curve

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

When I started at Strongminds I knew a lot about programming already. Of course I did not know everything, I had to use programming languages that I had not used before, integrate with technologies I did not know much about and learn new principals and methods. While a lot of this was challenging, it built on top of my existing knowledge and skills that I already had, so it was manageble to incrementally learn new stuff in these areas.

However, there were stuff that I had next to no previous experience with, which made it much more difficult initially. When you are doing software development, there are a lot more things to think about than just the technical aspect of writing the code.

First of all, you need to figure out what the code is actually supposed to do. In other words, you need to figure out the needs of the customer, that you are writing the software for. One of the problems with that is that there is a high likelihood that you might not understand each other very well. The customer might not be very familiar with technical language and software concepts while you might not be very familiar with the domain of the customer. This can quickly lead to misunderstandings, and if it is not addressed in some way, it will ultimately result in a software system that does not adequately solve the problem that the customer needs solved.

A solution to this problem, can be applying the concept of Domain-Driven Design (DDD).

Photo by Danist Soh on Unsplash

What is Domain-Driven Design?

Domain-Driven Design was a concept first introduced by Eric Evans in his 2003 book of the same name.

As the name implies, it is all about understanding the domain of the problem that you are writing code to solve. In order to get this understanding of the domain, you need to speak with someone who understands the domain very well – a so called domain expert. However, it is not enough to just gain knowledge of the domain, you also need to make some kind of abstraction of the domain in order to put the knowledge into system and deal with the complexity of the domain. This abstraction is called a domain model, and is used as the basis for designing the system that you need to build. The domain model needs to be expressed in some way, and it can both be through written descriptions, diagrams or even a combination of the two.

One of the problems when building a domain model in collaboration with domain experts is the communication barrier. It is crucial to use the same language when exchanging knowledge and building the model, but as it is often neither feasible to use the languge of the developers, nor the languge of the domain experts, something else is needed. This other language should be rooted in the model as that is the common ground. It is not too important how exactly this languge is, some terms could be taken from the domain others from the developers’ language or from some other place depending on what makes the most sense in the given context. The important thing is that everyone agrees on what terms to use and what those terms mean. In order for this to effectively break down the communication barrier, it is important that this commen language is used everywhere that the team communicates. Because of this, it is called the Ubiquitous Language.

Let me give you an example from the real world, that shows the kind of misunderstandings that can happen if different groups working together are not using a common language:

The example revolves around the process of restarting a computer. You could also call that a reboot or a power cycle. For some people and in some contexts all these terms might describe the exact same process, while in other contexts they might be describing similar but substantially different processes. In the context of a Windows computer for instance, the term restart would normally refer to restarting the computer from within Windows, while a power cycle would normally describe cutting the power to the computer, waiting a bit, and then turning the power back on again. From a user standpoint this might seem like the same operation – the computer is turning off and then on again – but from a techinical standpoint there is a difference, and the two operations might not always result in the same outcome.

On a project that I worked on, we actually had an issue with some Windows computers, where a power cycle fixed a certain issue but a Windows restart did not. A combination of miscommunication and a lack of understanding of the exact nature of the problem, resulted in us developing a solution for easily performing a Windows restart of specific computers through our software. But as this new “fix” we had made did not solve the real issue, it just ended up causing more problems and was disabled again shortly after. Some of this could probably have been avoided if everyone had used the same ubiquitous language, and thus had the same understanding of what “restart” and “power cycle” meant.

This underlines the importance of having and using a ubiquitous language. If you try to fix a problem that is not completly understood and also described using a common language that everyone involved understands, then an outcome like the one described above has a high likelihood of happening.

DDD example

Now you might think that all of this sounds very good, but how do you actually do it in reality? At least that was what I wondered when I was starting out. DDD does not provide any hard and fast rules on how exactly to build a model. This does indeed make it more difficult to start building and expressing a model, when you don’t have much experience in doing so. On the other hand it has the advantage of giving you a lot of freedom when expressing a model, which makes it possible to capture just about any domain that you can think of. It also means that there is no “wrong” way of modelling a given domain or of expressing a model.

This, however, still leaves us with the problem of how you get started when you are not experienced. One thing that I think is very valuable in this case is to see examples. So in the following I will give an example of how you might model a domain and express that model through some diagrams.

Let’s imagine that we are working with a medium size flower store and need to build an internal system for them. In this case the domain experts are both the owner of the shop and the employees. Through our talks with them we figure out that one of the things the system needs to do, is to show the work schedule for the shop, which is currently only available in a paper version located in the backroom of the shop. In the first iteration of our model we will therefore have a schedule that contains the days on which the shop is open, with each day containing the employees that are working that day. This simple model could be expressed through the below diagram.

Here I have chosen some UML notation, as it is very descriptive and fairly widely known, while stile being somewhat understandable even if you don’t know the notation. You could also make diagrams using your own notation which you describe in a legend, or you might even get away with not using any special notation at all.

An alternative model could have a schedule that contains employees, each of which contains the days where they are working. None of these models would be wrong, but they represent different ways to look at the domain.

Through further conversation with the domain experts, we find out that the schedule is made on a weekly basis, and that an employee working on given day, does not necessarily work the entire day. In their current schedule each day is divided into multiple timeslots, which then have a number of employees assigned to it. This makes us add the concept of a week and a time slot to the model. We also find out that the owner herself is also part of the work schedule. With this information we could add the concept of an owner to the model, but as we currently do not seem to need the distinction between owner and employee, we insted change the concept of an employee to a staff member to also cover the owner in this category. With these changes to the model we can also update our diagram.

As the next step, we discuss how the work schedule is made and changed. It turns out that either the owner or some employees with special rights creates the schedule, while all changes to the existing schedule must go through the owner. To incorporate this into our model, we can add the notion of a role that a staff member can have, and a set of rights that can be associated with a role. This causes another change to our diagram.

Next up

This concludes the first article in the series on Domain-Driven Design. In the next article I will dive into some of the central concepts of DDD like entities, bounded contexts, repositories and more.