I’ve heard many times that DDD should be applied to complex, interesting domains only. Even some experts that I deeply admire say that, so it must be true, right?
The problem is that I’ve never heard what exactly makes a domain interesting or complex. Especially, what makes it interesting or complex enough for the purpose of DDDifying it. I think the problem is we’ve been asking the wrong question here.
This tweet by @DDD Borat summarizes my thinking perfectly:
But first let’s have a look at two examples that shaped my opinion on the subject.
Case study # 1. Anemic domain model. Boring, boring, boring LOBA (BBBLOBA).
A few years ago I’ve worked on an e-commerce system. We’ve covered basically everything you could imagine online store does, starting with displaying catalog, managing promotions, calculating prices, checkout, through emails, payments integrations, to all the backend stuff that customers never see, like refunds or shipments integration.
The business logic was randomly divided between controllers, data access classes and stored procedures. There was no business logic layer whatsoever (at least not when I started there).
One day I was particularly frustrated. Looking at yet another property bag which was proudly (and inaccurately) called our domain entity, I mumbled something about Anemic Domain Model. My colleague heard it and he sighed. “Yep, no wonder we have anemic domain model here”, he said. “There’s no interesting business logic. That domain is just soooo boring.”
I didn’t know what to say. I’ve just spent a week tracking how refunds are calculated. I found a bug, which was rejected by our QA saying “It’s too complicated, I’m not raising it”. If that wasn’t an interesting piece of business logic, then I have no idea what else it was. So I only nodded my head in faked agreement and went back to work.
Case study # 2. Domain crunching applied. Boring, boring, boring pet project.
A few months ago together with my boyfriend we got really pissed off with the mess which is called our personal finance. We didn’t know exactly where our money went and how much we spent. We used Excel before, but that didn’t seem good enough anymore. Our finances got more complicated over time. Also our expectations were higher. After a few years of tracking expenses, we knew what we wanted out of the app.
We did some research, I checked dozens of apps and none of them fit our criteria. We could hack them to fit our needs and do some calculations outside of the app. Instead we did what any programmer would do in such a situation – we decided to write our own.
Now this surely is the most boring domain one could imagine, right? Apart from maybe a TODO list, it’s the most popular pet project ever. Every programmer writes it at some point.
But over the period of a few months we’ve learned a lot about the domain. I think we can say we did the proper domain crunching. I acted mainly as the annoying customer/business expert, who is never satisfied with what they get (I’m absolutely brilliant in this role). Often I didn’t know what I was after, but I knew exactly when something felt wrong.
The first insight was that in fact we have two main parts in our app, which are to large extent independent. Tracking and analyzing. That fact impacted our model in significant way.
For example accounts are very useful for tracking. I can compare the actual total on one of our 11 accounts and the data in our app. If there’s a difference I can start looking what I missed this time. FYI I can’t force myself to enter all transactions every day, so it’s extremely important that identifying what transactions I missed is convenient. Accounts are perfect for this.
On the other hand I don’t care about accounts at the analysis stage. I don’t care if the specific payment was made from my personal account, our joint account, or my boyfriends wallet. Consequently, why in the world would I filter my expenses by account in reports? It gives me no actionable insights whatsoever. Adding such a feature would be a waste of time.
You might think “Isn’t it obvious? What’s the big deal?”. This is exactly what shows that we’re on the right track with modeling our domain. Afterwards it seems like the most obvious thing under the sun. But I can assure you it wasn’t that obvious when we started. Plus, most apps DO reports by account. Don’t ask me why would anybody use this. I have no idea. I wouldn’t.
Then we hit our first problem. I’m self-employed, so I pay taxes and health insurance myself. It’s not really an expense, in the sense that I can’t do much to make it lower. So from the perspective of optimizing expenses it was only a noise. Yet, it showed on my account and it was useful to track in some way. At first we added a flag which indicated whether the specific expense should be included in analysis. But after a while we’ve realized we have a missing concept here – an income cost. We have other expenses that shouldn’t be included in reports, but tracking my income costs on its own is actually useful information. Making this concept explicit made both things easier and less error-prone.
The next challenge came from my boyfriend. He does a lot of business trips. He covers expenses during his trips himself, and then his employer returns the money in the next salary. He goes mainly to countries more expensive than Poland, so those expenses are rather high. They completely ruined our analysis, and made tracking all expenses challenging. We still wanted to track those in the app, so we don’t forget to check if the money was returned, but those weren’t just normal expenses like groceries. That lead us to discovering another new concept – reimbursable transactions.
Since I occasionally lend money to family or friends we thought about explicitly modelling loans too. After giving it some thought we decided that using reimbursable transactions in that case is good enough. If we ever need more detailed distinctions between those two types of transactions, we can adjust our model. For now it’s good enough.
We’ve made many more discoveries like those described above. We used the app, noticed that something feels wrong, discussed it and refined our model. With each new discovery, our model got cleaner and made more sense. Looking back we were surprised we didn’t come up with all of this from the very beginning. It looks so obvious!
Back to DDD Borat
If you think about this, an e-commerce platform is way more complex and interesting than a personal finance app. Or is it?
I think we’ve been asking the wrong question here. It’s not about the domain per se. It’s not that one domain is more interesting or more complex than the other. Being interesting (whatever that means) is not an intrinsic characteristic of a particular domain.
What makes a particular domain interesting are problems you are solving.
In many cases it doesn’t make sense to go with your “domain crunching” very deep and some basic, off-the-shelf model, or slightly customized solution would do. If you can get away with CRUD, then by all means, do CRUD. If you’re a physicist then a bird is a bird, that level of abstraction would do just fine. It wouldn’t work for a biologist though.
The other thing that makes a particular domain interesting is you.
Can you notice when your model is not good enough anymore? Do you know when it’s time for a re-modeling session? Do you ever talk to your domain experts using their language? Are you truly interested in their problems and how to best solve them?
If not then no domain would be “interesting enough” to justify using DDD.
No excuses
So don’t let the popular myth to hold you back. You can apply the so-called “strategic design” principles even on your pet project.
In our case applying DDD concepts to the pet project pays off. The app is easy to use, we make fewer mistakes than in the beginning. When it was a simple CRUD app, I messed something up at least few times a week, because I forgot what flags to set in what situation. Fixing my mistakes could take us anything between 10 min. to 1 hr. Now each concept is modeled explicitly and I have no doubts how to enter all transactions, even when I’m particularly tired.
In many ways our app is simpler than the apps available on the market (e.g. our “budgets” are primitive), but it’s more sophisticated in other aspects. Above all – it makes sense to us.
Interesting story. I personally find the threshold for an app ready to be “DDDfied” really low. It’s only a matter of a couple of business rules where you start benefiting from the DDD principles, even on small projects.
Thanks Vladimir. Could you share some specific example from your experience? I think there aren’t enough of them now and personally I’d be very interested to see how you go about it.
Sure. For example, I had a simple web project where judges could vote for members of a small competition. There weren’t many business rules here: judges could vote only once for each member and they were deemed to be “done” only when they voted for all members.
Many would consider anemic domain model is a good fit for this particular case. Still, I was able to benefit from the DDD principles: I extracted the notion of Result, which represented a result of voting (contained a list of ratings a judge gave to all member’s qualities), and introducing a simple Judge-Result aggregate to hold the invariants: deciding whether or not a judge is “done” and preventing them from voting more than once for a single member.
I think together with code samples that would do a great blog post or presentation. I feel we don’t have enough examples, especially for those “small” things. Then it’s easy to think that my case is too trivial, what’s the point of optimizing something so simple?
Nice writeup. Is the finance app open-source? I’m really interested on using it.
I’ve talked to Eric about this exact subject at the DDDEU conference, and his point of view is pretty much the same – if you dig deep enough, you’ll find interesting and complex parts in most domains.
Btw, I don’t think that anemic domain model is necessarily an anti-pattern. As long as domain analysis is done, and it’s a conscious decision – the design is still driven by the business domain.
Great post , thanks! (I was watching
Domain From the trenches
and your article got a shout out).link to the talk: https://www.youtube.com/watch?list=PLGl1Jc8ErU1wcFdxzRr33ZoP_94B_1CGe&v=TzZ_f3paRwU
I’m glad you liked it, and thanks for the link, I didn’t know about it 🙂
Pingback: So you want to be a tools developer? |