1

To sum up, I am going to ask:

a) It makes sense to prevent the use of direct object references between aggregates in all scenarios?

b) how can there be collisions in an optimistic concurrency control in relationships between aggregates using direct object reference but with lazy load?

Long explanation

Taking a look at classical resources about DDD: blue book, red book and lots of posts here, the rule of thumb is always the same: "different aggregates must be referenced between them by IDs not using 'direct objects reference'".

The arguments in favor are:

A) Aggregates with inferred object references are thus automatically smaller because references are never eagerly loaded ( red book)

B) It prevents updating more than one aggregate in a single transaction (If you don’t hold any reference, you can’t modify another Aggregate, red book)

C) It forces all connected ARs to be in the same database.

D) If you do EntityA->getEntitiesB() maybe you have a million B's and you are going to cause memory problems

E) If you go for a pessimistic concurrency control you are going to have a lot of blocks

F) You are going to have a lot of collisions using optimistic concurrency control

I know that in the DDD world you always have a big "depending on" and a lot of trade-offs, so IMHO, taking into account that I'm working in a PHP environment using Doctrine as ORM and the application will not grow to sharding.

So, in my scenario I will refuse above reasons:

A) => is not a problem here, I am using Lazy Loading.

B) => if you pay attention and use doctrine DEFERRED_EXPLICIT you don't have problems.

C) => not problems because no database sharding is expected.

D) => It could be but, not planned, due to the size of the application or can be optimized specifically using a repository method and paying attention.

E) => Not using pessimistic concurrency control

F) => no idea¿? I have been doing some POCs and I don't get a version increment in EntityA, when I do entityA->addEntityB(entityB) or entityA->removeEntityB(entityB).

And in this scenario, I guess I have more advantages using direct object references:

ADV1) The relationship is reflected in the domain (rich and encapsulated) and I can test my domain relationships in a domain layer.

ADV2) I don't need additional hops between domain, application layer, and repository to retrieve relationships (at least not the biggest ones).

So my questions are:

a) It makes sense to prevent the use of direct object references between aggregates in all scenarios/applications?

b) how can there be collisions in an optimistic concurrency control in relationships between aggregates using direct object reference but with lazy loading?

References:

Red Book: https://www.informit.com/articles/article.aspx?p=2020371&seqNum=4

StackOverflow: Domain driven design and aggregate references

DDD in PHP: https://www.amazon.es/Domain-Driven-Design-PHP-Carlos-Buenosvinos/dp/1787284948

Lazy loading and domain: https://enterprisecraftsmanship.com/posts/domain-model-purity-lazy-loading

reqAst
  • 75
  • 2
  • 5
  • the overall benefits of these rules depend on your scenario. If you have and Aggregate like employee with direct object reference to Attendance aggregate then whenever you want to fetch the employee you should fetch all the attendances. and if you decide to use lazy loading you may not adhere to some old forgotten domain invariants in large applications – Ali.Rashidi May 12 '22 at 20:03
  • Hi Ali.Rashidi, thanks for your comment. Yes, I think that the key is that the "overall benefits of the rules depend on the scenario", it is something that I am trying to evaluate. My purpose is to get a list of rules and tactical patterns from the most strict DDD that make sense to apply in a scenario where we don't have the risk of a high volume of users, the performance is not so critical or the risk of change ORM or database engine is zero, just a more relaxed DDD version that allow us go faster and more comfortable – reqAst May 13 '22 at 16:19

0 Answers0