This article is about domain-driven design, key concepts, vocabulary, and general ideas. I was motivated to write this article while attending the SymfonyWorld 2020 conference. Neal Brooks had an inspiring lecture “The absolute beginner’s guide to Domain Driven Design with Symfony”.
You can use the Table of Contents to get a quick overview of this article and easily navigate to a part you are interested in.
What is Domain Driven Design?
Firstly, when we ask what is Domain Driven Design we actually want to understand the concept of Domain-Driven design. It is an approach to understanding a problem, designing it, and coding it at the end. It results in better, more testable, and maintainable code.
Secondly, understanding what is domain-driven design will help you communicate with your entire team on a different level. Through this improved communication you will become a better developer, leader, or key stakeholder.
Finally, it is important to understand that this is not the only possible approach and it is not the single source of truth. However, if you do not know about it, you can not compare it with the others.
If we want to understand domain driven design, it is important to understand the definitions and the vocabulary.
Domain Driven Design
Domain-Driven Design is an approach to understanding the business in order to represent it in software, and also an architectural pattern for simplifying the business.
If you are interested in Domain-Driven Design there are lots of good books about it. My suggestion would be Domain-Driven Design: Tackling Complexity in the Heart of Software or something more practical Implementing Domain-Driven Design
The domain is a company that we are creating software for. It is what our customers are doing. This is what we want and what we need to understand.
Domain experts are people who will use our software and have experience in that area. They are people with relevant experience. This experience is important for software developers because they probably won’t have it.
Firstly, remember, making software is not about writing code. It is about building tools to help in doing some work. Because if we don’t know what kind of work is someone doing, we can not make a good tool.
Ubiquitous Language is how people communicate in a specific group. It is how people use language in that domain. We want to use this vocabulary when we build software, to keep it consistent.
For example, we might say ‘User’ while some other team says ‘Customer’. Furthermore, part of the team might use the term ‘Property’ while other parts of the company might say ‘Instruction’ for the very same thing.
Bounded Contexts are different meanings in form of different contexts. It is a logical boundary around some behavior within the business.
A DDD Entity (DDDE) is a class that has some sort of identity-making in unique from other identical objects.
Aggregate is a collection of objects that represent one concept in the domain. For example, a car is an aggregate of many different objects (design, motor, sales value, etc.).
The Aggregate root
The aggregate root is the entry-point into the specific aggregate.
Invariants are business rules that the domain is enforcing. They are separate from application-level rules.
Domain services hold domain logic whereas application services don’t.
Application services orchestrate the execution of domain logic according to outside-world input but don’t contain any domain logic themselves.
There are four layers of DDD architecture: domain/model; infrastructure (code, classes); application (application services), and UI (only talks with the application layer and does not know about domain or infrastructure).
Firstly, it is important to work with domain experts to discover different rules and hidden requirements. Secondly, think about words and communication between teams and business. Furthermore, if possible, identify bounded contexts as early as possible.
Finally, start talking about business processes and invariant with all stakeholders. However, understand that there is no genially the “right way” of doing things. Domain-driven design is about understanding the problem and using that understanding to make concuss and reasonable decisions.
The complete code example is available on GitHub https://github.com/nealio82/absolute-beginners-guide-to-ddd-with-symfony
Note: There was a discussion during the presentation. Based on comments most of the discussion was in the directions: “is DDD too abstract”, “too many classes or does it even matter”, “are their performance concerns”, “how to document DDD properly”.