I’ve recently been reading Eric Evans’s Domain Driven Design book, and it’s made me seriously reflect on my development experiences. All to often in majority of the projects I’ve been involved with, there is this, almost automatic approach, to just develop software in a very technically layered manner, without any real regard to domain modelling and enriching that model with business functionality. i.e. you have many layers in your application(Facade, Service, Repository, Managers etc), with one main “layer” responsible for most of the domain type logic, and your “domain” classes are nothing but anaemic glorified data containers!
I don’t think that we as developers just automatically assumed this kind of development practice. I think we might have been surreptitiously conned into it by past languages and practices which possibly reinforced bad design. For example, I remember back in the day when Visual Basic came onto the scene and introduced the notion of property sheets, and public getters/setters – and then subsequently the advent of JavaBeans which followed the same sort of approach which in the end, I feel perhaps could have influenced software developers over the years to accept that anaemic objects with exposed internals were OK. Quite frankly, after reading about DDD, this is just plain wrong! 🙂
I’ve discovered that there is an increasingly growing community of DDD advocates out there, and I can’t thank those of you enough, who have shared their experiences with me, and helped me to learn more about DDD, and how to effectively introduce it into a project. As with most software development concepts, when learning them, there is always an abundance of sample code out there as well as opinions, and quite frankly, majority of the time, there are never those samples which manage to convey enough complexity to fully understand design challenges or pitfalls. I find when in this type of position, StackOverflow is usually my friend, but sometimes that can just be a source of conflicting information and advice – not the greatest when you’re trying to learn the correct approach.
When I began to actively introduce DDD into my projects, I came up against a problem of allowing access to outside application services from within my domain model. Huh?! I hear you say. Well I mean, I had arrived at a point where my domain objects – which are now enriched with business logic and rules(data and behaviour) – needed to access outside services which do other related operations on the domain objects’ behalf. My question was how do I go about accomplishing this in the most strictest of DDD terms?
This is what this series of blog posts will try to offer by means of samples showing my journey of the many different approaches I’ve attempted at solving the problem. All these approaches will be available on Github. These samples are just a journal of my evolving understanding of DDD. Feel free to take from them what you will, but I do not profess them to be the silver bullet when faced with the same challenges. As with each of these sample approaches, I have tried out, I have experienced their pain, and their joy.
The “real-world” problem
For the purpose of discussion, lets assume we have the concept of an order made up of multiple order items which basically represent a customers’ order of items from a shop. To make this problem a little more digestible, I’ll attempt to express it as a user story.
As a customer
I want to place my order, with the respective supplier(s)
and be notified whenever any order item is ORDERED
So that I know when the order item is on its way.
- When placing the order item with the supplier, if the supplier responds with ORDERED, then the customer must be notified immediately via email.
Obviously in this contrived sample, we’re missing other blatantly obvious business actions, like taking payment etc., but to keep the focus on the problem at hand, we want the focus to remain on how the action of placing an order makes calls outside of the entity itself, and how it raises notifications. All this story is about is making notifications based on results from external calls, but how does one design this? That is what we’ll see evolve over each of the samples.
When each line item is sent to the respective supplier, the supplier may choose to fulfil the order immediately and will respond with the result of ORDERED. In such a case we need to notify the customer of this state via e-mail. The supplier may not fulfil the order immediately, in which case they would respond with the result of PENDING. The supplier may choose to tell us at a later date that it is fulfilled – but we won’t be covering that situation here. The business requirement is that when the order item transitions to the ORDERED state, then we need to notify the customer.
Now, to highlight the problem, lets say I have a method in my order item which will place the order on my behalf. However this has to occur through an external service. On receipt of the result of that action, we need to determine additional operations – i.e. possibly sending the email to the customer. How does the domain object here(the order item) gain access to the services responsible for carrying out this work? I’m talking about both the placing of the order item with the supplier, and the sending of the email to the customer. There are a few approaches, and so begins my journey to find the best solution…