You get a bonus - 1 coin for daily activity. Now you have 1 coin

Bounded context DDD, folder structure with classes by DDD

Lecture



Bounded Context is a concept from the Domain-Driven Design (DDD) methodology, introduced by Eric Evans. DDD is a software development approach that emphasizes actively involving the domain in the development process.

Bounded Context is a strategic pattern that helps divide a large and complex domain into separate parts, each with clearly defined boundaries. This allows complexity to be managed and improves the clarity and modularity of the system.

In the context of DDD, a Bounded Context defines an area within which a particular term or concept has a specific meaning and context. Within each Bounded Context, team members and domain experts share a common understanding of how the various components of the system work and interact with each other.

Each Bounded Context can have its own domain model, entities, aggregates, services, repositories, and other elements. These elements may differ between contexts, but they are confined within that context and do not overlap with other Bounded Contexts.

The core idea of Bounded Context in DDD is to simplify understanding of the domain and reduce interaction between different components, which makes it possible to build flexible and easily maintainable systems. In addition, limiting contexts allows different parts of the system to be developed independently of each other, which supports project scalability and improves development productivity.

How do you break a large system down into smaller, more manageable components? I'm asked this question often, so I've gathered my knowledge into this article.

In DDD, a large system is decomposed into bounded contexts, which become natural boundaries — like microservices in code and like teams in an organization.
Bounded context DDD, folder structure with classes by DDD
There is no way to quickly and easily identify good bounded context boundaries. This requires broad and deep knowledge of the business and the domain. This workshop format was designed with both of these needs in mind and uses two tools to find the most effective system design: EventStorming and the Bounded Context Canvas.

Bounded context DDD, folder structure with classes by DDD

«I developed this canvas while running DDD workshops at public events and corporate sessions. Feel free to change its structure if you find formats that work better for you».

Key DDD Concepts

1. Domain-Driven Design

DDD starts with a deep analysis of the business domain, not with technical details.
First, the problem space is studied — the real business processes (product, sales, customer support), their goals, and their rules.
Then, based on this analysis, the solution space is formed — the software services (Order Service, Product Service, User Service).

The point: code should reflect business logic, not the other way around.

2. Using models to represent business entities

DDD involves thinking in terms of models, rather than tables or APIs.
A model is a simplified but accurate representation of business reality (Product, Order, OrderItem).

Levels of abstraction:

  • Data — raw facts

  • Information — structured data

  • Knowledge — business rules

  • Understanding — comprehension of the domain

The point: we reason about the system in terms of models that the business understands.

3. Defining boundaries (Bounded Context)

The same entity can have a different meaning in different contexts.
For example, an Order in the context of orders and an Order in the context of payments are not the same thing.

The diagram shows separate contexts:

  • User context

  • Product context

  • Order context

The point: each context has its own model and rules, and they should not be mixed.

4. Defining aggregates

An aggregate is a group of related entities managed by a single root (Aggregate Root).
For example:

  • Order — the aggregate root

  • OrderItem, Payment — its parts

All changes within an aggregate:

  • go through the root;

  • must preserve business invariants.

The point: aggregates ensure the integrity and consistency of business data.

5. Separating entities and value objects

DDD distinguishes between:

  • Entities — have a unique identifier (Order, OrderLine)

  • Value Objects — have no ID and are defined by their value (Address)

Value objects:

  • are immutable;

  • are compared by value, not by identity.

The point: not everything in the system needs to be an entity.

6. Manipulating models (Factories, Services, Repositories)

DDD forbids «chaotic» creation and modification of objects.

Special patterns are used:

  • Factory — creates complex objects

  • Domain Service — business operations

  • Repository — saves and loads aggregates

The point: domain objects don't know how they are created or stored.

7. Layered architecture

The system is divided into layers:

  • Presentation — UI, API, WebSocket

  • Application — use cases

  • Domain — business logic

  • Infrastructure — database, cache, storage

The domain does not depend on the infrastructure.

The point: business logic is at the center of the architecture and is not tied to any technology.

8. Building the domain model

The domain model is formed from:

  • actors (the user);

  • use cases (searching for a product, creating an order, payment);

  • events and processes.

The following may also be used:

  • Event Sourcing;

  • modeling objects in color.

The point: the domain model is a living reflection of the business, not a static diagram.

The bottom-line idea of DDD:

A software system should speak the language of the business, be resilient to change, and reflect the real domain.

Bounded context DDD, folder structure with classes by DDD

Recipe


The basic recipe consists of the following steps:

  1. EventStorming (at least 1 hour).
  2. Modeling bounded context candidates (at least 30 minutes).
  3. Modeling the domain message flow (at least 30 minutes).
  4. Bounded Context Canvas (at least 90 minutes).
  5. Creating context maps (at least 45 minutes).


As a starting point, I recommend setting aside a full day for this workshop. This will help you understand how much time you actually need to run the workshop properly. If it's expensive (labor-intensive) to get everyone together, try setting aside two days right away so you have time to get everything done.

Ideally, the participants should be domain experts and technical experts. If that's hard to arrange, at least try to have the domain experts present for the first hour of the workshop.

