Model-Driven Design = Next-level Domain-Driven Design
Small Talk with Bruno Boucard and Kenny Baas-Schwegler
This blog post is the transcription of the chat we had with Bruno Boucard and Kenny Baas-Schwegler about their Deep Dive into Mode-Driven Design on 16 February 2024.
The conversation has been slightly edited to better fit the written format. Enjoy!
Avanscoperta: I would like to ask you to introduce the workshop. So what are we talking about? What is it for?
Kenny: Let’s introduce ourselves first. I’m Kenny, a software developer, software architect, and independent consultant.
My expertise is in Domain-Driven Design and Team Topologies, and my goal is to enable teams to develop software, design software, and run that software as independently as needed. We're going to deep-dive into the second-part design because that's the bit that a lot of teams and organizations are still missing.
And this is, namely, “How can teams independently design with their stakeholders?”
Bruno: I'm Bruno. I have more than 20 years of experience in IT. And I would like to explain how I discovered Domain-Driven Design.
It was 10 years ago. I met Alberto, Eric, and Matthias at the Build Stuff stuff conference. It was for me a great moment. I felt like crossing the world, like an episode of Black Mirror. And since this period, I've not yet returned to my original world.
So I think it's important to say some words about how I discovered the Blue Book. It was a very strange experience for the first time. I started reading the Blue Book, and I was very surprised by the literacy style of the book more than by its complexity.
And I returned to it several times. And finally, I began to understand the finest of Eric's words. And I fell in love with the third part of the blue book, the reason why I'm here. That's the motivation behind wanting to do this workshop.
Kenny: And now back to the original question, “What is this workshop about?”
It's about part three of Eric Evans’ Blue Book. And what we see, well, at least what I see and observe in the Domain-Driven Design community, is that people get the problem. But what problem?
It all started with me as well 12 years ago, writing software with anemic domain models, thinking about surface object patterns, and then a domain model that maps with object relationships, right? Okay, that's not how you want to do it.
So I started using Domain-Driven Design, got my aggregate out, and got my rich domain model out. I thought that it was okay, but if I had read the book correctly, it wouldn't have felt like the promise of DDD was being fulfilled.
And this is where I see the industry move now as well. A lot of people focus on strategic design, which is perfect, as we need that. But we're missing the depths of tactical design because most people we encountered using Domain-Driven Design talk about aggregates and value objects, which is a good head start…
But the problem is that there's still a disconnect from a situation like, “Okay, we modeled and designed it together with the stakeholders, and now software developers are starting to build software.”
I think it's even in chapter two of Eric Evans’ book, where he says, “There's a disconnect then between the code and the model,” and that's because developers are left to implement it by themselves.
So we need that deeper connection with stakeholders, with domain experts as he calls them, which is what we're going to do in this workshop, go deeper into Model-Driven Design, which also means that we can also design and model through coding.
We're going to spend more time in the code, going back to our modelling space, and realize that aggregates are indeed a first start but we need to go deeper. It might not even be the best start. You might not even use aggregate, right? It's just the tactical patterns, but that depth, which is called deep modeling, that's what we see is lacking.
And because we're lacking that, in most organizations I see Domain-Driven Design doesn't live up to its promise of making software more adaptable to users' needs, making that deeper connection, because usually we stop there.
We're going to go through the whirpool once, we got our domain model and never improve it, never adapt it, never change it. And I think that will be what this workshop is about, and where the problem is.
Bruno: I totally agree with what Kenny says, and I’d like to add something. Deep-modelling is an approach; it’s not a tool. It's a way to organize how you deep-dive and how you discuss and think about the complexity of the domain of your business roles.
Generally, people love solutions because things like aggregates, value objects, and entities are easy to understand. However, it's very useful to protect your modeling. But inside your aggregate, you have to deep-dive into your modeling, and that’s the problem of the developer because honestly, part three of the book is not so easy to understand for a new developer. I think that's the problem.
Kenny: You need to have experienced it. You need to have worked on a domain for at least six months, better even a year. Also we're focusing on Java and C# at this moment.
Bruno: It’s important to have experienced this situation, to be hands-on and ready to have a good way to discuss with the domain experts, and apply what Eric said, which is make a prototype, discuss that and make refinements.
And Eric talks about refactoring, indeed the title of the third part is Refactoring toward deep insight. But this refactoring is not exactly the refactoring defined by Martin Fowler. It's another way to make a refactoring. It's a refactoring like carving the wood. It means that each time you see something, you see the world is not exactly aligned with the domain, you have to change a little. Or maybe sometimes you do a refactoring like Martin Fowler does.
Kenny: I like this point, Bruno. Because the code is not the model. The code is like a reflection of the domain model. So if you go into code and you see this nice folder called “domain model”, you might hope that it represents the domain model, but it is not in fact THE domain model.
That's why we use supple design in order to make sure that the code in there is adaptable to the domain model, because the domain model in this case is an abstraction.
The domain model is the conversation we're having with our stakeholders, with our domain expert. It is the understanding of our domain represented in a form, which is kind of abstract, but that's what we're going to experience during this workshop.
But again, we're looking at how fast we can go to code in changing that model. And that's the refactoring the domain model, which of course, if you refactor the domain model, you need to refactor your code.
Now, if you refactor your code, you also need to refactor your domain model. It goes both ways to refactoring. And that's what Eric says, “Refactoring doesn't mean the code”... well, it does mean the code. But if you refactor the code, you must refactor your domain model and the collaboration you have with your stakeholders.
That's a good point about Model-Driven Design. We don't want to confuse it with Model-Driven Development, which is also a technique.
We are being explicit that we’re talking about the Model-Driven Design as described in the original Domain-Driven Design book by Eric Evans.
Eric's being exact in that it's about collaboration, about continuously changing the model to a deeper insight.
And we only do this, of course, where it really matters. “Tackling complexity in the heart of software”, right?
We won't do this for a very complicated or simplistic challenge or domain challenge. We do this only when people are working on complex problems.
Bruno: When you have something very complex, you need several steps to understand.
The first step is quite blurred, then the next step is quite clear. And the third is clear. It's because in your mind you have a mental model growing and you get something new, but it takes time. It takes time to do discussions, conversations and coding to be sure to be aligned.
Kenny: As an example, in one of my previous clients, we had a very complicated domain. It wasn't complex, but it was very complicated. We had deep conversations with several domain experts, at least three different types.
We went over three months of iteration, continuously updating the model, then the code, and then again the model and the code.
And everyone, especially the domain experts and product owners, were saying “Why is it taking so long?”, even getting a bit upset. And then you have that breakthrough come to a very simple, clean model.
Then after three months of development, we caught up. Every new feature that was brought in was built in within minutes or hours. It was very fast.
And that understanding, that intrinsic understanding, that's what we're going through in this workshop.
We start with a naive model and we'll give you a naive model to work with. You're going to code a bit on it and then we're going to give you a whole new feature. That's what happens in real life.
“We designed, we modelled, we took into account what we know. It's complex, we don't know the future.” And while you're working on the first model, the product owner comes in and says, “You know what? We might be able to do this”, and then you think, “Oh, but that's not how we accommodated the model for.”
And from there, we're going to start the Model-Driven Design, see how we can make the code supple in order to accommodate these new features and how we can refactor to a deeper model.
This is the kind of process we're going to follow and that makes this different from your normal tactical Domain-Driven Design workshop where you go into aggregates.
So you need to have a base understanding of aggregates and objects as well, and how they're represented in the code, because we're gonna go deeper to it.
Avanscoperta: So what is Model-Driven Design?
Bruno: Model-Driven Design is a connection of two things—deep modeling and supple design. But as a definition, it's not enough because it's an approach. As Kenny said, we practice supple design, which is a way to to apply your ubiquitous language in your code, apply autonomy of your classes, to continue to refactor with ease.
My point is, Modern-Driven Design is not a chapter in the Blue Book, which is a shame. It is a pattern in the book, but it’s not well-named and defined.
It is explained in every chapter in the part three, where you have some mention of a Modern-Driven Design. There is something more in the Orange book, but not in the blue one.
All part three of the Blue Book is dedicated to Modern-Driven Design. And since it’s not so explicit, plenty of developers miss the definition and don't understand clearly what's the aim of part three. This workshop aims to fix this.
Avanscoperta: Do we need people to have read Eric Evans' book or even just the part three of the book to join the workshop?
Kenny: No, because you're going to experience this ongoing dialogue between domain experts and practitioners in the workshop.
I want to emphasise this as we don’t usually see this ongoing conversation happening. This means that this conversation will also carry on as we work through the code.
I usually don’t see it happen in our industry. We stop from a design session, we stop and then the developers go back to their working station and gonna work with each other to make pretty aggregates and value objects… but there’s never an ongoing collaboration with stakeholders. This is what our workshop is about.
Avanscoperta: We've seen this in many other workshops—it's all about collaboration… but then what happens when it stops? You find yourself in a lost-in-translation kind of scenario and this does not help.
Kenny: I want to emphasise the why of the workshop as well…
The code moves away from the domain model when developers go to code and stop the collaboration with other stakeholders because you did a lot of collaboration, there's a domain model, there's a shared understanding and domain model, then you go through code and there's so much in code, which is what Eric talks about - the breakthroughs and the deeper understanding.
That’s why big up-front design does not work—because in the code, you get new insights that you need to bring back to the domain model… and all of this bringing back from the code to the domain model is the actual focus of this workshop—making sure that code stays more aligned to the domain model.
If you don't do that, it's going to get in your way because you're constantly progressing. Every change, every new feature, will be harder to implement because you need to translate again, and that translation is what we try to actually solve with Domain-Driven Design in the ubiquitous language.
But we're not aware that we're moving away from the domain model in our code. That's the pain point we're aiming to solve, right?
“I did Domain-Driven Design, I did all this design with the stakeholders, now I'm coding. Two months later this new feature comes in and I don't understand anymore because there's just these nouns in my code right and I don't know what they're talking about specifically and it's different and I need to translate it…”
That's the pain point and that's why a lot of people think, “Well, there's so much work going into creating aggregates and value objects and it doesn't work because two months after we're using it I'm still making these translations.”
Yes, that’s because because we're not continuously refactoring.
Bruno: On the developer side, we need a specific behavior, self-determination, and engagement because it's not a lazy position.
You can’t do deep modeling if you are lazy; you need to be engaged and think about it. Then, as Eric says, you need to sleep on it. It means you have a short meeting. We do sessions with a domain expert to understand deeply. And sometimes you need several days to think about, and this is also very important. You cannot do any of this if you’re not engaged and you don’t care.
You also need to exercise the ubiquitous language all the time because it helps a lot in the way you think.
Avanscoperta: And now some questions from the chat, here’s Anthony’s: “Can you outline some heuristics that can allow us to build a model and code that represents that model to be pilable and allow for changes? “
Bruno: This question is more about supple design. Actually, supple design is the answer to continuously refactoring.
Supple design is a collection of patterns for your code to obtain something very supple and change your mind without breaking your design.
Kenny: And if you want a very concrete heuristic, Test-Driven Development is the answer. If you do that together with supper design, it works. A big part of this workshop is using Test-Driven Development. We use our clear scenarios from our modeling, a Test-Driven way, but not the normal way.
We have a design. We already have design. So we're not doing dogmatic Test-Driven Development. We're doing it from the rich model that we get.
And from there, the heuristic is, “Don't use a new feature in Test-Driven Development inside your current domain. Use it in a test. So don't use your current code and your current domain model in your code while introducing new tests. Just use it from where you're starting with a test.”
And this is what we're gonna do in the workshop as well. We're gonna start from our tests and then integrate them in our domain model or find out that our domain model isn't optimized for this, so maybe we need to change it.
And again, what Bruno said, if you use proper supple design patterns, then it would be relatively easy, right?
Bruno: I would like to add that we’re talking about TDD outside-in, and not only test. We’re talking about acceptance tests, not unit tests.
Avanscoperta: Let’s jump to the next question by Federico. “Refactoring a model in an event sourcing system can be tough due to the immutability nature of the stored events. What do you think? Are you going to tackle the event sourcing even in the workshop?”
Bruno: No, because event sourcing is a specific pattern for a specific use case. We can use deep modeling for it, absolutely, but we don't want to deep dive in a specific pattern.
But to answer, if you have some invariant in your aggregate with some complexity, you have to use deep modeling effectively, even if you practice event sourcing.
Supple design is based on capability to be immutable. You should avoid side effects. We apply a pattern called closure of operation, it's a mathematical pattern to return back a type and avoid a mutation. Supple design is dedicated to autonomy and immutability.
Kenny: We don't tackle event sourcing, but it's the same as Eric says. “Domain modelling is separated from your technology.”
We're going to use object orienting, but there are great books, like the one by Scott Wlaschin on functional programming, doing the same. That doesn't really impact the deep modeling. Of course, it impacts the technology. We're using object-oriented methods because most of the world still uses them. But from my experience, actually using event sourcing should make this simpler.
I'm very curious as to why this can be tough due to the immutability nature of the stored event. But yeah, that's not what this workshop would be about.
That in itself is already for me a flag because that means now that you're using event sourcing it's not supple anymore because your modelling code is not easily adjustable. So now a domain expert comes in and says, “Well, we need to go this way”, and then you're like, “Well you know, I use event sourcing”.
I don't think event sourcing is the problem here, it should make it even easier than object-oriented and functional (well I'm not sure about functional programming…), it makes it easier to change your modelling code. So for me for me that’s a very interesting question that I need to understand a bit deeper.
Event sourcing should enable deeper modelling better and more supple.
Avanscoperta: We have another question from our chat. “What tools are you using for your modelling?”
Kenny: We’re aiming at Java and C# developers, but you don't need a deep understanding of C# or Java. We're almost not using any framework, we're only using a unit testing framework.
The rest is just plain old C# or Java code, so Pojo and Poco inside the code. For modeling, we're gonna use Miro in this case, we're not doing a lot of whiteboard modelling, but most we'll be focusing on the code.
Sometimes we go back to the whiteboard modeling to update our domain model, but I think those two tools is what we're mainly gonna use. So you need your favorite IDE, able and capable of running, and Java and/or C# in their latest versions.
Bruno: We should split people in small groups. It means we work together, and if you don't know the language very well, you should be pairing with other folks who might know better, so it should not be a problem for you.
Kenny: We're not gonna focus on the programming language. We're really gonna focus on the modelling aspect inside the code.
Avanscoperta: Time to show a picture that Bruno prepared for the workshop. I know Bruno prepared a very nice picture for this workshop. We spoke about the whirlpool, which we all know about when it comes to Eric's book, but we also have our whirlpool.
Would you say something about this?

