Domain Driven Design - Step by Step
Domain Driven Design - Step by Step
Domain Driven Design - Step by Step
com
Contents
Foreword............................................................................................................................................. 4 The Ubiquitous Language ................................................................................................................... 5 In Conclusion ................................................................................................................................... 5 Bounded Contexts............................................................................................................................... 7 Example Ecommerce Contexts........................................................................................................ 7 Bounded Context or Context? ........................................................................................................ 8 Surely Bounded Contexts Must Interact? ...................................................................................... 8 In Conclusion ................................................................................................................................... 8 There Is No Database .......................................................................................................................... 9 What is Persistence Ignorance and Why Does it Matter? .............................................................. 9 Where Does Persistence Ignorance Appear in DDD? ..................................................................... 9 So Why There Is No Database? .................................................................................................. 10 In Conclusion ................................................................................................................................. 10 Command Query Separation as an Architectural Concept ............................................................... 11 What Does CQS Mean at an Architectural Level........................................................................... 11 Does This Mean We Have More Than One Set of Data? .............................................................. 11 Duplication of Data ....................................................................................................................... 12 In Conclusion ................................................................................................................................. 12 Entities and Value Objects ................................................................................................................ 13 Entities .......................................................................................................................................... 13 Value Objects ................................................................................................................................ 13 Hey, Ive Heard of These, We Have Them in .Net! ....................................................................... 13 So Entities and Value Objects Just Store Data? ............................................................................ 14 And We Put These Things Into Repositories Right? ...................................................................... 14 In Conclusion ................................................................................................................................. 14 Where is the Code? A Brief Interlude ............................................................................................... 15 Aggregates and Aggregate Roots ...................................................................................................... 16 A Simple Example .......................................................................................................................... 16 So What is the Point of an Aggregate? ......................................................................................... 16 Restrictions on Aggregates and Aggregate Roots ......................................................................... 17
In Conclusion ................................................................................................................................. 17 Services ............................................................................................................................................. 18 So Domain Services Are What? ............................................................................................. 18 Shouldnt Logic Be on the Entities Directly? ................................................................................. 18 So What Are the Characteristics of a Good Domain Service?....................................................... 18 Some Examples of Services ........................................................................................................... 18 Services in the Ubiquitous Language ............................................................................................ 19 In Conclusion ................................................................................................................................. 19 DDD: What Kind of Applications Is It Suited To? .............................................................................. 20 Where is Domain Driven Design a Good Fit? ................................................................................ 20 Internal Applications ..................................................................................................................... 21 Outsourced Applications ............................................................................................................... 21 ISV Applications............................................................................................................................. 21 Data Centric Applications.............................................................................................................. 21 The Bad News................................................................................................................................ 21 The Good News ............................................................................................................................. 21 In Conclusion ................................................................................................................................. 22 DDD: The Repository Pattern ...................................................................................................... 23 Repository Is Just A Collection ................................................................................................ 23 Repository Is Just A Facade...................................................................................................... 23 Repository Is Not A Data Access Layer ................................................................................... 23 Repository Is Persistence Ignorance ....................................................................................... 23 Repository Is A Collection Of Aggregate Roots.................................................................. 23 What Sits Behind A Repository ................................................................................................ 23 In Conclusion .............................................................................................................................. 24 DDD: Living In The Enterprise ........................................................................................................... 25 What is SOA Anyway? ............................................................................................................... 25 Our Ecommerce Example ......................................................................................................... 25 SOA Services as a Facade to Bounded Contexts .................................................................... 26 In Conclusion .............................................................................................................................. 26 Reference .......................................................................................................................................... 27 Fundamental Patterns .................................................................................................................. 27 Good Online Reading .................................................................................................................... 27 Books ............................................................................................................................................. 27
Foreword
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 short blog posts, covering aspects of DDD and trying to demystify it. Domain Driven Design is actually pretty simple. It really isnt 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 courseEric 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 Erics 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.
In Conclusion
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 dont be two departments divided by a common language
Bounded Contexts
It was brought up indirectly in a comment on my last post the idea of a Ubiquitous Language (UL) seems like it is too all encompassing. Indeed it is unless you are working on a very simple application, one language just isnt 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 ofBounded Contexts come into the game. Bounded Contexts in DDD is one of the advanced topics, it doesnt 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 dont become an obstacle in the book you could flick a few hundred pages ahead, here you dont have that luxury. Feel free to skip this post until later if it doesnt 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.
In Conclusion
We skipped a fair way ahead here, so dont 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 Again prompted by discussion on the DDD Yahoo list, this post is intended to explain what on the face of it is a pretty dumb assertion there is no database in DDD! Im 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.
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.
Duplication of Data
We spend a great deal of effort maintaining data, maintaining integrity, maintaining consistency, and some fool wants to duplicate this problem all over, now we have two lots of data to manage and synchronise! Well, no. When you think about it, this is just data for read purposes. And that means that this data can be a subset or a combination of data from our Domain. It could be created by events being published from the Domain, or it could be created by taking a snapshot of the Domain data. The only issue that really exists is that this data could be stale or inconsistent it may be 5 seconds out of date, or 10 seconds, or maybe just 1 second but this data may not be up to date. Well, of course it may not be up to date but is any of the data in your system really up to date? Even if you just requested it from your Domain, and it appeared on screen, before you hit any key on your keyboard, that data is already stale by the time you press update someone or something else may have modified the data. Eventually the data may be up to date and consistent, it just may not be the instant you request it. So yes, the data may be stale, but is that really an issue? (hint: the answer is no)
In Conclusion
It may pay to split your Reporting concerns from your Domain concerns, keeping your Domain clear of ad-hoc reporting concerns, and UI concerns. It may also be far more effort than it is worth if the system does not have either massive numbers of these kinds of queries, or just is not that complex. However, bear in mind that this is a good option for allowing the Domain to evolve without concerns from other parts of the wider application leaking into it, and is a good tool to have ready when you face this issue.
Entities
this is my Entity, there are many like it, but this one is mine The key defining characteristic of an Entity is that it has an Identity it is unique within the system, and no other Entity, no matter how similar is the same Entity unless it has the same Identity. Identity can be represented in many ways on an Entity it could be a numeric identifier (the classic CustomerID), it could be a Guid (the classic oh never mind), or it could be a natural key (like the CustomerNumber your Customer was given by your CRM system when they first bought from you). Examples of common Entities are: Customer, Product, Container, Vehicle Whichever way you choose to represent it, an Entity is defined by having an Identity.
Value Objects
The key defining characteristic of a Value Objects is that it has no Identity. Ok, perhaps a little simplistic, but the intention of a Value Object is to represent something by its attributes only. Two VOs may have identical attributes, in which case they are identical. They dont however have any value other than by virtue of their attributes. Another aspect common to VOs is that they should probably be immutable, once created they cannot be changed or altered. You can create a new one, and as they have no identity, that is just the same as changing another one. Examples of common Value Objects: Money, Address, ProductCode
In Conclusion
The things in your business will usually be represented by Entities and Value Objects in DDD. They form the shape of your Domain, and would generally be the things you draw up on that class diagram on the wall.
A Simple Example
In all Object Oriented programming we are used to dealing with objects that have references to other objects, and in DDD it is no different. For example, our Customer may have a reference to the customers Orders. An Aggregate is slightly different, where as Customers and Orders can exist in the system independently, some Entities and Value Objects make absolutely no sense without their parent. The obvious example following on is Orders and OrderLines. OrderLines have no reason to exist without their parent Order, nor can they belong to any other Order. In this case, Order and OrderLines would probably be an Aggregate, and the Order would be the Aggregate Root The rule of Cascading Delete is sometimes cited as a good way to tell if you have a group of Entities or VOs that should be an Aggregate if the parent, in this case the Order, was deleted all other parts of that Aggregate below Order would be deleted too. So if it doesnt make sense that a parent being deleted would also delete all children, then you dont have an Aggregate, you just have a good old fashioned reference.
In Conclusion
Aggregates provide a logical grouping of Entities and Value Objects that belong together at all times. An Aggregate Root is the gatekeeper to the Aggregate. Each Aggregate is treated as a single unit for persistence purposes. By logically grouping Entities and VOs in this way, we provide a mechanism to strictly manage a grouping of objects, and a way to allow us to treat a number of different Entities and VOs as one.
Services
There can be no word more common in development, and no word used for such a multitude of different things as service It was therefore unfortunate that Eric Evans introduced yet another concept of Service in DDD, one which has since been referred to by some as a Domain Service. However, people often use the term Service in isolation, as Eric did in his book so if it is in relation to the Domain, it is probably what I prefer to call a Domain Service otherwise it is likely to be one of those other services.
The first two of those are pretty obvious and easy to apply, the last is in general a good definition of a Service, and although some would argue there is no such thing as stateless, dont express state explicitly, and presume instance of your Services should not affect each other.
After all, apart from needing to deal with the items in the Shopping Basket, these operations may well require communication with other services, calculation and pricing engines, external suppliers in other words, they have a lot of responsibilities that we do not want to bring into our Entity. Now instead of our ShoppingBasket having .GetTotalPrice and .GetShippingCost methods, we can use a Domain Service to get this information, and keep our Entity focused on the real tasks, managing the items in the ShoppingBasket
In Conclusion
Services provide a way of expressing actions and operations within our domain. Where as Entities and Value Objects, the things, provide the building blocks, Services provide the plumbing between them and allow us to express more abstract concepts. Just beware of creating an anaemic domain model; Services are there to support Entities and VOs, not to strip their logic from them.
Complexity
The subtitle of Eric Evans book says it all - Tackling Complexity in the Heart of Software DDD is a way of making complex systems more manageable, better understanding their intricacies, and simplifying a subject that could otherwise be overwhelming i.e. avoiding a classic big ball of mud. We often end up with a Big Ball of Mud when we started out with a fairly sketchy idea of the requirements we had, and built our software in such a way that rigidity set in early on. Over time as new requirements evolve, we bolt them on to what we had before, and piece by piece we end up with our Mud Ball or as I like to imagine it a Borg Cube where all your code has been assimilated, and is now part of the collective. By applying DDD we can break that complexity down into methods of extracting better models from our users and domain experts, and apply software patterns that let us add and evolve to the model, without it becoming a rigid monolith.
What DDD is good at is drilling deep into a business model, and turning that business into a software model.
Internal Applications
Obviously from what I have said so far, DDD is best suited to large projects, where the development team is in-house with the business they are providing a solution for. This ensures that you can gain maximum benefit from what DDD has to offer.
Outsourced Applications
If your development team is outsourced, but writing a bespoke application for a single client, then DDD could be made to work. The key to doing this successfully would be ensuring you had constant access to domain experts, and that their time was not in high demand elsewhere. Constant verification with the Domain Experts would be an important aspect of making this work, and obviously this would be easier with the team on the clients site.
ISV Applications
By their nature, ISV applications have two qualities that are not a good fit for DDD they have very generic requirements, and they have highly user customisable models. These kind of applications may well benefit from a lot of the common sense in DDD, and some of the patterns, but DDD will be no magic bullet here.
will find your software becoming more flexible, more reactive to your audience, and easier to understand just dont expect miracles, and beware of over complicating your code for the sake of it sometimes simpler really is better.
In Conclusion
There are no hard and fast rules about what DDD is best suited to, and I just made those statistics up, but no software methodology is going to be the miracle cure. Take from DDD what you think benefits you and your situation but accept that it cannot be everything to every person.
DDD: The Repository Pattern I seem to have taken a fairly long time to get here, and it has been mentioned in passing, but now we get to the last major part of the Domain Driven Design picture Repository. In traditional architectures, your application talks to some kind of database layer, and asks it to save or retrieve your objects. DDD is slightly different, after all, remember I said There is no database Of course, there is a high likelihood you do *actually* have a database, but the Repository pattern ensures you need to take little to no concern of it within your domain. Repository Is Just A Collection The primary thing that differentiates a Repository from a traditional data access layer is that it is to all intents and purposes a Collection semantic just like IList<T> in .Net Repository Is Just A Facade While Repository pretends to be a Collection to your domain, it is actually just a variation on the Facade pattern it takes a complex subsystem (persistence or the database), and wraps it with a simpler interface (a Collection) Repository Is Not A Data Access Layer Well, at least not in the traditional sense it doesnt talk in terms of data it talks in terms of Aggregate Roots. You can tell your Repository to add an Aggregate Root into its collection, or you can ask it for a particular Aggregate Root. When you remember that Aggregate Roots may comprise one or many Entities and Value Objects, this makes it fairly different to a traditional DAL that returns you back a set of rows from your database tables. Repository Is Persistence Ignorance An important part of any properly decoupled architecture is Persistence Ignorance your application or domain should be completely unaware of how or even if your data is persisted it should just expect it to happen. In DDD the Repository pattern achieves this by a combination of the first three headings above it pretends to be a collection, acts as a facade onto your actual persistence layer, and it does not act like a DAL The Repository is the seam between your domain, and the technical implementation you use to store and retrieve your data. Repository Is A Collection Of Aggregate Roots The Repository pattern is not just a thin DAL it is responsible for talking in Aggregate Roots only. A single Aggregate may contain 2,3 or more Entities and Value objects so our Order entity may also contain OrderLines, there would not be a Repository for OrderLines, it would be up to the Order Repository to persist an Order and all the OrderLines it contains. What Sits Behind A Repository Pretty much anything you like.
Yep, you heard it right. You could have a database, or you could have many different databases. You could use relational databases, or object databases. You could have an in memory database, or a singleton containing a list of in memory items. You could have a REST layer, or a set of SOA services, or a file system, or an in memory cache You can have pretty much anything your only limitation is that the Repository should be able to act like a Collection to your domain. This flexibility is a key difference between Repository and traditional data access techniques. In Conclusion The Repository pattern is a Facade, that abstracts your persistence away from your Domain. On one side it pretends to be a collection on the other it deals with the technical concerns of your persistence implementation. Repository provides us with a mechanism to achieve Persistence Ignorance in our Domain.
SOA Services as a Facade to Bounded Contexts Separation at a local level is good for isolating change and for keeping a logical split of things that do not belong together. On a wider scale, separation allows you to distribute components of a DDD application as the enterprise requires. An individual Bounded Context in DDD is a self contained application; it just doesnt have a user interface like a traditional application does. Instead it has a Context Map which could well be the set of services that fulfils our requirement to play nicely in the SOA Enterprise. These services could be old fashioned web services, or a REST layer, depending on the requirements; they can talk via a message bus, via synchronous or asynchronous requests, or via RPC requests. Within the Bounded Context we have a full Domain, we have a full set of Entities, VOs, Domain Services, Repositories and a persistence layer. So we have our DDD application and we can have as many or as few of these as we need. In Conclusion When you need to think of a distributed system, think of individual Bounded Contexts as miniature applications sitting behind a services layer.
Reference
Fundamental Patterns from: http://domaindrivendesign.org/discussion/messageboardarchive/Glossary.html
Entities Value Objects Repositories Bounded Context Context Map Aggregates Services Repositories