Domain Driven Design: A Step by Step Guide - Part 1

This article was created and edited (with permission) from a series of posts on Casey's blog.

Getting started

There is a lot of interest in DDD recently, both in the book, and in the methodology, and in the buzzword.

As a book and methodology, DDD is an excellent way to approach complex software problems, and make them far more understandable and manageable. As a buzzword, DDD is in danger of being corrupted like many other good software practices.

To try and clear up some of the confusion around DDD, I am intending to start a series of articles, covering aspects of DDD and trying to demystify it.

Domain Driven Design is actually pretty simple. It really isn’t that hard. That said, developers seem to have a hard time grasping it. I put this down to a great deal of inexperience, with many people who have just read the book in a cursory way saying “we are doing domain driven design” – these people then confuse the issue for others.

Very few people could claim to have done full-on-balls-to-the-wall DDD, due to the relative “newness” of the book, and the time the ideas it contain talk to peculate down. In addition I work in the .Net space, where DDD has taken longer to penetrate than the Java space where the book was formed. I have practiced DDD in some way on three live projects, to a lesser degree in some aspects, and closer to the “one true way” in others. So, like almost everyone doing DDD, I am no expert, beware anyone that claims they are.

That said, some of the “community” have done more with DDD than others. Their wisdom is well worth picking up along the way – with no specific favouritism or deliberate omission, I heartily recommend you read stuff by Jimmy Nilsson, Greg Young, Colin Jack, Udi Dahan and of course Eric Evans.

Some take the book, Domain-Driven Design: Tackling Complexity in the Heart of Software, to be “the one true bible”, but like everything in software, it is only a good starting point. That said, if you are stepping into DDD with more than a gentle dip in the water, this book will prove to be a very solid basis for going forward without drowning – I recommend it strongly.

For a quicker introduction, I recommend (and have done so in the past), downloading the InfoQ eBook Domain Driven Design Quickly. This distillation of Eric’s work provides a really strongly overview of what DDD is, and how it can help you.

When you remember that DDD is really just “OO software done right”, it becomes more obvious that strong OO experience will also stand you in good stead when approaching DDD. To do my part, I am intending to start a series of blog posts covering various aspects of DDD, to try and make DDD seem somewhat more approachable, and hopefully to try and show that DDD is a whole lot simpler than many make it appear.

The Ubiquitous Language

Britain and America are two nations divided by a common language
(George Bernard Shaw / Oscar Wilde)

It could be said that the business and developers are two nations divided by a common language. If you listen to conversations between developers and the business guys they are writing code for, they seem to speak the same language, but often have entirely different meanings.

This disjoint is what the concept of the Ubiquitous Language (or UL) is intended to eliminate in Domain Driven Design.

The concept is simple, that developers and the business should share a common language, that both understand to mean the same things, and more importantly, that is set in business terminology, not technical terminology.

Developers have historically had a hard time with talking to the business – developers are by nature technical, and have a bad habit of letting their technical “geek” terms leak into their conversations. We are all guilty of it at the best of times.

The Ubiquitous Language in DDD is a negotiated language between the Domain Experts and the technical guys – but the rule is that the Domain Experts lead and the technical people follow. As the UL evolves, and this may take weeks or many months, the language becomes more and more refined.

Eric Evans has some good examples in his book of how the UL is drawn out of the conversations between the domain experts and the development team, so I won’t duplicate them here – suffice to say you should be listening to how your users and domain experts refer to things, and try and fit in with their language.

One thing to bear in mind here is that although the UL is drawn in the language of the business, it can also include things that might seem like technical terms.

A recent conversation on a DDD list discussed things like Paging and whether these belonged in the domain. Some people then decided that these were technical terms, and on their (IMO misunderstanding) reading of the book, they stated that words like Paging are technical terms and shouldn’t be in the UL

That assumption has two basic problems:

1) Users have adopted terms like Paging as their own. They know what Paging means … it is present in 90% of the applications and web pages they use. So Domain Experts adopt this language when expressing their requirements. They probably won’t use a term like Paging in regard to the domain, but they may well use it in their user stories, use cases or requirement documents. Whether this concept carries through to the domain is an implementation issue.

2) There are many technical terms that exist in the UL already, Eric listed them in the book. These are common pattern names, that the technical team introduce to try and help the Domain Experts formalise their concepts. So terms like Specification and Event may well appear in the UL.

The Ubiquitous Language is the foundation of Domain Driven Design, it is the basis on which your technical team can become part of the business, and work in their interests, rather than being see as “the geeks who sit in the corner and deliver buggy software” – don’t be two departments divided by a common language

Bounded Contexts

The idea of a Ubiquitous Language (UL) can seem like it is too all encompassing. Indeed it is – unless you are working on a very simple application, one language just isn’t enough. Not only that, but a single “mammoth model” will also be too large, unwieldy, and eventually turn into a Big Ball of Mud. That is where the idea of Bounded Contexts come into the game.

Bounded Contexts in DDD is one of the “advanced” topics, it doesn’t even appear in the book until well over halfway. However, I am going to introduce it now, so that later in this series, the terms don’t become an obstacle… in the book you could flick a few hundred pages ahead, here you don’t have that luxury. Feel free to skip this post until later if it doesn’t make much sense now.

