Domain-Driven Design - tl;dr
After hearing about Aggregates and Bounded Contexts over, and over again, I decided to check out what Domain-Driven Design is all about. There is a ton of DDD resources on the Internet, but this blog post is for my personal reference. I am publishing it so I can google it, and maybe you find it useful as well. This post is about what DDD is, and how it can help you to write better code.
What is DDD?
According to Wikipedia:
Domain-driven design (DDD) is an approach to software development for complex needs by connecting the implementation to an evolving model. The premise of domain-driven design is the following:
- placing the project's primary focus on the core domain and domain logic;
- basing complex designs on a model of the domain;
- initiating a creative collaboration between technical and domain experts to iteratively refine a conceptual model that addresses particular domain problems.
More pragmatic (and ignorant) definition: DDD is software development approach that focus on business processes over implementation details. This allows developers to work with business people more effectively. It also makes code more maintainable and extendable.
Most important DDD terms (buzzwords):
- Ubiquitous Language - using business terms for naming classes, methods and variables
- Domain - functionality of the system
- Bounded Context - components used to deliver a functionality (AKA domains)
- Value Object - simple, immutable class representing some business term
- Entity - class with unique identifier, usually used to represent persistent data
- Aggregate - group of entities
- Repository - class used to save and retrieve aggregate (AKA save/retrieve data to/from database)
- Application Service - your Domain(s) communication layer
- Anti-corruption layer - layer for interaction with external (or legacy) system
- CQRS (Command Query Responsibility Segregation) - separates querying for data from modifying data
- Event Sourcing - storing changes to application state as a list of events, which allows to invoke and process events in producer/consumer fashion
Resources to learn about Domain-Driven Design
There are two DDD bibles: Blue Book and Red Book. I've been told to do not read Blue Book as first introduction to DDD, because it's very "heavy" and hard to understand. People were right. I would also add: it's not very well written (shoot me for criticizing DDD God AKA Eric Evans).
List of recommended resources, sorted in order that I would recommend to follow if you are new to DDD. I strongly recommend positions in bold!
- Domain Driven Design Fundamentals (Pluralsight) - this will give you an idea what DDD is, perfect to watch during short flight in 2x speed
- Domain-Driven Design Distilled (Vaughn Vernon) - overview of key ideas from Blue Book, this will help you to put all, high-level pieces together
- Domain Driven Design Quickly (thanks Michal Franc) - similar to DDD Distilled, but use even more systematic approach to outline DDD concepts
- Domain-Driven Design in Practice (Pluralsight) - this course shows how to actually use DDD in a project; course author Vladimir Khorikov has a blog Enterprise Craftsmanship, which is very good source of DDD and general Software Development knowledge
- Domain-Driven Design: Working with Legacy Projects (Pluralsight) - another course from Vladimir Khorikov that is a nice demonstration of transforming legacy projects into DDD-friendly architecture
- Implementing DDD "Red Book" (Vaughn Vernon) - comprehensive overview of DDD
- Domain-Driven Design "Blue Book" (Eric Evans) - the Bible of DDD, use it as a reference rather than reading from back to back
Notice that I placed Blue Book at the end. It's hard to absorb. It also suffers from low knowledge/pages ratio.
There is also Domain-Driven Design path on Pluralsight that has nice set of courses around DDD and software design.
My thoughts on DDD
Before diving into DDD I was expecting to learn about something new and revolutionary. After reading about Ubiquitous Language, Aggregates and Bounded Context I still didn't see much difference between DDD and good, SOLID software design. It feels like DDD is mostly about good object-oriented design presented in particular, formalized way with specific buzzwords (aggregate, bounded context, etc.). In Uncle Bob's Agile Principles, Patterns, and Practices in C#, there is the Payroll Case Study example that is following clean code, good design and implementation practices. If you were put that example into DDD book...it would fit. If you take examples from DDD books and put it into Uncle Bob's book...it would fit fine as well.
There are however, some new concepts introduced by DDD. Such as Repository pattern, CQRS or Event Sourcing. Are last two actually DDD? Or they are just related to DDD?
DDD is also enforcing designing system around business domain, not around, e.g. database. That is usually a case when designing architecture from scratch quickly. As 99% of apps are CRUDs, ending up with database driven architectures would be natural. You usually start with file->new project, and go from there. This is not a problem for small apps, but might strike later when evolving the app. DDD solves that problem.
If you are familiar with Clean Code and SOLID design as presented in Agile Principles, Patterns, and Practices in C# then DDD does not bring much new concepts to the table. It may make you think more from a business perspective, and consider using new patterns (Repository pattern, CQRS or Event Sourcing) though.
It's worth to notice that even if you look at Domain-Driven Design path on Pluralsight, there are non-DDD courses about good/clean design as part of the path. Thus, good design is prerequisite of DDD. On top of that we have mentioned earlier buzzwords, CQRS and Event Sourcing.
Going back to DDD terms (AKA buzzwords), they could be also summarized as follows:
- Ubiquitous Language - use meaningful names for classes, methods and variables
- Domain - be aware what problem you are solving
- Bounded Context - group objects that depends on each other
- Value Object - simple, immutable class
- Entity - class with unique identifier, usually used to represent persistent data
- Aggregate - group of related entities
- Repository - facade over your persistence layer to make it implementation agnostic
- Application Service - your system's API
- Anti-corruption layer - layer for interaction with external system
- CQRS (Command Query Responsibility Segregation) - separates querying for data and modifying data
- Event Sourcing - storing changes to application state as a list of events, which allows to invoke and process events in producer/consumer fashion
What DDD enforces from the beginning is layered architecture that may not always be needed. Should you follow DDD in your projects? The answer is, as always, "it depends". There are some good ideas there, but being over obsessed with favoring DDD in your design decisions over pragmatism will lead to over-engineering.
After TDD and BDD there is DDD. Should you use DDD in all your projects? No. It's just a way to design software. Also: using DDD does not mean that you need to use all patterns from Blue Book and Red Book.
It seems like DDD should definitely help in long term, but over-engineering (with CQRS and Event Sourcing) may unnecessary complicate things. Actually, I should say: writing SOLID code would help you...and here we are again: is DDD really something different than just good software design?