Bruno: There is already a picture by Eric Evans about refactoring deeper toward a different insight.
And we thought it was good to create something ourselves.
The first reason is to design our commitment to this workshop.
The second reason is to make the original diagram more human, because if you see the whirlpool process model exploration by Eric is a collection of arrows, but there are no people around. We wanted to illustrate a team and of a conversation with the domain expert, and we also wanted to keep the spirit of the original one, this was the goal.
The third reason is to find a way to embrace all of part three of the Blue Book. It's the reason why you notice on the right, there is a cloud with a storm, and it stands for the breakthrough.
Kenny: The main reason for it being a cloud is because if you've gone through this deeper modelling it can be frustrating from time to time. It can be conflictuous, right?
I always see conflicts popping up, frustration popping up, folks asking, “Why does it take so long to get it right?” And all of a sudden there's a flash and… here’s the breakthrough.
That's why we added that breakthrough in the middle of the team working with their domain experts. Again, we're focusing very much on that collaboration with domain experts even while we're doing code probing.
Bruno: We discussed this with Kenny and as I am a drawer I did a prototype on a notebook. And Kenny said, “Wow, it's correct, but I see something else”, and so on. I then moved to do this on a tablet, as it was easier to communicate. And we wanted to include a conversation. And even here, we iterated a lot to find a good idea to illustrate what the workshop is about, which is, mainly, “We started from nothing. And we're growing the idea. We have a new mental model at the end, and we obtain this feature.”
It's not a survey path, but it illustrates the workshop.
Avanscoperta: Before we finish today, I have two more questions from the chat. Victoria says, “I absolutely love the continuous refactoring approach, but sometimes you have devs who are absolutely terrified of changing anything about the system.”
Kenny: What I usually see is a disconnect, and that’s what Eric talks about a lot, right?
A disconnect with the underlying model. So the code has a disconnect with the underlying model.
And yes, I would be terrified of changing something in a system that I don't understand what will do on the business side, on the domain side.
There's no alignment anymore, and a lot going on… A lot of arrows and wires going to the business.
“So I need to cut the green, the blue or the red wire now? And what does that happen in the business?” That's what we're trying to solve here with Model-Driven Design, which is to keep that intrinsic knowledge of how things work because I know I understand perfectly how this will change my business.
That's why a lot of people are terrified of changing anything about the system because the domain model and the words in the code don't respond to each other.
So if someone is saying, “Kenny, can you change the A, B, C?”, I look at the code and I don't see the A, B, C, and I'm like, “Okay, what is this, and what do I change?” And it doesn't match anymore… And I would be terrified…
I’ve worked in an asset management domain. I was terrified the first month I came in and someone said, “Can you please change this interaction of 2.5 millions?”, and I was petrified. Then someone showed me and I'm like, “Oh, what this person says actually matched my code. Oh, now I feel much more comfortable of changing that code”.
That's what we're trying to tackle, that fear of knowing exactly how this small change impacts my product and my business. And understanding that if I decide to change a certain thing, that can be a high risk change. So let's start collaborating more again with my stakeholders.
I actually witnessed this—a user went into my code and said, "Kenny, this piece of code, this piece of code is wrong. The calculation is wrong, it should be different", and this person was no coder.
And that was nice. This was an economical domain. So it's not totally fair because they could read my calculation in the code a bit because that matches, but the point is that the code surrounding my calculations and the naming surrounding it all made sense to this person who was no coder.
So I could easily change that, push a button, go to production, and fix it. And that's the power, that's why I wasn't terrified of changing the system anymore because I understood exactly what the business was and what the impact of my code was on the business.
Bruno: When we do deep modeling, we suppose we are in a core team and it means we create something new and we are protected by the bounded context.
But if we started in a legacy system, I would prefer to use a bubble pattern, a bubble context, to protect me and to start with a clear and integrity core, not in the pure legacy system, which is very, very difficult and dangerous.
Avanscoperta: One of the pain points we're aiming to solve here is also avoid being so scared and making sure code and business requirements are aligned from start to finish.
Last question, this time from Wouter: “Is there a curve of change frequency? Do the number of larger changes to the domain info get less over time?”
Kenny: It's a very good question. Of course, it depends on your domain, but from my experience, going through a couple of these iterations, like the one I did previously… doing that for a complex domain takes time, like three months, but after three months, the number of large changes went down. All the changes were done in one or two days and it was even so much.
And this was interesting that I came to work one day and I asked, “How is this new change going?”, and they said, “Well, yeah, it's on hold”. I asked why, and they said that the business wasn’t ready for this change. “We went too fast.”
To which I replied, “Okay, we have another problem, but it's a better problem this time, right?”
It depends on the complexity of the domain. It depends on the market you're in. That can highly affect it. But overall, if you do this, and again, I would like to state that you don't do this for more supporting domains, as we call them in Domain-Driven Design because the investment is not worth it, right? You really do this deep modelling more for complex core domains.
And then yes, it's well worth it. The number of large changes to the domain gets less over time, except, of course, when you have stuff like COVID or major things that can screw it up big time.
Bruno: I would like to add that the engagement is fundamental. The more you are engaged, the more it's easier for you to understand everything and make sure everything is precise. And your capability to change some part of your system and of your code become very easy if you apply supple design.
So, effectively at the beginning, you can change a lot of things. If the model is not correct or too naive, for example, but the more you dig inside the model, the more your brain understands everything deeply.
That's the consequence of your engagement.
Kenny: And to finish that one off, I'm again going to stress it—you do it only for core domains. Else we're going to end up with this whole aggregate debate where everyone's using aggregates everywhere.
No, you do it for this particular reason. This is not the silver bullet that we're talking about. We're using it for core domains, for complexity, and there it has a definite payback over time.
Avanscoperta: I would finish off with some suggestions. Is there anything we can recommend to our learners online that they can watch or read?
Kenny: We did a talk at KanDDDinsky 2023, which gives a quick and short overview of what we’re gonna do.
And Bruno and I will work on a blog post to go a bit more in depth on this over the next coming months.
Also, if you need to get started on this very topic, it's either with part three of the Blue Book or watch our video if you want to take less time. Also Nick Tune’s work is amazing, check it out.
Check out Small Talk on YouTube or Spotify.
Credits: Picture by Adrian Cuj on Unsplash
Learn with Bruno Boucard and Kenny Baas-Schwegler
Bruno and Kenny are the trainers of the Deep Dive into Model-Driven Design Workshop.
Check out the full list of our upcoming training courses: Avanscoperta Workshops.
Let's stay in touch! 😊
Subscribe to our Newsletter 📩 and be the first to know when we schedule a new workshop or we publish a new workshop.