• We can express an association between two entities via object reference ( though a relationship between Aggregate root and its internal entity could also be expressed via a method defined on a root –> SomeRootEnt.BorrowMeIntEnt(...) ) or via Repository, which would retrieve related entities from a database.
• When relationship is expressed via Repository, client would directly call a Repository to obtain related entity(ies)
• The decision on how to express a relationship is based on whether this relationship is required for maintaining an integrity ( and perhaps on whether behavior requires association to be able to express itself )
1) If relationship ( say 1:* ) is expressed via Repository, are child entities required to contain an ID of a parent entity ( Note: this question is assuming that either at least a parent is a root or that they all reside within same aggregate )?
2) The relationship between entities in different aggregates should only be expressed by IDs
a) Why?
b) Wouldn’t such a relationship essentially be expressed via Repository?
c) If yes to b), this would also suggest that associations between entities in different aggregates in most cases aren’t required for the purpose of supporting a particular behavior? If yes, why?
UPDATE:
2a)
Expressing relationship with an identity reference is different from
expressing the relationship with an object reference. The reason that
the relationship should be expressed with an identity is to maintain
transactional integrity – ie only a single aggregate will be modified
in any given transaction. If an object reference was used, two
aggregates could be affected by a transaction.
I – I understand the point you’re trying to make, since if relationship would be expressed with an object reference, then simply for the fact that aggregate A1 ( which is being modified ) is “physically” connected to another aggregate A2, it means one of A1’s parts ( ie A2 <– in reality A2 is not really a part of A1, but hopefully you understand the point ) is not in sync with other parts?!
II – But conceptually speaking, if we modify A1, then even if the relationship between the two is not expressed using object reference, the two aggregates are still out of sync, so in practical terms, what difference does it make whether A1 and A2 are physically connected?
III – Anyways, why couldn’t we in BOTH cases simply use eventual consistency?
SECOND UPDATE:
original_2)
To be clear, relationships between root entities (ARs) should be
expressed with identities. References between non-root entities in
distinct aggregates should be forbidden.
Can we have unidirectional associations traversable only from A1 non-root entity(ies) to A2 root entity ( ie non-root entity in A1 would contain ID of A2 root )?
2)
a)
I.
If an object reference was used, two aggregates could be affected by a
transaction.It creates a possibility of A2 being modified in the transaction which
is modifying A1. Referencing A2 by identity eliminates this
possibility. Also, things such as database locking won’t apply to A2
when loading A1.
Ignoring for a moment the fact that DB locking won’t apply to A2 when updating A1 – why shouldn’t we in certain situations allow both A1 and A2 to be modified within a single transaction?
I know aggregates define consistency boundary, but if in rare cases we need both A1 and A2 to be synchronized within same transaction, then only other alternative may be to convert both A1 and A2 into a single aggregate, which in that particular model may not be appropriate?!
Thank you
1) Yes. For example, suppose you have a customer with orders. To get all the orders for a customer, you can select all orders with a corresponding CustomerId via orders repository.
2) To be clear, relationships between root entities (ARs) should be expressed with identities. References between non-root entities in distinct aggregates should be forbidden.
2a) Expressing relationship with an identity reference is different from expressing the relationship with an object reference. The reason that the relationship should be expressed with an identity is to maintain transactional integrity – ie only a single aggregate will be modified in any given transaction. If an object reference was used, two aggregates could be affected by a transaction.
2b) Yes. A repository allows the traversal and the identity expresses the relationship.
2c) This is the whole point of an aggregate – it should define a consistency boundary. If changes to an aggregate should affect aggregates, those changes should be capable of being applied in an eventually consistent manner.
UPDATE
2a1) It creates a possibility of A2 being modified in the transaction which is modifying A1. Referencing A2 by identity eliminates this possibility. Also, things such as database locking won’t apply to A2 when loading A1.
2a2) If the transaction which modifies A1 results in changes that need to be applied to A2, those changes will be synchronized eventually. The reason for keeping them physically separate are stated in 2a1.
2a3) You could, but again, reasons specified in 2a1 explain why it is better to use identity references.
UPDATE 2
2) I suppose if the integrity of the two ARs is maintained and the reference makes life a lot easier it can be acceptable. The reference is not itself a problem, it can lead to problems.
2a1) One reason for this is rooted in more modern document database architectures. Document databases usually only support atomic transactions on a single document. Another reason is that two ARs may be stored in different databases, in which case a distributed transaction would be required to maintain consistency. However, a relational database can certainly lock multiple tables and so a scenario where two ARs are modified in a transaction are possible. As a result, these constraints should be understood as guidelines. If all ramifications are understood and caution is used, then it can be acceptable to update two ARs.