1

I'm currently designing a DDD system, and it is a reference implementation. The reference is a big ball of mud. I'm finding myself spending a fair amount of time determining aggregate roots and the relationships to other aggregates. Have you ever tried making everything an aggregate root and then refactoring to small aggregates? No one is going to design their aggregates correctly the first time, so why not start really small and build to small in comparison to starting large and breaking down.

This may seem like a common sense observation, but it wasn't to me; I've designed several DDD systems and I always start with big aggregates. I do know that big aggregates are a common anti-pattern and design flaw in DDD.

This question may seem subjective but refactoring is an objective practice. How you refactor, is the subjective part. So can we be objective about how we begin?

3
  • i would agree. I think it should a be a high bar to include child objects in an aggregate root vs linking to them by id as a separate root. Rather than starting with a big blob and trying to split bits out
    – Ewan
    Jan 29 at 17:27
  • I think what you're describing is basically the bottom-up approach to design (as opposed to top-down - both perfectly valid strategies), it's just that here it's within the context of DDD. It's wiser to float somewhere in between the two extremes, though. Once in a while, take look at the big picture (or, if the big picture is a blurry mess, stop from time to time to see if you can reconstruct some of it). In a sense, bottom-up is a local search through a solution space, but it can get you stuck in a local maximum; a little bit of top-down helps you recognize that and try something else. Jan 29 at 21:37
  • P.S. By "search through a solution space" I just mean - you start writing code, and then you add more code, more features - and you just keep going (as if climbing a hill), hoping that your design choices won't lead you into a structure that turns out not to be right ("the local maximum"), and results in a costly refactoring Christophe warns about (cause you figured out that you need to be on another hill). Jan 29 at 21:42

1 Answer 1

3

Small is beautiful. This applies to aggregates as well.

According to Evans, an aggregate is:

A cluster of associated objects that are treated as a unit for the purpose of data changes. External references are restricted to one member of the AGGREGATE, designated as the root. A set of consistency rules applies within the AGGREGATE’S boundaries.

This definition bears indeed the danger of viewing the "unit" too large. After all, according to this definition a whole domain could be viewed as some kind of unit for the purpose of data changes. Fortunately in practice, nobody takes it to this extreme and flawed viewpoint.

What is missing, is that the "units" should also be minimalistic: this avoids a lot of unnecessary couplings of entities with aggregate roots with a view to common OO design principles (Principle of least knowledge, single responsibility principle, interface segregation principle, ...).

So I have much sympathy with the idea of starting with every entity an aggregate. However, using blindly this other extreme might loose some of the benefits of aggregates and be costly in terms of refactoring. I'd therefore advocate some more nuance: start making every entity an aggregate unless there are justified reasons to absolutely not do so. Typical mistakes, such as including an entity in an aggregate because it's somehow referenced in the root and nowhere else, should of course not be considered as a valid reason.

2
  • 1
    "This definition bears indeed the danger of viewing the 'unit' too large" - just wanted to say, this is a good point, and one that, I think, touches on one of the sources of a lot of confusion surrounding DDD. I think there's a lot of somewhat carelessly written information out there coming from secondary sources that obscures the kind of granularity and level of abstraction Evans had in mind when talking about different levels of organization of model elements into things like aggregates, subdomains and bounded contexts. Jan 29 at 21:25
  • 1
    @FilipMilovanović I fully agree with your analysis. I think the examples in Evans' book are straightforward and very appropriate. Many secondary sources take border-line examples that are not so well though. But even with some case, this other question shows how easy it is to get mislead.
    – Christophe
    Jan 29 at 22:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.