About two years ago, the company that I work for started to develop a new product, and since we predicted that the product would grow to be pretty big and complex, we decided to apply Domain-driven design (DDD) to the development process. It was my first project running Domain-driven design so I learned quite a bit along the way.
What follows is my list of our most important lessons...
1. Bounded contexts are hard to define
Bounded context is a key element in Domain-driven design, but they can be hard to define. I suspect that we might have ended up making our bounded context too small. This might or might not be a problem. It has definitely caused us more work, but as we're going towards micro services, it might actually have been good for us in the long run.
After 2 years in the project, I'm still not 100% sure of how to best define our bounded contexts.
2. Layering your application is great, but don't overdo it
Another corner store in DDD is layering your application. Some of the benefits are functionality-reuse, less coupling as well as making the application more testable.
I suspect that we over-layered our application, i.e. there are layers that merely consist of model mappings or just pass the execution to another layer. This leads to more code to maintain, which in turn costs money and resources. So make sure that you don't over-layer your application.
This leads us to...
3. Plan your architecture according to your resources
Domain-driven design can cost a lot to implement and it might not be the best architecture for smaller projects. If you are running a project that is medium-sized or bigger, DDD may be a good fit for you. But it's not all black and white - you don't have to do everything that DDD states. I would suggest that you select the pieces that fit your project, budget and goals the best.
4. Don't try to optimize the Ubiquitous Language
I think most developers automatically are looking for patterns, similarities and optimizations but that does not work well with the Ubiquitous Language. If "Persons" and "Customers" look really similar, don't be tempted to join them unless they in fact are 100% the same. Yes, sometimes the same personas use different names for the same thig, but this is actually pretty rare.
Yeah I know, this one ought to be pretty obvious, but we fell into the trap a couple of times.
5. Running a DDD-project with unclear demands can be expensive
Not all processes and/or business demands are well defined when you're starting a project. We found ourselves in a place where we had to do quite a bit of trial-and-error since no one was 100% sure how the end product should look or work. Due to the increased mass of code that DDD-project may produce, these experimentations might get pretty expensive. If I could do it all over again I might have chosen to write features with unclear demands more light-weight and reserve time in the future to fully adopt all of the DDD-patterns once the demands where final.
6. We could have done more with value objects
So we started working with value objects a bit late in the project. Value objects are really nice and I will bring them on from the start in my next DDD-project.
7. Continuous integration is great
Even if we started with a small team (which grew over time) we went down the CI-road from the start. Best decision ever - saved us so much time and made the code so much better!
What's your learnings from DDD? Thoughts on mine? Please leave a comment below...