curve

An Introduction to Domain-Driven Design (3/3)

This is the third and final article in my series on Domain-Driven Design. I will conclude the series with looking at a dynamic model, exploring refactoring in DDD and finally look back at the series as a whole.

Static vs. Dynamic Model

What we have seen so far, has all been examples of a static model. A static model shows the structure of the system, what components it consists of and how they relate to each other. It is useful for understanding the overall architecture and the relationships between different parts of the system.

However, we have not yet seen what the flow of the system is. For this we need a dynamic model, that shows the behavior of the system over time. It illustrates how different parts of the system interact with each other during the execution of a particular process or use case. A good way to illustrate a dynamic model is through sequence diagrams.

An example could be the owner of the flower shop making a change to the work schedule. The steps involved in this process might include:

  1. The owner logs into the system.
  2. The owner navigates to the existing schedule.
  3. The owner selects a specific day to modify.
  4. The owner changes one of the staff members assigned to that day.
  5. The owner saves the updated schedule.

A sequence diagram for this flow could look like the following:

A state diagram is another valuable tool for describing a model, especially when you need to track how an object changes over time. While the above sequence diagram is fairly simple and may not require a state diagram, in more complex cases – like a login flow – a state diagram can be very helpful.

To create one, start by identifying the object whose state changes are worth modeling. Next, look at the sequence diagram to find the events that trigger state changes for that object. From these events, determine the possible states the object can be in. In the state diagram, each state is represented by a box or circle, and transitions between states are shown as arrows, labeled with the events that trigger the change.

Refactoring

An important thing to remember when doing Domain-Driven Design is that the model is never set in stone. It should be evolved over time as we get more knowledgeable about the domain and as the requirements for the system evolve. Just as we continuously refactor our code, we should also continuously refactor our domain model. The iteration of the flower shop model is a very rudimentary example of this, but we can still use it to understand the overall process. The model starts out very shallow, and does not capture the actual domain very well, but through conversation with domain experts, we gain new insights and thus we adapt the model. As this keep happening, we iteratively make the model deeper and more nuanced in a way that better captures the domain. In reality this iterative process will happen over a long time, and will also continue after the software development has started.

When we make changes to the model after software development has started, it’s essential to reflect these changes in the codebase. Conversely, when making significant changes to the code, we must also update the model to ensure it accurately represents the current understanding of the domain. Significant code changes should ideally be driven by changes in the model, as the model is the foundation of the development process. But as the model won’t capture every implementation detail or minor behavior, these can be refactored independently without needing to alter the model. This dynamic interaction between the model and the code helps maintain consistency and alignment between the software and the evolving business domain.

Conclusion

Domain-Driven Design (DDD) provides an approach to software development that focuses on aligning the technical aspects of software with the business needs of the customer. By involving domain experts and creating a ubiquitous language and a shared understanding of the problem domain, DDD helps bridge the communication gap between developers and customers.

In our flower shop example, we demonstrated how DDD principles can be applied to model the work schedule system, and how a model can be expressed through diagrams. We saw how identifying entities, value objects, aggregates, and services can help structure the system in a way that reflects the real-world domain. Additionally, we illustrated the importance of using factories for object creation and repositories for data persistence, ensuring that business rules and consistency are maintained throughout the system.

Understanding the difference between static and dynamic models further helps in visualizing both the structure and behavior of the system. Using sequence diagrams, we can capture the flow of interactions, providing a clear picture of how different parts of the system work together to fulfill business requirements.

Incorporating DDD into your development process can be challenging at first, especially if you are new to the concepts. However, the benefits of creating a system that accurately models the business domain and addresses the customer’s needs will definitely be worthwhile in the long run.