Lessons in DDD from building an e-commerce platform
In a recent conversation with some colleagues, we were talking about how startups make the trade-off between design, domain-driven specifically, in favor of speed. They intentionally take on debt, technical and otherwise, to move faster.
I wasn’t in favour of employing DDD in a startup because it’s expensive and slow for a small system. There comes a time when the startup code needs to transition into enterprise DDD-style code, but I think it can be made if and when necessary.
After the conversation, I thought about the shortcuts I took building Supplybunny but noticed a few things that I did that were DDD-like.
E-commerce as a domain seems to encourage the same practices that DDD advocates for.
Ubiquitous language
When we started Supplybunny I knew little about the food and beverage industry. That’s what prompted me to learn the jargon.
Besides, the different actors used different language. For instance, a supplier would call a product an “SKU”, while a buyer would call it an “ingredient”. A supplier would care about an order and a logistics partner would care about a delivery or shipment.
The difference in language made it plenty clear that there were different contexts at play even if I wasn’t intentionally trying to separate them.
Bounded contexts
In e-commerce bounded contexts are clearer than in most other domains.
There is a public search for which you don’t need to log in.
The way a supplier and a buyer interact with orders and the information they need to see is different.
On the admin side, different departments need to see different things: logistics don’t care about customer support information, and vice versa.
Aggregates
A big part of e-commerce is dealing with the financial aspect of it. A key part of that is that the order information must be isolated and not change as a result of changes elsewhere.
For instance, the product name in an order item, the supplier address in the invoice, and the delivery charge.
Not only that, but several fields have multiple values. Take, for instance, the delivery charge: one amount is shown to the buyer, one to the supplier, one to the admin, and one might be sent to an external provider.
And not just that, but each of these must be independently traceable - that is, you must be able to generate an account statement for each of those actors.
This naturally encourages duplication and isolation of data.
Two patterns I used to manage that were the functional model and the actor model.
All these requirements naturally lead to clearer boundaries between contexts.