I'm currently facing the problem of handling the associations between the entities in the aggregate.
Consider following example:
Right now, we have a ,,User" Entity, which is also my aggregate root. He can have exactly one ,,Product" associated to him , and many ,,Aliases". What I need currently is the ability of retrieving the related ,,Product" and ,,Aliases" on-demand within the Domain Model. User is being created by UserFactory, which can be used separately or also used within UserRepository when creating Entities from data in persistence.
<?php
class User {
private $id;
private $aliases;
private $product;
public function isEligibleForCompanyPromotion() {
//I need a good way to populate this without a performance bottleneck.
$product = $this->product;
[.. code comparing things between User and Product begins ..]
}
}
The reason to this is because our business logic ( as you can see in example ) relies a lot on associations between objects and I suppose this logic related to associations between objects should be done within the Domain Model ( or maybe this should be moved out? )
I considered following solutions:
1) Just load everything ( the associated Product and Aliases ) when the User is being constructed.
Pros:
- Works?
Cons:
- BIG performance issue ( and unfortunately I'm working on live high-load system, so this can't be passed up upon )
2) Inject the relationship repository into the domain model
private $productRepository;
private $aliasesRepository;
[...]
}
Pros:
- Works ..
Cons:
- Defeats ( imo ) the purpose of DDD , with User being required to have the repositories inside ( so domain model is coupled to persistence.. )
3) Delegate the association-related logic out of Domain Model ( maybe to Domain Services and Policies? )
Pros:
- Also works
Cons:
- Actually I feel like this leads to Anemic Domain Models , because majority of our business logic is based on the relations of the objects, so a lot of code would be moved out of Domain Objects which kind of makes no sense.
4) Create a specialized Relationship object for handling the relation:
<?php
class UserFactory {
private $relationshipFactory;
public function createUser($persistenceData) {
$user = new User();
[.. creating of User, populating data etc .. ]
$user->product = $this->relationshipFactory->createUserProductRelationship($user);
}
}
class UserProductRelationship {
private $user;
private $product;
private $productRepository;
[.. productRepository is being injected within relationshipFactory, and user is provided ..]
public function loadProduct() {
[.. load the product based on the relationship criterias ..]
}
[.. calls to this object are proxied to lazy-loaded product via __call, __get etc. )
}
Pros:
- Also works
Cons:
- Circular dependency ( User is required to have the UserProductRelationship inside and relies on it. UserProductRelationship is required to be provided with the User entity. Combining those two classes would lead to scenario #2 ).
Maybe I didn't understand something properly.. should anyone have a suggestion, I'd be happy to hear about it.
Thanks!