DDD – Effective Aggregate Design Questions

domain-driven-designeventual-consistency

I just read Effective Aggregate Design, by Vaughn Vernon. Summarizing the takeaway:

  • Model true invariants
  • Design small aggregates
  • Reference other aggregates by identity
  • Use eventual consistency between aggregate's boundaries (before asking whose job it is)

After learning about the above, two questions sprang up:

  1. If I'm not mistaken, one of DDD's reasons for being is avoiding spaghetti code, where business logic is scattered all around on, most of times, a fat service layer. Are you not scattering business logic when you use eventual consistency?
  2. Is there any other way to represent the business ubiquitous language other than having a rich domain model? Can't the language be expressed in a fatter service layer?

I thank you in advance for any input.

Best Answer

A little remark, and then a tentative answer.

Use eventual consistency between aggregate's boundaries (before asking whose job it is)

That's aggregate design by definition. We might argue whether this is a good or bad decision, but the Aggregate in Domain-Driven Design is a "unit of consistency". This is not to say that this is "the right way to do things", only that, when we talk about aggregates, this principle is somewhat implicit.

If I'm not mistaken, one of DDD's reasons for being is avoiding spaghetti code, where business logic is scattered all around on, most of times, a fat service layer. Are you not scattering business logic when you use eventual consistency?

DDD doesn't exist for avoiding spaghetti code, but to provide a sensible way of designing code in places where you have frequent evolutions (due to intrinsic domain complexity - code is changed because people learn - or to rapidly evolving domains - code is changed because we are competing with new ideas). However... spaghetti gets in the way when you are pushing for frequent changes. ;-)

"Scattering business logic" per se isn't a good or a bad thing, until you take into account Bounded Contexts and different purposes that the software might serve. If the business logic belongs to different bounded contexts, then it's fine if it's not in the same place. In CQRS/ES for example, coordination logic frequently gets placed into ProcessManagers, reacting to external Domain Events.

Is there any other way to represent the business ubiquitous language other than having a rich domain model? Can't the language be expressed in a fatter service layer?

Another little clarification is needed: there is no such thing as "the business ubiquitous language". There are many languages with different purposes. They can be made ubiquitous and consistent only within the boundary of a Bounded Context, where they will be expressed well... everywhere (that's the ubiquity), from Acceptance Tests to UI labels to database field names.

The need of a fatter service layer often arises from a misconception of what a model is. If the model is principally behavioural, then its behaviour is decoupled from what users need to see. However, this decoupling is not spread evenly: some portions of the system will look CRUD-like, while in other portions the distance between what the software is doing and what a user needs to see might be strong enough to call for distinct models.

Focusing on what users need to see leads invariably to overlapping models: things with the same name that different users use in different ways. That's because the data looks the same, forcing promiscuous sharing. When the data is promiscuous, the obvious place to put the logic is the service layer. But the problem is upstream of that.