In our last book club meeting, we revisited Chapter 7 of Eric Evans’ Domain-Driven Design and tried to create a checklist for turning a domain-model into an object-oriented design. This is what we came up with.
0. The model is given, not done from scratch. This is the starting point of our checklist. The analysis, the conversations with domain experts leading to this model have already been done at the earlier design stages (and in the earlier chapters of the book).
1. Prune class relationships. Get rid of unnecessary relationships, especially many-to-many.
2. Identify applications — users of the domain model. In a shipping domain model, examples of such applications are a booking application or a tracking query for cargo. Remember that the application and the domain model live in different layers of the layered architecture.
3. Distinguish between entities and value objects. Enough said.
4. Design associationsbetween entities and value objects. Figure out directionality. For example, value objects shouldn’t reference their owners.
5. Figure out aggregate boundaries. Think not what to include in an aggregate, instead, look for reasons to exclude it. If someone wants to look up Y without X that owns it, then Y doesn’t belong in the aggregate where X is root.
6. Select repositories. Limit consideration to the roots of aggregates. If you are implementing an association between two classes as a collection, you don’t need a repository; if you are implementing it as a query, then you need a repository.
7. Walk through scenarios. Remember there is no penalty for throwing away a value object, even a complicated one. Think about associations and what happens to them when your model objects change, especially in aggregates.
8. Design object creation. Decide where to use constructors, what to pass to those constructors, where to use design patterns such as Abstract Factory, Factory Method and Prototype. Make sure you create valid objects that fulfill their invariants and create associations when they’re required.
9. Refactor. Note that we’re talking about refactoring the design, not the code that implements it. There is no general rule on how to do it. The only example in the book shows a refactoring move driven by a performance requirement. An important takeaway is that you need excellent model documentation in addition to its diagram! Otherwise, it may be impossible to tell why you did a particular refactoring move.
10. Think about modularity. The model may be large enough to divide it into several modules. In the shipping model example, such modules could be shipping, billing, and customer contact.