Practicing Domain Driven Design. Part 1: Understanding the problem.

Bogdan Melnychuk
6 min readJul 20, 2018

--

“Any fool can write code that a computer can understand. Good programmers write code that humans can understand.” Martin Fowler.

When building software, we often don’t think about how other people will understand our code later. Software is meant to be changed, and it’s very important that the source code terms can be connected to the business fluently. It should be easy for developers to understand, maintain and extend existing functionality according to new requirements. Fortunately, domain driven design (DDD) helps us solve this problem.

If you are a beginner in DDD and familiar with its terms and definitions, but you would like to see the practical side of it, you’ve come to the right place. The main goal of this article series is to go through a complete example of building a simple application using a DDD approach.

We will cover 3 important steps of building software:

  1. Understanding the problem (this article).
  2. Dividing the system into modules, define boundaries and dependencies between them (Part 2).
  3. Implementation: writing clean and maintainable code (Part 3).

We will start by defining the problem and collecting requirements. You will see that even what seems to be a simple problem at first requires a lot of decisions and understanding.

Problem definition

The problem we will try to solve is a simple version of trivia questions. You can find something similar at http://www.triviaquestionsnow.com or https://trivia.fyi. Basically, you have sets of questions grouped into categories by a common topic. The user can select a category and then answer questions which are validated by the system. You can use this app to learn interesting facts about various topics.

Understanding the problem

We have some really basic requirements. Is it enough to start with the implementation? I guess there are a lot of developers who are ready to jump into coding immediately. You can probably make guesses about possible names for classes and basic logic, but please don’t.

The information we have so far is very limited when you are the programmer whose job it is to create the software solution. It is extremely important to examine and analyze the actual requirements and then to plan how you will achieve the final development before you think of coding anything. It’s much cheaper to make changes during the planning phase than during the production phase. Here are possible risks:

  • Unnecessary refactoring if you did not cover all requirements.
  • Wasting time on over-engineering things that should be simple.
  • Without being aware of different edge cases and exceptions you will end up with an unstable system full of errors.
  • “Temporary” workarounds (that will stay forever) just to make the functionality work.

In order to fully understand the problem, we will make use of a technique called Event Storming.

Event storming

The goal is to discuss the flow of events in the system and show it in a way that is easy to understand. You need a wall, sticky notes, and both technical and business people in the room. It is very important to have the right people present. This includes people who know the questions to ask (typically developers) and those who know the answers (domain experts). First, we write down everything that can happen in our domain, which would be our domain events.

From here, step by step we will try to simulate the process.

You can start with any event, for example, “Question given”, and then immediately you come up with some questions (you should add your questions directly to the board, to keep it more readable I will post them as text):

Board with a single event and questions
  • What is a question, what are supported types of questions? A Question is represented as text only, nothing more, for example: “What is the capital city of Germany?”.
  • What is an answer? How many possible/valid answers are available? Answers are represented as text, only one answer can be valid, and no options are given to the user. For example, the question: “What is the capital city of Germany?”, has only one valid answer: “Berlin”.
  • How do we pick a question for a user? Every question belongs to one or many categories, and in order to get a question you need to specify the category first. The next question should be based on the progress of the user (We will get back to this a bit later).

From here there are two functionalities that are not clear: how to find a specific category and how answering the question should work. Let’s start with categories, and our next event “Category found”:

Board with two events
  • What is a category? It’s a set of questions grouped by a common topic. A category should have a non-empty title.
  • How do you select a specific category? You can either find it or select one from the available categories.
  • How do you find a category? By using keywords. Keywords should be a required property of a category, however, it’s not necessary that a title contains keywords.

Ok, so a category has a title and keywords, we can search for a category using a keyword as the query (do not think about any optimizations on the persistence layer yet). Then we can get a question in the selected category. Let’s continue with the question answering process. Our next events are “Correct answer given” and “Incorrect answer given”:

  • How do we validate an answer? How do we handle articles, own names, etc? The system should be smart enough to compare the meaning, not letters (We will cover this soon).
  • Can you skip a question? Yes, it’s considered as “Invalid answer given”

Earlier we have discovered that the next question should be based on the progress that the user made so far, our next event: “Progress updated”.

  • What is progress? For each question, you need to track the correct and incorrect answer attempts.
Board so far

One important thing we’ve not discussed so far: who is responsible to create questions/categories? We need to discuss the “Question added” and “Category added” events.

  • Who can create questions/categories? Only the admin of the system can create questions and categories, no need to develop anything around this.

The complete board with all domain events looks like this:

Complete board with events

Next, we need to identify the cause of each event. Usually, it’s:

  • Direct command: We use a sticker with a different color;
  • Another event: We keep those events together on board;
  • Time-based: You can mark those events with a special label;

For example, if we want the “Category Found” event to occur, there should be a direct command “Find category”, but “Progress Updated” is caused by another event: “Correct / Incorrect answer given”. Let’s add commands to our board (we use blue stickers for commands):

Board with events and commands

There are two processes that need to be discussed in more detail: next question generation and answer validation. With answer validation, we need to compare the correct answer and the answer given by the user. In next question generation we need to find the most relevant question for the user. We can use different strategies to achieve that. So, for now, we will add this to our board as policies (We will cover this in the next articles).

Complete board

And that is our complete board. What did we achieve?

  • We learned how the system works.
  • We built the common language between developers and business experts.(The so-called ubiquitous language).
  • It was quick, fun and more descriptive than text documents.
  • We are well prepared for writing the source code (We will be even better prepared after Part 2).

That’s it for now, I hope I have covered enough details and you get the idea. In the next article, you will see how this board can be used further, we will divide our functionality into modules and define boundaries and dependencies between them.

--

--