Hands-On with Domain-Driven Design

Audrey / July 7, 2025 in 

At BTI360, we recently spent a full day immersed in a Domain-Driven Design (DDD) workshop led by Paul Rayner. It was an intense, hands-on experience focused on understanding how to design software that reflects a deep understanding of the business systems it supports. The workshop gave our team fresh tactics for approaching complexity with clarity.

This post captures the core concepts and insights from that workshop. If you aren’t familiar with DDD, this post will give you a sense of what it looks like in practice.

What is Domain-Driven Design?

Domain-Driven Design builds design philosophy and methodologies around an idea most good software architects I’ve met know instinctively: software structure should reflect the structure of the system for which it is built. Deep knowledge of *what* we are building is necessary to make good decisions about *how* we build it.

DDD gives us tools to make that happen systematically, collaboratively, and at scale.

DDD breaks that into three steps:

  1. Understand the real-world system
  2. Abstract it into a model
  3. Build that model in code

Let’s walk through what that looked like in our workshop.

1. Understand the Real-World System with EventStorming

The first step is deep discovery. To design software aligned with the business, you have to understand the business — not just its requirements, but its pain points, language, and logic. It requires engineers to have direct conversations with subject matter experts (SMEs) and understand their day-to-day. These structured conversations are called “eventstorming

Here’s how it works:

  • Ask the SMEs what the system looks like as a user moves through it. This is a story about the user experience. The idea is to get the full picture of what the user needs from the system. Paul shared his favorite tactic for getting a good story: ask SMEs for their nightmare scenario or the worst thing that has ever happened in the system.
  • Capture events. Once you have a story (or several), write down every meaningful business event on a sticky note. Anything someone in the organization would care about should have its own sticky.
  • Sequence them. Arrange the sticky notes chronologically to visualize real workflows. You may need to rearrange the stickies several times and add new ones as you learn more about how the system works. It helps to do this on a large sheet of paper or piece of poster board so you can move or draw on it later.
    (Side note: post-its lie flatter if you peel them from the side — a surprisingly helpful trick from the class.)
  • Identify key events. Decide as a group what the “key events” are. Look for moments that trigger processes or represent transitions from one possible sub-system to another. It may help to draw a line on the paper underneath these events. Avoid designating too many. Try to narrow it down to three or four, then add more if necessary.
  • Group related flows. Reorganize the Post-its into logical processes or subsystems and see the model begin to emerge.

If this sounds like it could be chaotic, that’s because it is! The goal is not just to create a channel of communication between the SMEs and the product team, but to throw open the floodgates for productive dialogue. This exercise is designed to help the product team to discover as much as possible as quickly as possible about the space for which they are building. It builds fluency in the domain’s language, surfaces hidden complexity, and arms developers with the context they need to ask smarter questions.

2. Abstract the System into a Model

Once we understand the domain, we can start modeling it — building simplified representations that help us solve specific problems. DDD refers to this process as “domain modeling.”

Domain-driven design defines a model as “a useful abstraction within a bounded context.” For a real-world example, think of a subway map. It strips away actual geography and physical distance to highlight what matters: stops, lines, and transfers. It has a clear bounded context—navigating the subway system. You wouldn’t attempt to use it outside of that context. It’s not the full reality. Just the part relevant to the task.

In our case, we revisited our event map and began breaking it into subsystems — areas of responsibility aligned with different users or workflows. For each one, we asked:

  • What would be important to a specific type of user?
  • What concepts are central to this part of the system?
  • What can be ignored or treated as external?
  • Where are the logical boundaries?

When we’ve completed this process, we have models that are focused, understandable, and aligned with how the business actually operates.

3. Build the Model in Code

Now that we have a strong model of the problem space, we are ready to begin architecting a solution. We map domain-specific objects (e.g., trains, sales leads, approvals, documents) to data structures. We choose the best storage patterns based on business needs. We decide where and how users will communicate with the system. We implement core processes in the simplest way possible, striving to avoid introducing complexity that doesn’t exist in the domain itself.

In domain-driven design, our model should influence not just how we architect, but how we write individual lines of code. These principles overlap considerably with clean code practices. Code should make use of the ubiquitous language of the space. Objects in the code should have the same names as the real-world objects they represent. Function names should make sense to both engineers and non-engineers.

The code for your model must enforce strict boundaries on the contexts in which your model can be used. DDD emphasizes that abstractions are only useful within a bounded context – different contexts require models specific to them and optimized for their needs. Extending a model too far or into an inappropriate context will result in code that is brittle, confusing, and difficult to maintain.

 

Final Thoughts

DDD isn’t a silver bullet. It’s not an all-encompassing engineering approach. Its primary focus is on big discovery, and it doesn’t have as much to say about modeling and coding itself. It builds on and overlaps with existing software development methodologies. For instance, the clean code aficionados among my teammates saw plenty they recognized in the “Building the Model in Code” section, and those who have used Agile methodologies might see something reminiscent of “user stories” in eventstorming.

As a framework, though, I highly recommend DDD. It is excellent at cutting through ambiguity to identify the underlying structure. When used well, it leads to better questions, clearer code, and software that fits the world it’s meant to serve.

If you are interested in learning more, check out these resources:


Career Opportunities
Are you looking to join a software company that invests in its teammates and promotes a strong engineering culture? Check out our current Career Opportunities. We’re always looking for like-minded engineers to join the BTI360 team.

Previous

BTI360 Invite-Only Hiring Event

Close Form

Enjoy our Blog?

Then stay up-to-date with our latest posts delivered right to your inbox.

  • This field is for validation purposes and should be left unchanged.

Or catch us on social media

Stay in Touch

Whether we’re honing our craft, hanging out with our team, or volunteering in the community, we invite you to keep tabs on us.

  • This field is for validation purposes and should be left unchanged.