Archive for the ‘ddd’ tag
One of my favourite parts of the Domain Driven Design book is where Eric Evans talks about making implicit concepts in our domain model explicit.
The book describes this process like so:
Many transformations of domain models and the corresponding code happen when developers recognize a concept that has been hinted at in discussion or present implicitly in the design, and they then represent it explicitly in the model with one or more objects or relationships.
Lu and I were working on a small application to parse the WCF message log file on our project into more readable chunks whereby each request in the file would be outputted into another file so that it would be possible to read them individually.
We decided to create a little domain model for this since the code seemed to be getting a bit tricky to handle when it was all being written inline inside a main method.
To start with we just had a collection of requests which was an accurate representation of the way that the data was being stored in the log file.
We collected all these requests and then created individual files for each of them. We also grouped these request files under directories by the session that the request was from.
The input/output of our application looked a bit like this:
The next idea suggested for this little application was that it would be cool if we could put the characters ‘FAIL’ into the file name of any requests which failed and also into the folder name of any sessions which had failing requests inside them.
We tried to do this with our original model but everything we did resulted in adding more and more code to the Request object which didn’t seem to belong to it. The tipping point for me was when we ended up with Request.SessionFolderName as a property.
Eventually we realised that what had been implicit would now need to be made explicit and the Session came to be an object in our domain model.
What I found most interesting about this process was that we were always talking about the Session but it didn’t actually exist in our model!
The model in our code now pretty much represents the format in which we out outputting the data and with Session as an explicit concept it makes it much easier to make changes in the future.
One of the things I find a bit confusing when it comes to Domain Driven Design is that some of the higher profile speakers/user group contributors on the subject have expressed the opinion that DDD is more suitable when we are dealing with complex projects.
I think this means complex in terms of the domain but I’ve certainly worked on some projects where we’ve been following certainly some of the ideas of DDD and have got some value out of doing so in domains which I wouldn’t say were particularly complex.
What is Domain Driven Design?
One of the quotes from Jimmy Nilsson’s QCon presentation was that ‘DDD is OO done well‘ and I think there are a lot of similarities between the ideas of OO and DDD – in fact I think DDD has ended up covering the ground that OO was initially intended to cover.
Having our code express the domain using its own language rather than the language of the technical solution seems like an approach that would be valuable in any type of project and my recent reading of Code Complete suggests that this is certainly an approach that was used before the term DDD was coined.
However, if we’re truly doing DDD then in theory we should be modeling our domain with the help of a subject matter/business expert but from the projects I’ve worked on we can very rarely get access to these people so the modeling becomes a best attempt based on the information we have rather than a collaborative effort.
I’m not sure whether it’s actually possible to get a truly ubiquitous language that’s used by everyone from the business through to the software team by taking this approach. We certainly have a language of sorts but maybe it’s not truly ubiquitous.
As Luis Abreu points out, I don’t think there is a precise definition of what DDD actually is but for me the essence of DDD is still the same as when I compared it with OO i.e. Domain Driven Design = Object Oriented Programming + Ubiquitous Language.
What that definition doesn’t cover is the organisational patterns we can use to allow our domain model to fit into and interact with other systems, and I think this is a part of DDD which I underestimated when I wrote my previous post.
It also doesn’t take into account the possibility of doing DDD in a non OO language – for example I’m sure it’s possible to follow a DDD approach when using a functional language.
The value in using a DDD approach
As I’ve written before, I think there is value in applying the patterns of DDD even if we aren’t using every single idea that comes from the book. The approach of using just the patterns has even been coined as DDD Lite.
DDD Lite sounds to me like a particular subset of DDD but I would be quite surprised to find a project which used every single idea from the book, so maybe every use of DDD is merely a subset of the whole idea.
I’m not sure which presenter it was, but at QCon London the idea that we can use DDD to drive out the simplicity of our domain was expressed.
I would agree with this and I also think the idea of creating a ubiquitous language is very useful when working in teams, even if the domain is not that complex, so that we can stop doing the costly translations between the different terminologies people may be using to refer to the same things in the domain.
The idea of striving to make concepts in our code explicit rather than implicit is another idea which I think works very well regardless of the complexity of the project. Being able to look at code and understand what is going on without having to know a whole lot of context is invaluable.
Finally the organisational patterns of DDD, as Dan North pointed out at QCon, are valuable even in a non DDD context. We may not always use the DDD terms for what we are doing but I’ve noticed that a lot of the ways we interact with other systems have a corresponding DDD pattern which will explain the benefits and drawbacks of that approach and where it will and won’t be appropriate.
I know neither of the authors are writing off DDD for projects with less complex domains but I feel the value that the different ideas can give to most projects is sometimes not recognised.
What the book has done well is bring together some very useful ideas for allowing us to write business software and since this is what a lot of us are doing it’s definitely worth looking at where the ideas of DDD can be applied.
One of the big takeaways for me from the Domain Driven Design track at the recent QCon London conference was that the organisational patterns in the second half of the book are probably more important than the actual patterns themselves.
There are various patterns used to describe the relationships between different bounded contexts:
- Shared Kernel – This is where two teams share some subset of the domain model. This shouldn’t be changed without the other team being consulted.
- Customer/Supplier Development Teams – This is where the downstream team acts as a customer to the upstream team. The teams define automated acceptance tests which validate the interface the upstream team provide. The upstream team can then make changes to their code without fear of breaking something downstream. I think this is where Ian Robinson’s Consumer Driven Contracts come into play.
- Conformist – This is where the downstream team conforms to the model of the upstream team despite that model not meeting their needs. The reason for doing this is so that we will no longer need a complicated anti corruption layer between the two models. This is not the same as customer/supplier because the teams are not using a cooperative approach – the upstream are deriving the interfaces independently of what downstream teams actually need.
- Partner – This was suggested by Eric Evans during his QCon presentation, and the idea is that two teams have a mutual dependency on each other for delivery. They therefore need to work together on their modeling efforts.
I think it’s useful for us to know which situation we are in because then we can make decisions on what we want to do while being aware of the various trade offs we will need to make.
An example of this is when we recognise that we have a strong dependency on the domain model of another team where I think the approach that we take depends on the relationship the two teams have.
If we have a cooperative relationship between the teams then an approach where we pretty much rely on at least some part of the supplier’s model is less of an issue than if we don’t have this kind of relationship. After all we have an influence on the way the model is being developed and maybe even worked on it with the other team.
On the other hand if we realise that we don’t have a cooperative relationship, which may happen due to a variety of reasons…
When two teams with an upstream/downstream relationship are not effectively being directed from the same source, a cooperative pattern such as CUSTOMER/SUPPLIER TEAMS is not going to work.
This can be the case in a large company in which the two teams are far apart in the management hierarchy or where the shared supervisor is indifferent to the relationship of the two teams. It also arises between teams in different companies when the customer’s business is not individually important to the supplier. Perhaps the supplier has many small customers, or perhaps the supplier is changing market direction and no longer values the old customers. The supplier may just be poorly run. It may have gone out of business. Whatever the reason, the reality is that the downstream is on its own.
(from the book)
…we need to be more careful about which approach we take.
We are now potentially in conformist territory although I don’t think that is necessarily the route that we want to take.
If we choose to conform to the supplier’s model then we need to be aware that any changes made to that model will require us to make changes all over our code and since these changes are likely to all over the place it’s going to be quite expensive to make those changes. On the other hand we don’t have to spend time writing translation code.
The alternative approach is to create an anti corruption layer where we interact with the other team’s service and isolate all that code into one area, possibly behind a repository. The benefit here is that we can isolate all changes in the supplier’s model in one place which from experience saves a lot of time, the disadvantage of course being that we have to write a lot of translation code which can get a bit tricky at times. The supplier’s model still influences our approach but it isn’t our approach.
I’m not sure what pattern this would be defined as – it doesn’t seem to fit directly into any of the above as far as I can see but I think it’s probably quite common in most organisations.
There are always multiple approaches to take to solve a problem but I think it’s useful to know what situation we have before choosing our approach.
We’ve been doing some work this week around trying to ensure that we have a ubiquitous language to describe aspects of the domain across the various different systems on my project.
It’s not easy as there are several different teams involved but one thing we realised while working on the language is that the language of the business is not the same as the language of the user.
Although this is the first time that I recall working on a project where the language of the user is different to the language of the domain I’m sure there must be other domains where this is the case as well.
In our case the language is simplified so that it makes sense to the user – the terms used by the business make sense in that context but would be completely alien if we used it on the interfaces from which our users interact with the system.
At the moment our domain model represents the business terminology and then when we show the data to the user we refer to it by a different name. The problem with this approach is that there is a mental translation step in trying to remember which business term maps to which user term.
We can probably solve this problem somewhat by having the user terms represented in our Presentation Model but this still doesn’t help remove the translation problem when it comes to discussions away from the code.
At the moment there aren’t that many terms which differ but I’m not sure what the approach should be if there become more in the future, should we have a whole user language as well as a business specific ubiquitous one or should our ubiquitous language be the user language?
One of the underlying characteristic of most of the projects I have worked on is that we have defined our own domain model.
On my current project due to the fact that most of the logic in the system is being handled through other services we decided to use WCF messages as the domain model, meaning that our domain model is being defined externally by the team defining the message contracts.
Internal Domain Model
This is the approach I have seen on my previous projects and if our system does have some level of business logic/behaviour in then it is the approach we want to take if we are following a domain driven approach.
If we don’t have sufficient behaviour then the anti corruption layer will start to become a burden for the benefit it provides and we might be better off not defining our own domain model.
External Domain Model
The reason you might decide to take the approach we have chosen is if the domain in our system is the same as that defined elsewhere, in which case the mapping code would not be adding much value.
The problem with this approach is that we don’t have control over the messages and when changes are made to it our code breaks all over the place. I guess one way to try and overcome this problem would be to use consumer driven contracts.
An additional problem is that it is quite difficult to change the domain when we learn new information since this would require changing the message definitions which are being done by another team. The domain model we have therefore seems less expressive than ones on other projects I’ve worked on and I don’t think we achieve the ubiquitous language as much although certainly the domain terms exist in the code.
Both of these approaches have their merits and each may be appropriate given the right situation.
From my experience the majority of the time we will want to build our own domain model of rich objects. I actually think coding is much more fun when you have your own domain model.
I’ve started to come to the conclusion, while writing this, that if your domain is defined as message contracts then maybe it’s not Domain Driven Design at all, perhaps it’s more about SOA with a Ubiquitous language.
It does feel to me like some of the aspects of DDD are present though, just not all of them.
At the Alt.NET UK Conference which I attended over the weekend it occurred to me while listening to some of the discussions on Domain Driven Design that a lot of the ideas in DDD are actually very similar to those being practiced in Object Oriented Programming and related best practices.
Anaemic Domain Model/Law of Demeter
There was quite a bit of discussion in the session about anaemic domain models.
An anaemic domain model is one where a lot of the objects are merely data holders and do not actually have any behaviour inside them. While it has a fancy name, in OO terms this problem materialises due to our failure to adhere to the Law of Demeter.
My colleague Dan Manges has a brilliant post describing this principle but a tell tale sign is that if you see code like the following in your code base then you’re probably breaking it.
This is often referred to as train wreck code and comes from breaking the idea of Tell Don’t Ask. In essence we should not be asking an object for its data and then performing operations on that data, we should be telling the object what we want it to do.
Side Effect Free Functions/Command Query Separation
DDD talks about side effect free functions which are described as follows:
An operation that computes and returns a result without observable side effects
The developer calling an operation must understand its implementation and the implementation of all its delegations in order to anticipate the result.
The really valuable idea in this principle is that it’s extremely handy if you can clearly separate methods that change state from those that don’t. This is because you can use queries in many situations with much more confidence, introducing them anywhere, changing their order.
It’s not exactly the same but they have a shared intention – helping to make the code read more intuitively so that we can understand what it does without having to read all of the implementation details.
Intention Revealing Interfaces/Meaningful Naming
Intention Revealing Interfaces describe a similar concept to Side Effect Free Functions although they address it slightly differently:
A design in which the names of classes, methods, and other elements convey both the original developer’s purpose in creating them and their value to a client developer.
If a developer must consider the implementation of a component in order to use it, the value of encapsulation is lost.
Bounded Context/Clean Boundaries
DDD’s bounded context describes “The delimited applicability of a particular model” i.e. the context in which is is held valid.
This is quite closely related to the idea of clean boundaries in Clean Code where Uncle Bob states:
Code at the boundaries needs clear separation and tests that define expectations
In both cases we are creating an explicit separation of ‘our code’ from the outside world so to speak. We want to clearly define where ‘our world’ ends by defining the interfaces with which we interact with the outside world.
Anti Corruption Layer/Wrappers
The anti corruption layer in DDD is “an isolating layer to provide clients with functionality in terms of their own domain model.”
It is used to create a boundary for our bounded context so that the models of other systems we interact with doesn’t creep into our system.
The intention in all cases is to have one area of our code which calls 3rd party libraries and shields the rest of the code from them.
Domain Driven Design = Object Oriented Programming + Ubiquitous Language?
While talking through some of these ideas I started to come to the conclusion that maybe the ideas that DDD describe are in fact very similar to those that OOP originally set out to describe.
The bit that DDD gives us which has perhaps been forgotten in OOP over time is describing the interactions in our systems in terms of the business problem which we are trying to solve i.e. the Ubiquitous Language.
From Wikipedia’s Object Oriented Programming entry:
OOP can be used to translate from real-world phenomena to program elements (and vice versa). OOP was even invented for the purpose of physical modeling in the Simula-67 programming language.
The second idea of physical modeling seems to have got lost somewhere along the way and we often end up with code that describes a problem at a very low level. Instead of describing a business process we describe the technical solution to it. You can be writing OO code and still not have your objects representing the terms that the business uses.
There are some things that DDD has certainly made clearer than OOP has managed. Certainly the first part of the book which talks about building a business driven Domain Model is something which we don’t pay enough attention to when using OOP.
For me personally before I read the concepts of DDD I would derive a model that I thought worked and then rarely go back and re-look at it to see if it was actually accurate. Reading DDD has made me aware that this is vital otherwise you eventually end up translating between what the code says and what the business says.
Ideas around maintaining model integrity are also an area I don’t think would necessarily be covered in OOP although some of the implementations use OOP ideas so they are not that dissimilar.
Why the dismissal of DDD?
The reason I decided to explore the similarities between these two concepts wasn’t to dismiss Domain Driven Design – I think the framework it has given us for describing good software design is very useful.
Clearly I have not mapped every single DDD concept to an equivalent in OOP. I think DDD has given a name or term to some things that we may just take for granted in OOP. Certainly the DDD ideas expressed around the design of our model are all good OOP techniques that may not be explicitly stated anywhere.
I wanted to point out these similarities as I feel it can help to reduce the fear of adopting a new concept if we know it has some things in common with what we already know – if a developer knows how to write OO code and knows design concepts very well then the likelihood is that the leap to DDD will not actually be that great.
It would be really good if we could get to the stage where when we teach the concepts of OOP we can do so in a way that emphasises that the objects we create should be closely linked to the business domain and are not just arbitrary choices made by the developers on the team.
Maybe the greatest thing about DDD is that it has brought all these ideas together in one place and made them more visible to practitioners.
I am very interested in how different things overlap, what we can learn from these intersections and what things they have in common. It’s not about the name of the concept for me, but learning what the best way to deliver software and then to maintain that software after it has been delivered.
During the discussion about Domain Driven Design at the Alt.NET conference I felt like the idea of the Rich Domain Model was being represented as the only way to design software but I don’t feel that this is the case.
As always in software we never have a silver bullet and there are times when Domain Model is not necessarily the best choice, just as there are times when OOP is not necessarily the best choice.
To quote from Martin Fowler’s Patterns of Enterprise Application Architecture
It all comes down to the complexity of the behaviour in your system. If you have complicated and everychanging business rules involving validation, calculations, and derivations…you’ll want an object model.
What are the alternatives?
Domain Model is not a silver bullet and Martin suggests two alternatives when a model driven approach may not be the best choice
- Transaction Script – The best thing about this is its simplicity. It is easy to understand as all the logic is in one place and it is a good choice for applications with a small amount of logic.
- Table Module – This is a database driven approach with one class per table. If the system you’re working on is using a very table-orientated approach to storing data then this approach may be a good choice.
I think in order to make a Domain Model approach work, everyone in the team (including QAs,BAs etc) needs to buy into the idea and you need some people who have experience in using it so that you can use it in a pragmatic way.
While we have some great tools and techniques available to us in the world of software it is important to remember what problem we are trying to solve and pick the appropriate tool for the job.
I’ve edited the phrasing of this after conversation – I intended to refer to the Rich Domain Model concept used in Domain Driven Design and was presenting alternatives to this rather than to DDD as a whole.