Software Design
If architecture defines the big structural decisions, design fills in how the pieces actually work — how to model the domain, separate commands from queries, structure tests, and build code that bends instead of breaking when requirements change. This hub covers the core design methodologies: Domain-Driven Design, bounded contexts, CQRS, event sourcing, TDD, BDD, SOLID principles, and the anti-patterns that undermine good intentions. Practical tools for building systems that evolve over years, not just ship on a deadline.
Hub visual

Domain Modeling
The foundation. How to model your business domain in code so that the software reflects the actual problem space.
- What Is Software Design? — The anchor article. Design vs. architecture, the role of design in long-lived systems, and why design decisions compound over time.
- Domain-Driven Design Deep Dive — The most influential design methodology for complex systems. Ubiquitous language, entities, value objects, aggregates, repositories, domain services, and the strategic patterns that organize large systems.
- Bounded Contexts Explained — The most powerful and most misunderstood DDD concept. What bounded contexts are, how to identify them, how they relate to microservices, and the context mapping patterns that manage relationships between them.
Architectural Design Patterns
Patterns that sit at the boundary between architecture and design — they shape how your system processes and stores information.
- CQRS — Command Query Responsibility Segregation. Separate the write model from the read model. When it makes things simpler, when it makes things worse, and practical implementation with concrete examples.
- Event Sourcing — Store events, not state. Instead of updating a row, append an event that describes what happened. The benefits (complete audit trail, temporal queries, replay), the costs (eventual consistency, projection management), and when it's worth it.
Development Methodologies
How design emerges from the way you work.
- Test-Driven Development — Red → Green → Refactor. Write the test first, make it pass, clean it up. TDD isn't about testing — it's about design. How the test-first cycle forces you to think about interfaces before implementations.
- Behavior-Driven Development — BDD extends TDD by expressing tests in business language. Given/When/Then, specification by example, and how BDD bridges the gap between what stakeholders want and what developers build.
Design Principles & Anti-Patterns
The rules of thumb and the pitfalls.
- SOLID Principles Explained — The five principles that make object-oriented design maintainable: Single Responsibility, Open/Closed, Liskov Substitution, Interface Segregation, Dependency Inversion. What each means in practice, with concrete code examples.
- Anti-Patterns in Software Design — The patterns that look like good ideas but create problems: God Objects, Anemic Domain Models, Spaghetti Code, Golden Hammer, Premature Abstraction, and more. How to recognize and fix them.
- Designing for Change and Evolution — Software that can't change is software that dies. Practical principles for building systems that evolve gracefully: information hiding, dependency inversion, interface segregation, and the art of knowing where to add flexibility without over-engineering.
Where This Hub Connects
- Software Architecture — Architecture defines the big boundaries. Design fills in how the pieces work within those boundaries. Clean architecture, hexagonal architecture, and the other patterns in that hub set the stage for the design decisions covered here.
- AI Code Governance & Quality — Domain invariants and business rules (covered in the governance hub) emerge directly from the domain model. Good design makes governance enforceable.
- Context Engineering — AI agents need to understand design patterns to respect them. Structural and semantic context gives agents awareness of bounded contexts, aggregate boundaries, and domain rules.
- Engineering Best Practices — Design and process reinforce each other. TDD, code review, and testing strategies are practices that produce better design outcomes.
Suggested reading order
If you're reading this hub end to end, this sequence builds understanding progressively. Each article stands alone, but they are designed to compound.
10
Articles
~80 min
Total read
What Is Software Design? The Decisions That Shape Your Code
FoundationDesign is every deliberate choice you make about how code is structured, not what it does. Good design makes maintenance cheap, changes low-risk, and teams productive. Poor design costs you compounding velocity loss every single sprint.
Domain-Driven Design (DDD) Deep Dive: Building Software Around Your Business
FoundationDDD is the discipline of making your code speak the business language and reflect how your domain actually works. It's the antidote to codebases where the technology has completely obscured the business logic underneath.
Bounded Contexts: Drawing Lines That Matter
FoundationBounded contexts are clear lines around models where language and rules stay consistent. They're how you manage complexity in large systems, enabling teams to work independently and preventing the cognitive overload that kills big codebases.
CQRS: Separating Reads from Writes
Core patternsCQRS separates your write model from your read model because they're fundamentally different problems. It's powerful for complex domains where reads and writes have different patterns, but don't use it until you actually need it.
Event Sourcing: State from History
Core patternsEvent sourcing inverts traditional databases: instead of storing current state, you store every state change. It's powerful for auditability and temporal queries, but you pay for it in complexity. Use it only when the benefits outweigh the cost.
Test-Driven Development: Writing Tests First, Code Second
Core patternsTDD isn't a testing strategy—it's a design technique that forces you to think about how your code will be used before you write it. The red-green-refactor loop changes how you design, making testability and clarity natural outcomes.
Behavior-Driven Development: Bridging the Communication Gap
Applied practiceBDD bridges the gap between engineering and business by describing behavior in plain language before writing code. The Given-When-Then format creates shared understanding, but it's not a cure-all—use it where communication breakdowns cost you the most.
SOLID Principles: Five Rules for Better Code
Applied practiceSOLID principles prevent code from turning into an untouchable mess. They're not dogma—they're guidelines that solve real problems. Follow them where they matter, ignore them where they don't.
Anti-Patterns in Software Design: What NOT to Do
Applied practiceAnti-patterns are solutions that seem smart but create more problems than they solve. Recognize them early—God Objects, Anemic Models, Big Ball of Mud, Spaghetti Code—and you'll save yourself weeks of debugging and refactoring later.
Designing for Change and Evolution: Building Flexible Systems
Applied practiceBuild systems that bend instead of break when requirements change. The trick is designing for extensibility without building abstractions you don't need yet—watch for the pattern, then make it flexible.
Get Started with Bitloops.
Apply what you learn in these hubs to real AI-assisted delivery workflows with shared context, traceable reasoning, and architecture-aware engineering practices.
curl -sSL https://bitloops.com/install.sh | bashRelated articles
Clean Architecture: The Dependency Rule and Concentric Layers
Dependencies point inward: frameworks depend on business logic, not the reverse. Business rules know nothing of databases or web frameworks. Test logic without infrastructure. Swap databases without rewriting the domain. Concentric layers enforce this discipline.
Hexagonal Architecture: Ports and Adapters
Design your application first, then plug in external systems via ports. Swap a database adapter without rewriting core logic. Test without infrastructure. The hexagon's just a convention; the real power is inverting dependencies so external systems adapt to you.
Semantic Context for Codebases: Understanding Why Code Exists
Structural context tells you what code does. Semantic context tells you why it exists—the problem it solves, the trade-offs it makes, the patterns it follows. Agents without semantic context are pattern-matchers; with it, they're decision-makers.
Encoding Business Rules and Domain Invariants: Making Domain Knowledge Machine-Readable
Your domain has rules: order totals stay positive, emails stay unique, money doesn't disappear. Encode these as machine-readable invariants and agents can't violate them—even if they've never heard of them before.
Codebase Conventions and Standards
Consistent naming, file structure, and style reduce cognitive load. Automate conventions with linters and hooks so reviewers focus on logic, not formatting. One agreed-upon standard beats ten engineers doing it their own way.
How AI Changes the Software Lifecycle
Every SDLC phase changes with agents. Requirements become executable specs. Design becomes constraints. Implementation becomes agent-driven. Testing becomes validation. Maintenance becomes continuous refinement. Learn what each phase looks like in AI-native development.