Basic modeling principles


Running a session with experts requires a spacious room. If you choose a small room, you will most likely be disappointed with the results. Each group of 4 people needs at least 4 meters of wall space.

I'll describe my method loosely, without a strict set of rules. However, keep in mind:

«We constantly switch between the problem space and the solution space. We look for information, build a model, look for more information, refine the model, and so on».

And one more important point: the goal of the session is to develop options and build up the ability to propose better options in the future.

1. EventStorming


To design a system, you need two things: a good enough overall picture of the whole system, and a deep enough understanding of the details in each area. To get there, we start with EventStorming.

EventStorming is a collaborative design method that lets you model a large problem space from start to finish, while also allowing you to drill down into a large number of details wherever needed.



If you're doing this for the first time, I recommend setting aside 1-2 hours for EventStorming. After finishing EventStorming, I recommend splitting into groups of 4 people.

2. Finding bounded context candidates


Once your domain has been modeled broadly and deeply through EventStorming, you can start grouping and merging fragments into bounded contexts.

Bounded context DDD, folder structure with classes by DDD

There are many methods for identifying a bounded context. I recommend starting with the following:

  • Start with value — identify the core parts of the domain that provide the greatest value to the business.
  • Start simple — create a naive model by breaking the timeline into sequential steps.
  • Look for key events — business events that affect different parts of the business process.


The first time, spend no more than 30 minutes on this task. Ask the group to create an initial bounded context model as a starting point. It doesn't need to be perfect and is unlikely to be the final solution.

The output should be formatted as a list of bounded context names on a flipchart or piece of paper. You cannot physically alter the EventStorming board if you have multiple groups.

Next steps


You may immediately see several ways to model the system. Pick one of them to work with for now, and write down the other possible models (they will be useful later). You may also realize that you're missing information about the domain. If so, run another round of EventStorming.

3. Modeling the domain message flow


One way to check whether your design is correct and to find points for improvement is to visualize the interaction of bounded contexts across complete business scenarios in the system.

If the resulting domain flow is complicated, with lots of dependencies and bidirectional links, then your design is fragile and needs further analysis.

There are many visualization techniques you can use to model flows and use cases, including UML sequence diagrams and UML use case diagrams. I recommend using a domain storytelling variant.

When modeling the domain message flow, the bounded contexts are the characters in the story. So a typical story starts with a user trying to achieve some goal, and the interaction between bounded contexts is aimed at delivering that solution to the user.

Bounded context DDD, folder structure with classes by DDD
A made-up example of a domain message flow

Modeling strategic domain flows gives you feedback on the proposed bounded contexts. It shows how the contexts collaborate with and depend on each other to carry out a complete business process. This can help you find an alternative design.

The question you should ask yourself: does the description of each bounded context match the role it plays in the domain flow. If not, then the name or the boundaries of the context probably need to be redesigned.

Next steps


Since your domain flows define the relationships between bounded contexts, you may immediately spot obvious design flaws. You can go back to the previous step and update the bounded context candidates, or run a second iteration of EventStorming. You can also write down your design thoughts and gather more information for follow-up actions before starting the redesign.

4. Bounded Context Canvas


The next stage of the design is to develop the bounded context candidates by detailing the key design criteria. Your team should pick the bounded context you consider most important. Limit the discussion to a maximum of 3 minutes. Being 100% accurate is not critical.

Now draw the Bounded Context Canvas and go through the following steps to fill in the details. I recommend using 1 flipchart sheet or a piece of paper of similar size.
Once you've completed the listed steps, repeat the process until you've defined all your bounded contexts. Try to split your time evenly between the identified bounded context candidates.

4.1 Defining the shared context


Start by defining the name of your bounded context and its description. The description should show the purpose of the context in the domain and its role in the business, not implementation details.

Next, you need to do a strategic classification. Is the bounded context a core part of the system, a supporting element, a generic one, or something else? Read Vladik's post if you need help making that choice.

Bounded context DDD, folder structure with classes by DDD
As an example, a filled-in Bounded Context Canvas after completing step 1.

Next steps


If you can't come up with a clear name, or write a coherent, precise description, or your Ubiquitous Language (UL) terms are ambiguous — treat this as feedback for the design. Think about redesigning the boundaries, or make a note and come back to it later (usually it's better to come back later).

4.2 Clarifying business rules and forming a shared language


Now go back to the EventStorming board and look at the notes for this bounded context. Find the most important business rules and policies, then try to pick the 3 most important ones and add them to the canvas.

This is also a good time to look for key business words or phrases to add to the «Ubiquitous Language» section of the canvas. You'll keep adding words and phrases throughout the workshop; for now this is just a starting point.

Bounded context DDD, folder structure with classes by DDD

4.3 Capability analysis


The next step is working through the capabilities provided by the bounded context. This not only clarifies what it does, but also gives a lot of feedback for the design. You can ask questions like:

  • Is this context overloaded with responsibilities?
  • Do the capabilities look related?
  • Do the capabilities match the name and description of the context?
  • What if we moved this capability outside the context?


