There are tons of resources out there to make you a better engineer. But I have found few to help software engineers understand the trade-offs in actually choosing what's right for them.
Only after working on multiple projects you might learn the actually trade-offs from experience. As using any of these practices always comes with trade-offs, choosing what's right for your context I call Context(ual) driven development (CDD).
I documented a list below which hopefully helps you make a more balanced decision: ⬇️
(respond below with your suggestions and I will curate them and update this post)
Development
- Test-Driven Development (TDD): Overkill for trivial or rapidly prototyped features where requirements are highly volatile.
- Domain-Driven Design (DDD): Risk of significant overhead and over engineering especially smaller projects and new/unclear domains.
- Event-driven development: more complexity in debugging, tracing execution flow, and ensuring eventual consistency of data across service. (useful for decoupling domains and team in bigger projects)
- Object-Oriented Programming (OOP): Can introduce unnecessary complexity for simple, procedural tasks or data-heavy scripts. Can be more complex to test.
- Functional Programming (FP): less suitable for problems with inherently mutable state, complex (real world) objects or heavy I/O operations where performance is critical.
- Extreme Programming (XP) practices (Pair Programming, etc.): Can be disruptive to individual workflows and require significant team buy-in.
Testing
- Unit tests: A lot of overhead for new units of code with unstable interfaces. Refactoring code also means refactoring tests. Avoid when the unit is still unstable an relatively new and not your core business.
- Integration tests: Great middle-ground but not scalable, might test some unites of code over and over again and can quickly slowdown your CI pipeline.
- End-to-end tests: slow, does not provide quick feedback. should be added to deployment process when development is often breaking your business critical flows.
Process
- Code Reviews: Can become a bottleneck if not managed efficiently or if reviewers focus on opinions or style over substance.
- Static Code Analysis: Can generate excessive noise (false positives) if not configured carefully for the project's specific needs.
Code quality
- Design Patterns (e.g., Singleton, Factory): Can lead to over-engineering if applied without a clear, recurring problem to solve.
- Event Sourcing: Adds complexity to data storage and querying; not necessary for applications without complex audit trails or time travel requirements.
- Command Query Responsibility Segregation (CQRS): Adds complexity; unnecessary for applications with simple data access patterns.
- Bounded Context (DDD): Adds complexity for small or simple domains; Can lead to over-partitioning if not done carefully. Have at-least 1 engineering team per domain.
- SOLID Principles: Overly strict adherence can lead to over-engineering and overly complex class hierarchies for simple applications; requires careful judgment to balance design principles with practical needs.
- Caching: Adds complexity related to cache invalidation and data consistency; very bug-prone only introduce when absolutely necessary!
- Queueing: Adds complexity related to message delivery guarantees, message ordering, and handling failures; introduces latency and requires additional infrastructure.
Architecture/Infrastructure
- Microservices: Excessive overhead for small applications; introduces significant inter-service communication complexity.
- Serverless Computing (FaaS): Introduces vendor lock-in and can make debugging and local development more challenging; can be less cost-effective for long-running or consistently high-traffic applications.
- Micro Frontends: Adds complexity related to inter-application communication, state management, and deployment; can lead to performance issues if not implemented carefully.
- Backend for Frontend (BFF): Introduces code duplication and can complicate overall architecture if not carefully managed; adds maintenance overhead with multiple backend services to maintain.
Other
- Comprehensive Documentation: Can become outdated quickly if not actively maintained; excessive documentation can obscure important information and become a burden rather than a benefit.
All these paradigms are great! but I hope this helps you decide to sometimes not use them (in parts of your codebase).
⬇️ Please comment below your suggestions! ⬇️
Top comments (0)