alias: Lean Software Development, Simplicity-Driven Development, Essentialism in Software, Agile Minimalism
- premature abstraction
- YAGNI (You Aren't Gonna Need It): Avoid adding layers of abstraction for features or flexibility you might need in the future but are not required at present.
- KISS (Keep It Simple, Stupid): Favor simple solutions over complex abstractions unless complexity is warranted.
- Refactor Only as Needed: Start with simple, direct solutions and refactor to increase abstraction and flexibility only when changes or new requirements justify it.
- Concrete Before Abstract: Implement functionality concretely before creating abstractions to ensure they are necessary and useful.
- Avoid Over-Engineering: Do not build complex architectures or design patterns unless the problem demands them.
- Prefer Composition Over Inheritance: Use composition to achieve functionality sharing instead of using inheritance, which might introduce unnecessary abstraction.
- Stay Close to the Domain: Align your implementation closely with the domain model initially to avoid abstract structures that don't map well to the problem space.
- Understand Before Generalizing: Ensure a deep understanding of the problem domain before attempting to abstract or generalize code.
- Layer Only When Layers Have Clear Interfaces: Add layers of abstraction only when they serve a clear purpose and have well-defined interfaces to prevent "spaghetti architecture."
- Localize Abstractions: Keep abstractions local to their context until it's clear they need to be elevated or exposed to wider areas of the codebase to avoid unnecessary global complexity.
- Optimize for the Common Case: Focus on handling common scenarios simply; introduce abstraction only when uncommon cases become frequent enough to require ease of maintenance.
- Consolidate Similar Abstractions: Regularly audit code for similar abstractions that can be merged, preventing fractionalized abstractions that add needless complexity.
- Traceability of Abstraction: Ensure each abstraction layer provides traceability to specific requirements or challenges it addresses, making it justifiable and purposeful.
- Prototype to Discover Patterns: Use prototyping as a tool to experiment and identify recurring patterns naturally rather than imposing abstraction prematurely.
- Favor Readability Over DRY in Early Stages: In initial development phases, prioritize readable and understandable code over strict adherence to "Don't Repeat Yourself" if the abstraction would obscure intent.
- Maintain Conceptual Integrity: Ensure each abstraction serves the core concept of the software, rather than creating one-off layers that do not contribute to the product's primary purpose.
- Abstract Based on Real Constraints: Identify true constraints or limitations before abstracting, ensuring that abstraction serves practical needs rather than hypothetical scenarios.
- Manage Abstraction via Depth Control: Focus on controlling the depth of abstraction levels, ensuring clarity and coherence while avoiding deeply nested abstractions that complicate understanding and maintenance.
- Encapsulation with Transparency: Design abstractions to encapsulate complexity but maintain transparency to avoid unnecessary opacity, aiding in comprehension and debugging.
- Evolve Abstractions from Common Use Cases: Allow abstractions to emerge naturally from handling common use cases efficiently before making them a part of the initial design.
- Simplify State Management: Minimize abstraction in state management by keeping state transitions explicit and reducing unnecessary layers of indirection.
- Experiment with Concrete Implementations First: Test ideas with concrete, straightforward solutions to uncover real-world constraints or repeated patterns that may warrant abstraction.
- Isolate Complexity: If complexity is unavoidable, isolate it within a well-defined module rather than spreading abstraction across multiple components.
- Prioritize Domain-Specific Solutions Over General-Purpose Abstractions: Lean towards solutions tailored to the specific domain constraints, resisting the urge to create reusable abstractions prematurely.
- Feedback-Driven Abstraction: Use feedback loops from peers or users to determine when an abstraction is beneficial, rather than assuming its necessity from the outset.