I'm too young to talk about Domain Driven Design, and This article is about what I've learned from Domain-driven design by reading the resources that you can see at the end of this article.
- What is DDD?
- Why DDD ??
- Domain Model and Subdomain
- Ubiquitous language
- Value Object
- Aggregate and Aggregate Root
- Context And Bounded Context
- Domain Service
- Domain Event
- Persistence Ignorance
- Application Service
- Infrastructure Services
- Context Map
- What is the relationship between DDD and agile??
Software design is an art, like building and like any art there are rules should be followed. Domain Driven Design is a software development approach defined by Eric Evans in his famous book. software should be designed at the first place and It is not a good idea to sit down and start coding, coding is the easy part of developing. business requirements nowadays are huge and it's impossible to create a complex software by accident, we can Not just write code and create the product, software should be designed by specifications and tested over and over to create a successful application.
What is DDD?
Domain Driven design forces the developers to know the problem and then break the difficulties into simple steps and then start coding. Gathering a small part of a system to finally build the whole, DDD focuses on understanding and analyzing the solution first. DDD is a combination of design and development. DDD combines the design and development and it is an approach for large-scale and more complex applications And should not be applied in every application. DDD is all about thinking, analyzing, Modeling and developing the application. It focuses on overcoming to complexities in Domain and converting them to a Model. DDD is much more about the process than it is the code. There is no Database in DDD because it's about Designing Domain NOT database, it's most important focus is on Domain and database doesn't matter in it.
"What I love most about DDD is that it’s not an inhibitive methodology or framework; It's a collaboration philosophy focused on delivery." ~@ScottMillett
Why DDD ??
You should choose DDD when your domain is complex enough. DDD makes the domain complexity simple enough to understand by everyone. Rather than DDD advises about team working and agility, it forces team and domain expert to talk in a specific language called "Ubiquitous language", and a kind of relation between developers and domain expert exists in developing process. Because of solving the complexities in the domain, it forces you to know the business at first. I have to mention again that, DDD is just for some special kinds of application, Not for all.
Domain Model and Subdomain
Domain Model is in the center of the domain driven design. A model should represent knowledge of the business and language that your team speaks. Usually, domain got big changes in developing process Domain model codes should be clear enough that everybody should learn by reading without any knowledge about that. You can divide a large Model to several subdomains and also Multiple models could be in a subdomain. A model should be small enough to assign to a teamwork. "There is no best of perfect model design, it is only about efficiency for the current solution." you do Not need to inject anything into your domain entities, Domain should be POCO and pure objects.
Ubiquitous language (UL)
Ubiquitous language is a common and shared language between domain expert and software specialist or development team. A Ubiquitous language connects all part of the design team and Domain model is completely based on ubiquitous language. every change in this Ubiquitous language would be a change in the model. UL is a convention built on the Model and it could be a writing, speech, phrases, and Diagram and it could be shown in namespaces, classes, methods, properties or every part of the Model.
An entity is an object that has both entities and attributes that its attribute is mutable because it's known by Identity. Entity represents by its identity and it is unique within the system. there is more example for Identity such as products or orders in a shopping system. It is better to create the entities of the model first and specify the aggregate root.
Creating every object in Model as an entity comes with a cost and every instance of entity should have a unique identity. It is not all about what object it is, sometimes it's needed to know what attribute an object has. The value object is determined by its attribute, the most common example for value object is Money, an identity of money is not important but its value is important. a value object is an object that describes a certain aspect of a domain, it should be created by a constructor and never be modified during the lifetime because it must be immutable. So If you want to change a value object you should replace the object with a new one .it is a shareable object and Identity means nothing to it. two value objects are equal if all their fields are equal. Value Object also required to an entity Despite it has no any Identity, in another word you can't have a value Object in an aggregate without any entity defined. Making a wrong decision on choosing an object as an entity or value object could be too dangerous for a system.
Aggregate and Aggregate Root
A collaboration of entity and value object and overall group of the associated object in a system to represent a context is aggregate. Each aggregate has one root(aggregate root) which is an entity and it is the only accessible object in the aggregate from outside.
"Aggregate is a pattern in Domain-Driven Design. A DDD aggregate is a cluster of domain objects that can be treated as a single unit." ~Matin Fowler
Aggregate root is the main point of aggregate. And without aggregate root, aggregate doesn't mean anything. Entities and value objects of an aggregate hold the reference of the aggregate root, so if an aggregate root is removed, all the objects in the aggregate will be removed. Only aggregate root is retrievable from a database and other objects that holding the reference of the aggregate root will be retrieved in the querying process. For example, to querying a value object from the database, you should tell the repository to retrieve the related aggregate root which contains the value object. You can see the diagram of an e-commerce application aggregates in the picture below discussed in Scott Millett's book.
aggregate root has the behavior of aggregate and Aggregate Roots Combine Entities and Any references from outside the aggregate should only go to the aggregate root.
Context And Bounded Context
Each model is a collection of entities and value objects and overall they define a context, this context should be easy to understand and fluent and no more complexity with its name and real context, in another way it should be divided to another context. we can use the terms Context and Bounded Context interchangeably! Suppose a big application that has many different fields of business, for example, an application that has a Shopping center and social media, Every one of these parts could be a bounded context in this application. a Bounded Context is an area of your application, Each of these areas within the application has their own Ubiquitous Language, their own Model, and a way to talk to other Bounded Contexts to obtain the information they need. Every bounded context should have a name which should be part of the ubiquitous language. A bounded context is about separating different context in very large enterprise application because they can't combined or mixed together although it is not so easy task. A bounded context can cover more than one subdomain. Bounded context works with each other and they are in communication to create the product. each Bounded Context should be independent of any other Bounded Context. A bounded context is not a module at all, it is something more than a module, it is frame and group of models, Module used to collaborate or organize a model but a bounded context surrounds modules.
CRUD operations, Persisting and retrieving of every aggregate should be done by a repository, in other words for every aggregate you should have a repository. Repository Is Not A Data Access Layer because repository exists for every aggregate root, not for every data. You can name your repository based on your aggregate root. you can inject Repositories into your Services, it means you can have some specific method rather than CRUD in your Repository for an aggregate accessible by services.
In large and complex applications as Models are so big or maybe grow bigger in the developing process, for making model understandable and readable it is better to separate model in different parts called "Module" , in the simplest form it could be a folder in a class library. You can preserve this modularity from Model to Presentation layer.
Domain service is a way of dealing with entities and value object in the domain, it could be created for every aggregate root. When concepts of the model would distort any Entity or Value Object, a Service is appropriate. Domain service is a part of a domain model and should be part of a ubiquitous language. Domain service doesn't contain any CRUD operation, it just represents the behavior that has no Identity or sate. Eric Evans lists good service characteristics in his book:
- The operation relates to a domain concept that is not a natural part of an Entity or Value Object
- The interface is defined in terms of other elements in the domain model
- The operation is stateless
A domain event is just a simple POCO that represents an interesting occurrence in the domain, it's a part that accepts messages from clients and calls methods on the domain model. There are handlers in another independent part (in a separate layer such as infrastructure) which handle events of the domain. And These domain events are a part of the ubiquitous language and should be represented explicitly.
Persistence ignorance separates the concern of the persistence and communication from a domain model. It's all about loose coupling to make the code testable and maintainable. It says we should try and keep our code free of anything that refers to, relates to, or propagates, aspects of the mechanism we intend to use for persisting our data. With persistence ignorance, we try and eliminate all knowledge from our business objects of how, where, why or even if they will be stored somewhere.
Application service calls into the domain service and contains security, logging and etc. Application service should not be created for every operation, it should be created for important concepts of the domain. Business rules are not allowed in an Application Service, those belong to the Domain layer. Application Services will typically use both Domain Services and Repositories to deal with external requests. As I said before application service could use some specific method of repository rather than CRUD operations.
Infrastructure Services Used to abstract technical concerns. infrastructural services are different from Domain services because domain services embed and operate upon domain concepts and are part of the ubiquitous language where Infrastructural services are focused some requirements of the application such as file system access, database access, email, etc. Infrastructure Services live in the infrastructure layer.
A context map is a document which outlines the different bounded context and relationship between them, it could be a text or diagram. The context map is Guide to other members of the team in another bounded context to have a whole view of the context.
What is the relationship between DDD and agile??
Because of different kinds of communication and relationship defined in DDD, it is so useful for agile teams. In agile manifesto website you can see :
- Individuals and interactions over processes and tools
- Working software over comprehensive documentation
- Customer collaboration over contract negotiation
- Responding to change over following a plan
As you saw above, interaction over processing, documenting, being in contact with the customer(or domain expert in DDD via UL) and changeability of DDD application during development process are the main aspects of DDD.
- Domain Driven Design By Eric Evans http://www.amazon.com/Domain-Driven-Design-Tackling-Complexity-Software/dp/0321125215
- Practicing Domain Driven Design By Scott Millett https://leanpub.com/Practicing-DDD
- Domain Driven Design Quickly http://www.infoq.com/minibooks/domain-driven-design-quickly