Can one Aggregate Root have multiple subtypes

aggregatecqrsdomain-driven-design

I have a concept that I am struggling to design in a DDD CQRS manner, and I hope to find some insight.

In the old days (before I knew DDD) I would have used simple inheritance, and that's how my mind is wrapping around the following…

  • I have a domain concept: Property
  • There is a SingleValueProperty which has a PropertyType and a Value
  • There is an AttributedProperty which has a collection of Attributes

The latter two are basically the same base concept as they share 8 class attributes, and would use the same Commands and Events to be managed in the domain. I am stuck at how to furnish them in the DDD Aggregate Root concept as it feels weird to have the Repository return different types of object.

On the other hand, I also feel that it's ok and still follows the SOLID principles, as this is what inheritance is for right?

Anyone got any hints on how to model this dilemma?

Edit:

I want to add more context as it may sway the consideration.

A Property is created with only it's main 8 attributes. After that the other aspects like addition of Attributes or choice of PropertyType are added to the Property. Does this mean 3 separate aggregate roots?

Best Answer

DDD doesn't really specify how you write methods or classes, so I don't see inheritance as being in conflict with DDD, even with Aggregate Roots.

Aggregate Roots have identities that are used to referred to them from outside of the bounded context. Assuming the object of subtypes all share the same identity space (e.g. their identities are unique within, that is, they don't overlap.) that is all that's needed.

A Property is created with only it's main 8 attributes. After that the other aspects like addition of Attributes or choice of PropertyType are added to the Property. Does this mean 3 separate aggregate roots?

You can determine whether you need multiple AR's by whether you have separate concepts to be independently referred to from outside the context. In this case, the question you need to answer is whether an Attribute is added to the system and has a stable identity of its own that can be used from outside the bounded context. If so, then it is certainly a candidate for being another AR. If, on the other hand, these other Attributes are referred to (and attached to the Property AR's) by their value/name then perhaps they do not merit being their own AR's.

It seems to me that you are introducing unnecessary complexity by separately categorizing single property type, in particular b/c you don't even know the true type until the (number of) properties are attached.

Is there a problem representing all property type as some multiple property type having a collection that has zero or more properties? This also goes to the good question that @ConstantinGalbenu is asking about differentiated behavior. Now, sure a property with no attributes and with one attribute and multiple attributes may have different behaviors but how different, and do you need inheritance to support tell don't ask by consuming callers.

I'm not sure if this is so, though your question suggests that the entities can graduate from no attributes to single attribute to multiple attributes. If that is the case, use of a class hierarchy for that feels contraindicated to me (but still can be done, to be sure, if you want to destruct and reconstruct objects of new type with same identity). The is-a relationship is meant to be stable, and if attributes can come (and maybe go) that shouldn't be part of the is-a relationship — that's just composition.

But back to the DDD aspect: DDD does not require separate AR's for subtypes, as it doesn't tell us how to implement class structure. DDD's AR concept concerns itself with references and identities as seen by clients external to the bounded context.