Domain Driven Design has been around for many years now. There have been many discussions, hundreds of articles, presentations, various talks, millions of lines of code written to better understand, explore and make the most of it. And yet we are still exploring for the better and I believe that's the beauty of it.
What is it?
For me,it's a way of capturing, communicating and implementing the business logic when building a software and primarily empowering the domain to control its own destiny and logic when doing so.
There is lots in the DDD toolbox. There is philosophy behind it, there is terminology. There are lots of design patterns and modelling approaches to promote better collaboration between techies and domain experts. And there are lots of material. I mean lots.
DDD has gained popularity with the famous blue book "Domain Driven Design: tackling complexity in the heart of software" (2004), where Eric Evans discusses DDD as an approach to developing complex software. There is also a DDD Reference later published in 2015. The fundamentals of DDD have not changed but a lot has changed about how we built software, says the author and carries on with putting the model to work in which we
focus on the domain core domain.
explore the models in the core domain in collaboration with software and domain experts
speak the ubiquitous language within the same bounded context
Here is a below a list of patterns and their relationships from DDD Reference (2015) by Eric Evans.
and some definitions again by Eric Evans, from the same reference.
domain : sphere of knowledge and activity where the application logic revolves. The subject area to which the user applies a program is the domain of the software.
model : a system of abstractions that describes selected aspects of a domain and can be used to solve problems related to that domain.
ubiquitous language : a language structured around the domain model and used by all team members within a bounded context to connect all the activities of the team with the software.
context : the setting in which a word or statement appears that determines its meaning. Statements about a model can only be understood in a context.
bounded context : a description of a boundary, (typically a subsystem or the work of a particular team) within witch a particular model is defined and applicable.
layered architecture : software divided into cohesive layers where each layer is only dependant on the layer below and loosely coupled to the layer above. Domain logic is isolated and put into a layer where is it separate from infrastructure and application logic. This allows the domain model to be rich and cohesive enough to capture essential business knowledge.
entity : an object where it is distinguished by its identity, rather than its attributes. Simple class definition, responsible for tracking its state and rules regulating its lifecycle.
value object: no need to track the identity of every object, especially when only the attributes and the logic of the object is important to the software. Make the object immutable, make operations side effect free that do not depend on any mutable state.
aggregate: unit of consistency. Root entity andcluster of entities and value objects within a defined boundary. External objects hold references only to the root entity. Properties and invariants are defined for the aggregate as a whole.
domain events : events that domain experts care about. Immutable facts, where the state of an entity can be inferred.
services : when a significant process or transformation in the domain is not a natural responsibility of an entity or value object, add and operation to the model as a standalone interface declared as a service.
repositories: provide query access to the aggregates in the ubiquitous language. A service that creates the illusion of an in-memory collection of all objects of that aggregate's root type.
factories: Responsible for creating complex aggregates and structures so that the aggregate could be assembled consistently with entities and value objects enforcing its invariants. This way client code is not coupled to internal structure of the aggregate or the complex value objects.
Where to start?
Software development is one of most creative processes and it is always handy to let good patterns and principles guide the way, help us with decisions and communicate the code better. Although it's good to have many choices and different ways of building a better software, it's also as better to know when to use them on what and how.
I find the best way of exploring DDD is to have a high level understanding of its philosophy and terminology first, going through articles and then to look at the examples, see what others think, how it is applied to different domains and when it is applied. Even the author of the famous blue book finds it better to communicate it with an example.
Some good examples are;
https://github.com/ddd-by-examples/library : Super comprehensive from event storming to modelling and implementation backed by hexagonal architecture approach,usage of C4 language and even ArchUnit as a way to test the implementation against the architecture.
And give it a try. Share it, get it reviewed, discuss.
Why would I bother?
Of course, DDD is not the answer to everything. (That is 42, for sure!) But it is a big step towards better understanding and communicating business logic and implementing in a more collaborative and more manageable way. It may be one of the best toolbox if it works for the domain we are building.
Improved communication within the team
As a result of the usage of ubiquitous language, the langue that the domain experts use and it is reflected in the code and tests. No extra translation is required between technical terms and business terms when talking about business rules and how it is applied to the code.
Easier to review and track progress
Not just the people but also the software will be speaking the same language as the business, it becomes easier to track progress and to identify what's left. It also allows domain experts to be part of the of the SDLC, it becomes easier to spot miss-interpretations and catch potential bugs at an even earlier stage by reducing the wrong implementations in the first place.
Allows the team to focus on the business logic
Starting from the domain, understanding the business rules and logic first allows the team to keep focus on the actual core logic of the software. Technology becomes a facilitator for the domain but not the target.
Less duplication and more cohesion
The isolation of the business logic from the infrastructure and even the application logic forces a cohesive domain model. As a result the business logic is not scattered to the various layers of the software. It's implemented in the domain model and available for reuse instead of implementing the same business logic and rules in different parts of the software.
Don't overdue it in the beginning
It can be confusing to decide when and how to apply DDD, especially when it is a new concept among the team. We all want to do the right thing and do it perfectly. But as Eric Evans says, do not start with a perfect picture. Model it to the extend that it gives you a good start, helps you communicate better with domain experts and the rest of the team. Don't overdue it in the beginning.
Dumb-down domain layer
it could be the case you have a perfect layered application but with models which are merely data containers with no business logic. if you have a complex business logic but yet dumb data containers as model, then it is a smell that your business logic is probably scattered in your application, persistence and UI layers.
There are many problems with this approach:
long and expensive tests due to fact that the core business functionality requires full assembly of all layers.
unnecessary duplication of the code as the same rules could be implemented in different layers without being aware of each other.
inconsistent behaviour could occur due to different implementations in different layers.
difficult to change when there is a change in requirements. Similar changes will have to be reflected in all relevant layers.
it's a different way of modelling software. Different approach which requires more time spent with domain experts to understand the business domain and learn to speak the same ubiquitous language. Many projects suffer from not having that much time in the beginning of the project. There is also a huge tendency to implement business logic within application services, with the intention of reusable services. Some blames SOA, some claims this as miss-interpretation of SOA. Regardless, as more and more requirements are added with complex business logic then the services get fatter. The design once seemed clean and readable ends up complex, tangled, difficult to change with unnecessary duplication, difficult to test and far from the core domain.
DDD requires that initial investment on understanding the core domain. It also requires buy-in from the whole team which could be a new concept to many.