13

I have two aggregate roots and two non aggregate root entities:

entity relationships

I know, that the relation D -> B breaks DDD principle.

I heard, that in the most cases the solution is to make the referenced entity a new aggregate root.

But is making B to a new aggregate root really an option if B is a real child of A (B can not live without A)?

frol
  • 185
  • 8
  • 2
    What about D, is it a "real child" of C? Could it be possible to make D an aggregate root on its own and invert the reference? Hard to tell, though, without the domain knowledge... – zafarkhaja Nov 15 '12 at 15:44
  • +1 designing aggregates is really situational, a little context would help. – guillaume31 Nov 15 '12 at 16:00
  • In the real life D is modelled as a relationship entity which stores timed one-to-many releations from C to B. Timed means: B is assigned to C, and this assignment is valid for some time interval. This times releationship between C and B belongs to C as this can not exist without C. – frol Nov 15 '12 at 18:21
  • The domain is energy logistic market. Entity A is _Metering point operator_ (German: Messstellenbetreiber). Entity B are _Metering fees_ (German: Messentgelte) for metering point. Entity C are _Metering points_ (German: Messstelle). Entity D is _timed relationship_ between Metering point and Metering fees. – frol Nov 15 '12 at 19:22

2 Answers2

2

I agree with you, sometimes it just doesn't make sense to separate one entity from its aggregate, because it fits so naturally in it. This is one of the reasons why I'm not totally sold on the "small aggregates" approach that some recommend.

In such a case, what you can do is get a reference to B by traversal of an instance of A instead of getting it directly. After all, if B can't exist without A, there's no reason objects outside of the aggregate should know about a particular B and not know about its A.

guillaume31
  • 13,738
  • 1
  • 32
  • 51
  • I can not get the reference to B be traversing A because I don't know the particular B. This reference D -> B needs to be at least persisted. – frol Nov 15 '12 at 13:40
  • 1
    You can persist the information needed to retrieve B via A in D. That way, you can reference A from C and have specific D instances retrieve the specific B instances they need via A. – eulerfx Nov 15 '12 at 17:47
  • That means, if I use O/R mapper I can not force **integrity constraint** on the reference D -> B. Instead of using foreign key to B in D I have to store some other key (likely primary key of D). – frol Nov 16 '12 at 10:29
  • I also believe that using this approach would **reduce the performnce** because if I need to work with collection of D's I have to fetch the whole A aggregate for each D just to get the particular B. – frol Nov 16 '12 at 10:52
  • 1
    Performance concerns could be address by separating your [read-models](http://gorodinski.com/blog/2012/04/25/read-models-as-a-tactical-pattern-in-domain-driven-design-ddd/) from your domain models. – eulerfx Nov 16 '12 at 16:10
  • 1
    Also, I don't think you absolutely have to give up foreign key constraints. More details about your use case could shed some light on the issue.. – eulerfx Nov 16 '12 at 16:11
  • *"I can not get the reference to B be traversing A because I don't know the particular B"* - of course you don't know it, since you're looking for it. But A should be able to give it to you according to some parameters (time interval and C for instance). Also, I'm not a big fan of relationship entities, especially when they aren't identified domain concepts, so I would get rid of D and use some kind of dictionary to fulfill the need to search by time interval. – guillaume31 Nov 18 '12 at 22:06
1

First of all, this isn't DDD thinking, this is RDBMS thinking. In DDD you model business processes as they are in the real world, you don't have one-to-many etc concepts. So forget about DB, foreign keys and so on.

What are your bounded contexts (BC)? Each aggregate is a BC itself so they can have different representation of the concepts EVEN if they are named the same.

If I understand corerctly, it seems that A B C D are part of a single aggregate. That doesn't mean they are defined ONLY in that aggregate and ONLY in that form. However if C is a fully fledged AR in some other BC, it is quite possible that in THIS context to be represented only as an id or a few properties (interfaces are VERY handy for this stuff). So even if they are both named C, they are different, having only the behavior needed by a specific context.

DDD works with a lot of BCs and the models are valid for one BC only. this means that in your app you would have multiple A ,B ,C definitions according to each BC and each definition might be slightly different. This means that there isn't really only one model suitable for all the cases (and I'm not talking about CQRS here, just DDD).

I don't know much about the domain to actually come up with something more concrete. But simply put, try to represent things as they are and as they work in reality.

MikeSW
  • 16,140
  • 3
  • 39
  • 53
  • Eric Evans talks a lot about one-one, one-many etc. relations when modelling the domain. Also Each aggregate is not its own BC. – mathiasbn Mar 02 '20 at 19:53