0
votes

Lets say I have

  • aggregate root A which has entity B

  • aggregate root C which has entity D

I've read that best practice is to hold object Id inside aggregate roots instead of direct references, for example A->C_Id and C->A_Id.

  • can aggregate hold Id of entity in separate aggregate? Like A->D_Id and C->B_Id?
  • can one aggregate root instantiate another aggregate root? Like A instantiate C and vice versa?
  • can aggregate A instantiate new instances of entities stored in separate aggregates? Like A attempts to instantiate D or C attempts instantiating B?
  • can aggregates and/or entities methods take as arguments direct references of entities from other aggregates, provided that they will not store direct references after method exit? Like A->method(D) or B->method(C)
3

3 Answers

0
votes

Yes :)

There is no real reason why any of your options would be incorrect.

can aggregate hold Id of entity in separate aggregate? Like A->D_Id and C->B_Id?

If there is a real relationship then this is certainly possible.

can one aggregate root instantiate another aggregate root? Like A instantiate C and vice versa?

Having one aggregate serve as a factory for another is absolutely fine. Typically this would require both to be within the same bounded context though.

can aggregate A instantiate new instances of entities stored in separate aggregates? Like A attempts to instantiate D or C attempts instantiating B?

Same as above.

can aggregates and/or entities methods take as arguments direct references of entities from other aggregates, provided that they will not store direct references after method exit? Like A->method(D) or B->method(C)

This is perfectly reasonable but, again, this is only probably going to be feasible when the entities are within the same bounded context. That being said, it is quite possible to use a value object representing an aggregate from another BC as that instance.

0
votes

I've read that best practice is to hold object Id inside aggregate roots instead of direct references, for example A->C_Id and C->A_Id.

Yes, this is the recommended way.

can aggregate hold Id of entity in separate aggregate? Like A->D_Id and C->B_Id?

Yes, but only to use that information on the read side (i.e. on the UI) and not to use it to protect the invariants.

can one aggregate root instantiate another aggregate root? Like A instantiate C and vice versa?

I don't recommend it. Aggregate A would have to much responsibility. Also, Aggregates should be independent of each other.

can aggregate A instantiate new instances of entities stored in separate aggregates? Like A attempts to instantiate D or C attempts instantiating B?

Under no circumstances. That would break the other Aggregate's encapsulation.

can aggregates and/or entities methods take as arguments direct references of entities from other aggregates, provided that they will not store direct references after method exit? Like A->method(D) or B->method(C)

I don't recommend it as it would couple to much the two Aggregates. Instead, you should pass primitives or Value objects.

0
votes

can aggregate hold Id of entity in separate aggregate? Like A->D_Id and C->B_Id?

You mean of a non-root entity? Just an ID won't typically be of any help, since non-AR entities can't be directly retrieved through repositories. You would have to store both the entity ID and its parent Aggregate Root ID. Memorizing too many things about the inside of another aggregate may also be a code smell.

can one aggregate root instantiate another aggregate root? Like A instantiate C and vice versa?

Sure. In some approaches it's even the recommended way to create an AR.

can aggregate A instantiate new instances of entities stored in separate aggregates? Like A attempts to instantiate D or C attempts instantiating B?

Why not, though I can't think of a valid example right now, except maybe with simple value objects. Do you have one in mind?

can aggregates and/or entities methods take as arguments direct references of entities from other aggregates, provided that they will not store direct references after method exit? Like A->method(D) or B->method(C)

Yes, transient references are fine.