Start identifying capabilities by imagining the public interface. What can consumers request from this bounded context, and what commands can they invoke? Use the domain data flows to see what consumers need from this bounded context.

Not all capabilities are triggered by external commands and queries. Some capabilities can be triggered internally — for example, scheduled jobs. Sometimes you'll notice that capabilities cluster together, e.g. a command, a query, and a notification. If so, group them together on the canvas and give the cluster a name.

You may get a feeling that a responsibility is out of place and should belong to a different bounded context. If so, flag it with some kind of marker on the sticky note.

Bounded context DDD, folder structure with classes by DDD

Next steps


If you find it hard to identify the capabilities of a context, or you feel that some are missing, I recommend going back to EventStorming and modeling this bounded context in more detail, focusing on finding the capabilities needed by other contexts or services.

Drilling into capabilities [optional]


Break down each capability on your canvas into further sub-capabilities. This additional level of detail helps you find alternative models. If there isn't enough room on the canvas for the details, find another sheet of paper or space on the wall. You can go as many layers deep as you find useful.

4.4 Dependencies


Dependencies are necessary if we want modularity, but they also cause a wide range of business, technical, and social problems. So it's important to see the dependencies, understand their impact, and consider alternative options. That's why the final step of designing a bounded context is aimed at capturing all the key dependencies of your bounded context.

Reviewing the EventStorming results and the domain data flow diagrams, identify each dependency the bounded context has, and record the following information:

  • the name of the other bounded context or service;
  • a brief explanation of why the dependency exists;
  • where the dependency is located: inside this system or in an external system (e.g. a third-party service);
  • the type of relationship: is it an inbound dependency (another service depends on this bounded context), an outbound one (this bounded context depends on another), bidirectional, or a user interface (the dependency is some kind of user interface).


Question each dependency: is it needed, and what are the costs and benefits of having it. If it seems like you could do without it, mark the dependency with a yellow sticky note.

Bounded context DDD, folder structure with classes by DDD

4.5 Constructive criticism


Once you've finished filling in the canvas, spend a few minutes critically evaluating the resulting design of your bounded context. Break your feedback down into the following categories:

  • Good: aspects of the design you like.
  • Bad: aspects of the design you don't like.
  • Not sure: aspects of the design you're unsure about.

4.6. Reflect and repeat


Good design is iterative. Before moving on to the next bounded context, step back and look at the big picture. Have you learned anything that contradicts your design? If so, redraw the proposed boundaries, then continue designing the next bounded context.

At this point, ask yourself whether the domain has been modeled in enough detail. Was it hard to fill in any parts of the canvas? If so, try running another round of EventStorming across the whole domain, or on certain parts of it.

5. Creating context maps


After creating a canvas for each bounded context and gathering design feedback, the next part of the session is to return to exploration. This time you have a full body of knowledge to help you find the best design options.

The output of this exercise is a collection of basic context maps — visualizations of the structural relationships between bounded contexts — and any other diagrams you consider necessary, such as domain flow diagrams. Each team should develop at least 3 context maps, each showing possible ways to build the system.

Bounded context DDD, folder structure with classes by DDD
An example of a very precise context map; that's plenty for this workshop.

We'll be running a meetup at TechLead Conf 2020 where we'll go over various techniques, patterns, and anti-patterns for applying DDD, and put together a visual radar. We'll publish it after the conference.

The final activity can be run in a free-form way. The goal is to review the collected information and use it to develop a number of system designs. As a starting point, I recommend:

  • Review all the feedback gathered for each context, and experiment with the «bad» and «not sure» feedback.
  • Ask «what if» questions ...
  • «What if we moved this capability into another bounded context?»
  • «What if we split this capability and moved one of the sub-functions to another bounded context?»
  • «What if we split the bounded context into several contexts?»
  • «What if we took a capability from each of these three contexts and used it in a new context?»
  • «What if we duplicated the functionality to remove the dependency?»
  • «What if we created a shared service to reduce duplication across contexts?»
  • «What if we isolated the truly key capabilities and moved the rest to a quieter place, into a separate context?»


If you prefer to visualize these transformations, the following illustrations may be useful:

Bounded context DDD, folder structure with classes by DDD

Bounded context DDD, folder structure with classes by DDD



Bounded context DDD, folder structure with classes by DDD

Closing the workshop

To wrap up the session, each group should present a selection of the context maps they created and discuss the trade-offs of each design. You need to explain your choices, and a 5-10 minute presentation is usually enough for that.

What to cover in the presentation:

  • Focus on the key areas: how each design option lets you develop the core parts of the system more effectively.
  • Compare the domain data flow diagrams: how one system's design reduces complexity and the number of dependencies.
  • Explain what you'll do next to validate your choice.

See also

  • [[b9975]]
  • [[b9149]]
  • [[b8520]]

See also

Comments

To leave a comment

If you have any suggestion, idea, thanks or comment, feel free to write. We really value feedback and are glad to hear your opinion.
To reply

Lectures and tutorial on "Running server side scripts using PHP as an example (LAMP)"

Terms: Running server side scripts using PHP as an example (LAMP)