Design Complex Software Systems w/ Domain Driven Design (DDD)

ömer erakman
7 min readOct 27, 2020

While designing a software project, some software engineers tend to put more focus on shiny technologies, technical details and UML’s at the beginning of the project. If you start designing a complex software system with those technicalities, then you will be in trouble as the project grows. Software systems change and evolve in time. The design of the software should allow these changes to be applied in acceptable period of time. To be able to make a design that can respond to changes, the domain should be understood first. DDD focuses on the domain instead of the technical details of the project and allows the software to adapt to changes.

If the developer team does not have good understanding of the domain, they may develop a working software (mostly not in time) but the software will have unnecessary complexity and lots of wrong design issues. These design issues will pile up to the point that it may end up with rewriting the whole or some parts of the solution. This is what DDD aims to prevent.

In today’s world, most projects have at least one product owner or analyst and these people are not usually domain experts. Yet they analyze needs and try to generate requirements for other teams members. It is like a chinese whispers game. The valuable information may be lost, changed or transformed during the transformation of information from top to bottom. If developers/ architects cannot get the information as it is, then it is challenging to come up with a good design solution.

Talk to domain experts from start
Domain experts are the people who are in the business. They know the market, challenges, opportunities and for sure the domain. There are tons of things to learn from domain experts that can assist the development team during development, analysis or project management team. In DDD, working with domain experts is critical. Some may hesitate to talk to domain experts/ customers because they tell us more than we plan to build. But it is definitely worth the effort as it will help the team to come up with a better design for the project.

Use a Ubiquitous Language
In order to conduct an effective conversation, people should be talking to the same language. Usage of an ubiquitous language may be the most important thing with DDD. If you do not use ubiquitous language, then get ready to spend lots of enormous time just exchanging ideas with domain experts and teams.

Just to be clear, ubiquitous language is not the language of what developers talk to. It is the language of business and business does not have words like databases, interfaces or design patterns in its vocabulary.

Even though you achieve a common language among different parties, a word might still have different meanings in a software project which we will talk in details in the bounded context chapter.

Domain Types and implement strategies
Domain defines a company’s main activity. For Ferrari it is car. A domain consists of multiple sub domains. These sub domains exists to support the company’s core domain. In DDD analyzing the sub domains also plays an important to role to a successful design. Sub domains exist even before a project. You should identify what they are as the design strategy might also change according to type these subdomains. Some of the subdomain types are as follows:

Core sub domain:
Core sub domain is what your company invests in or what makes the company different or better than its competitors. It is the most complex problem you should solve so give it to your best developers.

Supporting sub domain:
Supporting sub domains are usually easier to implement and do not add much value as core sub domain to your solution. Frameworks or tools could be used implement these domains in house. One example of supporting domain can be a CRUD operation. It is also a good candidate for outsourcing.

Generic sub domain:
Generic sub domains are the already solved problems. Most of uses same techniques or algorithms. So you do not need to develop it in house. Just use an open source solution and adopt it to your needs or buy it from a third party company.

As the software systems evolve, also the sub domains change. Core sub domain may turn to a supporting domain, a supporting domain may change to a generic domain. Do not be afraid of these changes. Instead, try to adapt to it. For example, a supporting sub domain in which you developed an algorithm for a specific problem could become a generic sub domain when someone develops the same algorithm in a better way and open sources it. No need to wait for using that open sourced new algorithm.

What is a Bounded Context?
Let’s assume we have already defined a ubiquitous language. To manage the complexity of the system we divide the language to smaller separate languages. We may also define the bounded context as dividing a sub domain into smaller parts in which these parts have significant boundaries. Defining the bounded context is a complicated job. If you are using DDD for the first time, then you may make mistakes while designing bounded contexts. Increasing the knowledge of the domain always helps to apply DDD in practice.

Sometimes bounded contexts and sub domains are mixed up. Main difference between these two subject is that sub domains already exist in the business and we just identify them. On the other hand, bounded contexts are designed by us.

Ubiquitous languages are defined for bounded contexts. Words might have multiple meanings within different bounded contexts. For example the word “letter” may have different meanings depending on the context.

A bounded context should be assigned to only one team but one team may be responsible of multiple bounded contexts.

Until here we discussed about strategic design (ubiquitous language, sub domains and bounded contexts) with DDD. Now it is time to get into tactical design with aggregates and domain events.

Aggregate

We talked about bounded contexts. It is time to go in detail what a bounded context contains. Aggregate is a collection of objects that are bound together by a root entity. This root entity is also known as “aggregate root”. An aggregate is a composition of entities and value objects. Entities have unique identifiers but value object are defined by their values.

An aggregate has a transaction boundary. An aggregate and its entities can be updated through its aggregate root. This is a business boundary. The business use case defines that boundary.

Aggregates best practices:

  • Define aggregate and its transactional boundary with business use cases.
  • Design small aggregates.
  • Reference other aggregates with just unique identifier.
  • Update other aggregates with eventual consistency.

Is this model small enough?
There is not an exact number to tell if the model is big or small. It depends on domain. If you are unsure about whether the aggregate is small enough, do not force yourself to break it down into smaller pieces. It may be a sign of lack of knowledge about the domain. With the deadline pressure, people can make wrong decisions but it is usually better to start with bigger models and split the model later when you have more knowledge of the domain. Without enough knowledge, dividing the model more than it should be will bring you new problems and unnecessary complexities.

Domain Event

A domain event is a message that describes an occurrence of a significant event, it occurs in a bounded context. There are domain event that produced by aggregates and also there are subscribers them. For example OrderCreated event is generated from Order aggregate and it might be consumed by Shipping aggregate. That event should not be consumed by just other aggregates. Another system can also consume it.

Modelling Dept
Technical dept is the rework caused by choosing an easy solution instead of a better design or approach. In DDD terminology, we can talk about modelling dept. If we design a wrong software model then we will pay the cost in the future. Since the domain model sits in the center of a software system, a wrong model will affect almost everything.

If you design a wrong model, then you may find yourself solving different problems than the actual problem. If you step back and reevaluate your model you will realize that you are solving some problems that you created which are not real business problems.

DDD & Agile
Agile methodologies and DDD are around for some years. Agile encourages communication with customer like it is in DDD with domain experts. With agile methodologies user stories are used rather than generated requirements. User stories are written in business language. In most ways agile and DDD support the same concepts:

CONCLUSION
DDD focuses on domain. Domain is the most important aspect that will help you design the software. It does not matter if you use agile methodologies or waterfall, talking to domain experts and understanding the domain may bring success.

What is next?
Next story will be about DDD and Microservices…

--

--