Software Design¶
Tier: 2 (Architectural Judgment)
Concepts: 14
Durability: Durable (Principles address essential complexity of managing change, coupling, and coherent behavior in software systems; concepts survived OOP, functional, and multi-paradigm transitions)
Fundamental Tensions¶
| Tension | Description |
|---|---|
| Flexibility vs. Simplicity | Adding extension points increases future adaptability but introduces indirection and cognitive load. Cannot be eliminated because future requirements are unknown, yet every abstraction has a comprehension cost. |
| Abstraction vs. Indirection | Deep abstractions hide complexity but add layers that obscure understanding and debugging. The tension exists because abstraction requires indirection, yet too many layers create "lasagna code" as harmful as "spaghetti code." |
| YAGNI vs. Extensibility | Building for future needs risks over-engineering, but not building for them risks costly rewrites. Cannot be resolved because predicting which extensions will be needed requires knowledge we fundamentally lack at design time. |
| Inheritance vs. Composition | Inheritance enables code reuse through hierarchy but creates rigid coupling; composition enables flexibility but requires more explicit wiring. The tension persists because both are valid mechanisms with different cost profiles depending on domain stability. |
| Fail-Fast vs. Fault Tolerance | Detecting errors immediately aids debugging but may cause cascading failures; tolerating errors enables resilience but may hide bugs. Cannot be eliminated because error handling strategy depends on context and consequences that vary across system layers. |
Concepts¶
- Single Responsibility Principle
- Open/Closed Principle
- Liskov Substitution Principle
- Interface Segregation Principle
- Dependency Inversion Principle
- Composition Over Inheritance
- Information Hiding
- Deep vs. Shallow Modules
- Design Patterns as Named Solutions
- Law of Demeter (Principle of Least Knowledge)
- Command-Query Separation
- State Machines as Design Tool
- Fail-Fast Principle
- Dependency Injection as Inversion of Control
Cross-Domain Transfer Summary¶
| This Domain Concept | Transfers To |
|---|---|
| Single Responsibility | Software Architecture, API Design, Database Design |
| Open/Closed | Software Architecture, API Design, Testing Strategies |
| Liskov Substitution | Type Systems, API Design, Testing Strategies |
| Interface Segregation | API Design, Microservices, Testing Strategies |
| Dependency Inversion | Software Architecture, Testing Strategies, Plugin Systems |
| Composition Over Inheritance | Functional Programming, UI Frameworks, Microservices |
| Information Hiding | Software Architecture, API Design, Database Design |
| Deep vs. Shallow Modules | API Design, Library Design, Abstraction Layers |
| Design Patterns | Architecture Patterns, Integration Patterns, Concurrency Patterns |
| Law of Demeter | API Design, Microservices, Data Access |
| Command-Query Separation | CQRS Architecture, Functional Programming, API Design |
| State Machines | Protocol Design, Workflow Systems, UI State, Compilers |
| Fail-Fast | Distributed Systems, API Design, Testing, Databases |
| Dependency Injection | Testing Strategies, Software Architecture, Functional Programming |
Canonical Sources¶
| Source | Coverage |
|---|---|
| Gamma, Helm, Johnson, Vlissides, "Design Patterns" (1994) | Design patterns, composition over inheritance, foundational OO design |
| Martin, "Agile Software Development, Principles, Patterns, and Practices" (2002) | SOLID principles comprehensive treatment |
| Ousterhout, "A Philosophy of Software Design" (2018) | Deep vs. shallow modules, complexity management, modern design philosophy |
| Meyer, "Object-Oriented Software Construction" (1988, 1997) | Open/Closed principle, Design by Contract, Command-Query Separation |
| Parnas, "On the Criteria To Be Used in Decomposing Systems into Modules" (1972) | Information hiding, module decomposition criteria |
| Liskov & Wing, "A Behavioral Notion of Subtyping" (1994) | Formal treatment of substitutability |
| Hunt & Thomas, "The Pragmatic Programmer" (1999, 2019) | Practical design principles, fail-fast, DRY |
| Fowler, "Patterns of Enterprise Application Architecture" (2002) | Enterprise patterns, dependency injection concepts |
| Bloch, "Effective Java" (2001, 2008, 2017) | Composition over inheritance, practical design guidance |
| Constantine & Yourdon, "Structured Design" (1979) | Coupling and cohesion foundations |