Art Of Knowledge Crunching In Domain Driven Design
In this article, learn how to use BDD and DDD tools and technics to overcome complexities, blind spots, misunderstandings, and more.
Join the DZone community and get the full member experience.
Join For FreeBig teams often struggle with communication, coordination, decision-making, and delivery of large-scale projects. Agile provides a framework to help reduce these issues, allowing teams to move quickly and adapt to changes. It encourages teams to work together more collaboratively, breaking down large projects into smaller, manageable chunks.
Agile also helps to prioritize tasks, identify and manage dependencies, and provide clarity for the overall project goals. This helps big teams to stay organized and on track and to make sure everyone is working towards the same objectives. Perhaps you’ve heard about Scaled Agile Frameworks and wonder whether it’s worth investing in one of them to get you to the next level.
But, how far you can go with Agile frameworks? There are some blind spots that should be considered when using Agile frameworks. One of the main problems with Agile frameworks is that they structure communication in a way where domain experts are at the top, and their will is taken to production. This poses a risk because there is no guarantee that the software engineers will implement the same thing as the domain experts expect. Therefore, it is important to ensure that all stakeholders are included in the discussion, and software engineers must have a clear understanding of what is going on as Alberto Brandolini says:
It is not the domain expert’s knowledge that goes into production, it is the assumption of the developers that goes into production.
How are developers supposed to solve a problem when they do not know what the problem is? Are developers’ assumptions right? Is there any shared understanding? This article is about how we can use BDD and DDD tools and technics to overcome complexities, blind spots, and misunderstandings to properly knowledge-crunching and find a ubiquitous language.
Domain-Driven Design Is Linguistic
In order to communicate effectively, domain experts and the development team must have a shared understanding. Developers do not need to be experts, but they must be familiar with the terms and their context in that domain. For example, if they are working in the health domain, they do not need to know how to treat a patient, but they do need to know the exact meaning of the word shift in that domain. It is not enough to just know the meaning of the term; they must also understand the context in which it is used.
Separation of the same term in different contexts is at the core of Domain-Driven Design. Though a term may have the same meaning within two different contexts, this is not our primary consideration. Instead, it is the context that defines the meaning of the specific term that matters most.
Let me clarify further. Imagine a cup of coffee with a specific cup, taste, and even brand. When it is served in a coffee shop, it has value and you will pay for it. But, if the same coffee is left on a bench in a park, would you pay for it or even drink it? Of course not - it is the same coffee yet in a different context. This is why context matters.
If OOP is in terms of object, DDD is in terms of context.
Many developers make mistakes and unintendedly think in terms of data and taking care of certain states rather than behavior. Behavior is not data: data is the product of behaviors under fixed circumstances and it’s what we might make a decision based on. In fact, the behavior that leads to a certain state is more important than the actual state. We can prove this by math: f(x) = y and g(x) = y =/=> f = g. We can not conclude f and g are replaceable based on their final state. As I mentioned above, we preserve the meaning in a specific context, instead of the final state.
Remember the coffee example: we do not care how the coffee is made (as it is a normal cup of coffee), but we do care about the context. Coffee is our data, and the coffee shop and park are the contexts in which its behavior is defined. Can we replace them? I mean, we see the final output as a normal cup of coffee - we cannot replace the park with a coffee shop. In other words, we cannot say, “I want a cup of coffee, I can take it from the park or coffee shop - who cares?”
We separate park coffee and coffee shop coffee with the help of bounded contexts in Domain-Driven Design (DDD). We encapsulate and make ubiquitous each term within its own context. This means that we would not have a global ubiquitous language; instead, each bounded context would have its own ubiquitous language.
Miscommunication during knowledge crunching sessions would have different reasons, such as cognitive bias, which is a type of error in reasoning, decision-making, and perception that occurs due to the way our brains perceive and process information. This type of bias occurs when an individual’s cognitive processes lead them to form inaccurate conclusions or make irrational decisions. For example, when betting on a roulette table, if previous outcomes have landed on red, then we might mistakenly assume that the next outcome will be black; however, these events are independent of each other (i.e., the probability of their results do not affect each other).
Also, apophenia is the tendency to perceive meaningful connections between unrelated things, such as conspiracy theories or the moment we think we get it but actually, we do not get it. A good example of this could be an image sent from Mars that includes a shape on a rock that you might think is the face of an alien, but it’s just a random shape of a rock.
Sometimes people lie, not in a bad way; I mean, not on purpose. Imagine while you are working on your laptop, your roommate might ask when you to go to the kitchen to turn the light off. After 20 minutes, you go but forget to turn the light off—without any intention. These are inevitable during collaboration sessions, and we need to find ways to reduce them.
Developers should collaborate effectively to create a ubiquitous language and have a clear understanding of the different terms in the domain to create proper bounded contexts. However, making sure they understand every problem in the domain is a difficult task. The proper way to address this problem can only be achieved by employing DDD and BDD. These approaches have different tools to cover every blind spot and minimize ambiguity.
Domain (Problem Space)
For this article, I define a straightforward domain for an imaginary camper-vans rental company within Texas.
The main service of the company is renting out campervans, which are managed in the HQ. Clients can only rent available campervans, each of which is separated by its unique car tag. They must be picked up or returned at one of the company’s stations (e.g., Houston, San Antonio, Dallas, Austin, etc.). There is no limitation regarding the return station; that is, campervans can be returned to any of the stations. Clients can cancel their rent before pick up, which means that they would not be able to cancel after they picked up the campervan. Also, they can not have three cancel in a row else their account would be limited.
But, they must be returned before the due date of rent. If the client returns late, they must pay a penalty. The penalty is currently a fixed price. Every campervan can be serviced and repaired in the company’s repair garage. Whenever a campervan is in the repair process, it is not available for rent. Every campervan must be repaired after five rentals or three months after the last repair.
The company has portable equipment (like portable toilets, bed sheets, sleeping bags, camping tables, chairs, etc.); equipment is added or removed with their respective stock in the HQ of the company. Clients can book any number and type of available equipment for their rent, in addition to their campervan.
Equipment is stored at stations and has a limited count at any given point in time. Once a client drives off the station, the available amount of equipment at that station is reduced (by the number of equipment the client took with them) and when the client returns the campervan, the number of equipment at the station is increased accordingly.
Since the amount of equipment is limited and during the high season the number of campervans and the equipment used simultaneously is the highest, your business needs to plan ahead for the amount of equipment needed at each station per day in the future. This mitigates the risk of running out of equipment. For simplicity, I have omitted the payment part. Let’s use event storming and BDD to model our domain.
Event Storming
One of the best approaches for knowledge crunching is event storming. It is a flexible workshop format for the collaborative exploration of complex business domains. For event storming, I will come up with a series of articles soon, but for this article, I will have a glimpse of it.
What makes event storming so efficient? It is a rapid, lightweight, intense, highly interactive, and collaborative workshop that helps to build ubiquitous language. It is the most important part of the whole storming, where the common goal is to share the maximum domain knowledge from each of the participants. There are different steps of event storming workshops: a big picture, process modeling, and design.
A big picture session is usually used to discover the business domain and share knowledge. Process modeling and design are more focused on system design, and defining aggregates, and involve developers, product owners, UX/UI designers, and engineering managers.
Let’s start off with big picture, like a blind man in the room. You may tackle the whole business in this session. As you know in enterprise companies knowledge is shared. Each department has its own expert who does not know about others or knows little. The real value of any brainstorming is people and their knowledge. Therefore, for a successful event storming, inviting the right people with appropriate knowledge is essential as well. It starts with chaotic exploration, sticking orange sticky notes to the wall. On each note, there is a past sentence that describes a domain event.
Domain Events
Each event is expressed in a past term verb, written down on an orange sticky note, and their respective actors. Here are a few points to help you understand what domain events are:
- You could read about them in domain books.
- Domain experts understand them.
- Writing them in the past tense is a trick to create meaningful events. They are not actions of someone or something. Even though some events will result from actions, we are not interested in actions yet.
- They are not technical, and should not be specific to our system’s implementation.
In the imaginary camper-vans rental company domain, the chaotic exploration phase would be like this:
Whenever we come across or agree on a domain word, feel free to write a definition for it on a large yellow sticky note. This is a way to build up a domain of ubiquitous language. This is very helpful to improve communication between all of us. This in turn improves how we work in many different aspects. It should be added to the wall like this:
What about a question we cannot answer something that does not seem right, or any problem we should look into? we use purple sticks to park "problems." After this, ask attendees to identify actors (users with a role) that trigger or respond to events. The convention is to use a small yellow sticky note for that.
Note: There is no need to add an actor to every event, sticking one at the beginning of a chain of events is enough.
Similarly, complex systems also interact with external systems. External systems are not humans, but they could be an online API for example. The convention is to use blue post-its for external systems. Place some at a place where the events interact with them.
Command
Now, it’s time to focus on the command that triggers appropriate events. Write down "Command, important for the business," on a light blue sticky note and place them left in the event they spawn. A command is a message that represents the intention of a user and could be expressed as an action, like request booking, cancel booking, request refund, etc.
Policy
Policy artifact is used to document conditions and policies for events to happen. So, on a storming wall, a policy stays between a domain event and a command. Policies are formalized like, "Whenever…X, then…Y," or, "If…X, then…Y." Imagine when a client picks up a camper van we need to update the related equipment stock for the origin and destination stations. For the destination, it must be applied to the expected return date. The policy would be an Equipment Stock Change Policy which states that if a client picks up a camper van, then update the related stock.
Aggregate
In Domain-Driven Design, aggregates are a cluster of domain objects which can be treated as a single unit. An aggregate will have one of its component objects be the aggregate root. The aggregate root is the only member of the aggregate that outside objects are allowed to hold references. All of the other objects within the aggregate will only be accessed through the aggregate root. This enforces data integrity and consistency within the aggregate.
The hard part of Domain-Driven Design is identifying aggregates: it’s always hard and confusing. However, with event storming, this would be much easier and more understandable. In this case, go through all commands and events that are not linked by an external system. Add an empty yellow sticky note there. Please don’t call them aggregates. It’s going to work better if you call them "Business Rules." Ask participants to fill in these business rules:
- Preconditions: These are things that must be true before a method is called. The method tells clients “this is what I expect from you.
- "Postconditions: These are the things that must be true after the method is complete. The method tells clients “this is what I promise to do for you."
- Invariants: Invariants are the things that are always true and won’t change. The method tells clients, if this was true before you called me, I promise it’ll still be true when I’m done. Let’s gather business rules, commands, and events that occur together, no matter where they are in the process.
- The last step is finding a proper name for your aggregate.
Also, I identified bounded contexts:
What Is BDD(Behavior-Driven Development)?
BDD is a collaborative practice.
These days engineers think BDD is Gherkin (given, when, then) or they might know it as Cucumber, which is totally wrong. I mean, BDD is not about UI, log-in, etc. BDD is an iterative approach to fill gaps in Agile. BDD starts off with a team and the team needs to discover first then formalize and at the end implement. The discovery phase is an activity that leads to ubiquitous language through collaboration through examples and conversation on rules.
Due to its nature, the discovery practice works best when the team discusses the requirements together. The discussion of a user story usually generates examples. Collecting examples can be started by focusing on simple questions, such as “Could you please give an example for this?” We collect examples for the user story’s rules, which are already defined in the event storm.
After that, take examples, and recheck what is going on in the event storming wall to see if we can find any errors or realignments. This will help to improve and justify. At this stage, it is perfectly acceptable to capture the examples as a list of steps that describe the behavior of the system in a particular case.
In the formulation step, we transform the examples into scenarios using the "Given/When/Then" keywords. The format of the scenarios and keywords is called Gherkin. The scenarios written with the Gherkin syntax can be executed as automated tests by different tools, like Cucumber.
Write Gherkin for rules that have priority.
A sample Gerkin for the rental company domain would be:
- Scenario: As a client, I want to update my rent date.
- Given that I have a rental request for a campervan
- When I decide to update my rent
- Then the rent should be canceled, and I should be able to rent a new campervan on the desired date.
Good Gherkin scenarios are business readable, and via automation, they verify the application. When they fail, the failure is understandable both by the business side and the delivery side of the project. So essentially they make a connection between the problem and the solution or in other words the members of the distributed team. Scenarios represent our shared knowledge and shared responsibility to produce quality software.
Conclusion
Every tool has its own blind spots and every blind spot might be million dollar mistake. Let’s use DDD and BDD tools together to build better models.
Opinions expressed by DZone contributors are their own.
Comments