Suffice to say you could model your entire domain as a single thing, with a language to cover everything, but if you look at the business you are trying to model, it is unlikely that is how they see things.

An example of Context here would be within an ecommerce system. Although you could model this as a single system, it would also warrant splitting into separate Contexts. Each of these areas within the application have their own Ubiquitous Language, their own Model, and a way to talk to other Bounded Contexts to obtain the information they need.

Example Ecommerce Contexts

Well the obvious starting point would be the customer facing Context – let’s call this the Shopping Context – this is the part of the application that lets a customer browse the catalogue, search for items, pick items, and put them in their shopping basket.

You may be thinking this is it for a simple ecommerce system – and for a simple system it probably is. However on larger systems there are other Contexts that should probably come into play

When the customer clicks “checkout” then we need to process that order, this is going to involve the Ordering Context to take the shopping basket, process the payment and to create the relevant instructions for picking, the Inventory Context (which may have been involved earlier to display “items in stock”) to reserve the items in the warehouse, and the list may go on depending on the scale of the entire application.

Each of these Bounded Contexts has a specific responsibility, and can operate in a semi-autonomous fashion. By splitting these apart it becomes more obvious where logic should sit, and we can avoid that BBOM.

Bounded Context or Context?

The term Context is a general description of a grouping of concepts, the term Bounded Context is more specific – a Bounded Context is an area of your application which has explicitly defined borders, has it’s own model, has it’s own Model, and maintains it’s own code. Within the Bounded Context everything should be strictly consistent.

Usually, we can use the terms Context and Bounded Context interchangeably, though I tend to talk in terms of Context about the business side of things, and the term Bounded Context about the technical implementation.

In essence, a Bounded Context is an application in it’s own right. By splitting your large application into many Contexts, you gain all the advantages of modularity, separation of concerns and loose coupling – but on a much larger scale than many developers often think.

Surely Bounded Context’s Must Interact?

Indeed they do need to. Within DDD this is done using a Context Map. Again, I will skip the details for now, but suffice to say, a* Context Map* is a clearly defined way of talking between Bounded Contexts. The book has a number of examples of how this could be implemented, and many more will become apparent as you progress. The Context Map is the contract your Bounded Context provides to the outside world, other Bounded Contexts

In Conclusion

We skipped a fair way ahead here, so don’t get too stuck up on Contexts, just bear in mind they exist, and they resolve issues around conflicting Ubiquitous Language terms, allow Models to focus on specific problems, and provide a loosely coupled application architecture.

There is no database

Do not try to bend the spoon; that's impossible. Instead only try to realize the truth: There is no spoon.
The Matrix

We now move on to explain what on the face of it is a pretty dumb assertion – there is no database in DDD!

I’m sure right at this point, jdn is reaching for his keyboard to point out that I am dangerously close to repeating The Tao of Domain Driven Design. Yes, I love my mystical analogies!

But if you think about this apparently stupid statement, in the context of Domain Driven Design, it has a subtle and important point – DDD is all about the domain, not about the database, and Persistence Ignorance (PI) is a very important aspect of DDD.

What is Persistence Ignorance and Why Does it Matter?

This relatively new principle says we should try and keep our code free of anything that refers to, relates to, or propagates, aspects of the mechanism we intend to use for persisting our data – traditionally the good old relational database.

Early versions of this were focused on the imaginary requirement that we should be able to change from SQL Server to Oracle with relatively little effort. Changing connection strings wasn’t good enough, so various frameworks and adapters appeared to try and make this happen. Frequently however, knowledge of not only what specific database would be used, but even the fact that the data would be stored in a database leaked into our objects.

With persistence ignorance, we try and eliminate all knowledge from our business objects of how, where, why or even if they will be stored somewhere.

This is a major step towards decoupling our real code and logic from infrastructure concerns like data access, it therefore benefits us hugely in terms of testing, maintenance and change.

Where Does Persistence Ignorance Appear in DDD?

Pretty much everything in DDD is designed around PI, the basic pattern that is used for accessing Entities and Value Objects (the core building blocks of DDD which I will cover in my next post) is the Repository.

I won’t cover Repository in detail at this point in the series, but the primary purpose of a Repository is to represent itself as a collection, albeit a collection with fairly specific and advanced querying. The Repository provides a simple and powerful mechanism for making your Domain totally unaware of the actual persistence framework you are using behind it.

As a Repository is a collection, anything that uses it is completely unaware of where the Entity or Value Object may or may not have been stored.

So Why “There Is No Database”?

Domain Driven Design states specifically, in the name, why – we are designing our applications from the point of view of the Domain, and the Domain is drawn from the Ubiquitous Language we negotiate with our Domain Experts.

If we were to start with a database the it would be Database Driven Design. If we were to consciously or subconsciously bring elements from the database into our Domain, then we would risk compromising our Domain model purely to support the persistence layer we had chosen.

In Conclusion

Start from the premise “there is no database”, try to evolve the UL, the Domain, and everything that entails, without concern to the database you may or may not use in the end.

Eric covers in his book points where you may need to compromise one side or other, and good reasons for doing so, but if you start from a pure point of view, at least you will be making informed and explicit decisions about your compromises.

That's it for now, but stay tuned for further discussion on the topic of DDD in future articles.

Reference:

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter” - Eric Raymond