In DDD, Entities have this concept of identity that uniquely identifies every instance regardless of all the other properties. Usually this identity has to be unique among the BC in which the Entity live, but there is an exception.
Sometimes we need to create Aggregates that are not only made by the root Entity and some Value Objects but have one or more child / nested Entities (that I understand to be called local Entities). For this kind of Entities the identity has only to be locally unique i.e. unique among the Aggregate boundaries.
Given this, let's also consider the fact that are two way to model a has-a relationship in DDD, depending on the actual business needs: separate Aggregates or Aggregate Root + child Entities.
In the first case the "child" Aggregate of the relation has a reference to the identity of the parent one, which in turn usually has a factory method to create and return an instance of the child:
class ForumId extends ValueObject
{
// let's say we have a random UUID here
// forum name is not a suitable identifier because it can be changed
}
// "parent" aggregate
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
method startNewThread(ThreadId threadId, string title): Thread
{
// make some checks, maybe the title is not appropriate for this forum
// and needs to be rejected
...
// passing this forum's ID,
return new Thread(this->_forumId, threadId, title)
}
}
class ThreadId extends ValueObject
{
// let's say we have a random UUID here
// thread title is not a suitable identifier because it can be changed
}
// "child" aggregate
class Thread extends AggregateRoot
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
If we consider instead the second case, let's say because for some business reason we need to have Thread as a local entity of Forum, what is the correct way to identify it? Should Thread still contain the ForumId of the parent Forum or it is redundant since it will only live inside that specific Forum and never accessed outside?
Which way is better and more importantly why? May the data model (i.e. the database level) steer the decision toward one way or another, or should we still ignore it as per good DDD design?
class Forum extends AggregateRoot
{
private ForumId _forumId;
private string _name;
private List<Thread> _threads;
method startNewThread(string title): ThreadId
{
// or use and injected `ThreadIdentityService`'s `nextThreadId(ForumId)` method
var threadId = this.generateNextLocalThreadId()
var newThread = new Thread(/*this->_forumId, */ threadId, title)
this._threads.append(newThread)
return threadId
}
}
// "child" aggregate - case 1
class Thread extends LocalEntity
{
private ForumId _forumId;
private ThreadID _threadId;
private string _title;
}
// "child" aggregate - case 2
class Thread extends LocalEntity
{
private ThreadID _threadId;
private string _title;
}
So the main purpose of having an aggregate is to make any change to this aggregate atomic.
The aggregate root contains the full child entity inside, for example Forum would have a collection of Threads.
Since the Thread is already inside a Forum wouldn’t make any sense having ForumId inside since the repository in charge of saving it would already know that id because we’d save the whole forum not a single thread.
Also wanted to add that Forum aggregate seems to be a huge aggregate, that implies some trade offs that you should take into account.
Related
i'm stuck with this problem while designing aggregates in a DDD project.
Please consider the following scenario:
public abstract class BaseAppType{
public abstract int GetUserOwnerId();
public List<AppTypeHost> Hosts {get;set;} = new List<AppTypeHost>()
}
public class PersonalAppType:BaseAppType //this is an aggregate root
{
public int override GetUserOwnerId(){ return Hosts.Select(h=>h.UserId).Single(); }
}
public class TeamAppType:BaseAppType //this is another aggregate root
{
publi int TeamOwnerId {get;set;}
public int override GetUserOwnerId(){ //this is much harder becase i don't have the info in the object }
}
public class Team {
public List<TeamMember> TeamMembers = new List<TeamMember>();
}
public class TeamMember {
public int TeamId {get;set;}
public int UserId {get;set;}
public TeamMemberRole Role {get;set;} //this might be either Owner or Member
}
So basically i've two types of appointments that share common info, functionality and shape via a root class.
Now i've to implement GetUserOwnerId in the two derived class, which are two distinct aggregates root.
In the PersonalAppType it is kind of easy because the information of the userOwner is within one of the entity of the aggregate so i simply query the object in memory and return it.
In the TeamAppType it is more diffuclt because the information is in another aggregate root ( basically for my business rules, the owner of the TeamAppType is the Owner of the Team AggregateRoot).
Since Team is another AggregateRoot i could not load it into the TeamAppType aggregate and i pretty stuck...
I've tried:
the route of injecting a service in the TeamAppType
so that i can call it within the GetUserOwnerId but i don't like it because it feel "wrong" to inject a service within a domain constructor and it is kind of hard because when i retrieve the aggregate root from ef core, it doesn't inject the service ( because it uses the default construcor with 0 params )
I've also tried the route of doing it in a domain service, something like this:
public class AppTypeOwnerResolverService{
public int GetUserOwnerId (BaseAppType appType)
{
switch (appType.GetType())
{
case "PersonalAppType":
//retrieve owener of PersonalAppType
break
case "TeamAppType":
//retrieve owener of TeamAppType
break
}
}
}
but it feels off because it looks like the GetUserOwnerId should stay within the inherited class and this reduces the benefits of polymorfism.
Do you have any suggestion on how to approach this problem?
Thanks to everyone for the help.
Another option would be to have a Team aggregate emitting domain events, (i.e. TeamOwnerAssigned) and having a domain event handler that modifies the TeamAppType aggregate based on this event.
In a bounded context I created an Entity which serves as an aggregate for other objects in this context. The problem is, an instance of an Entity may be in child-parent relation with another Entity. In terms of a database it means, that there is a parent_id field which references a row in the same entities table.
And the question is, from DDD point of view, is it ok to make an instance of an Entity an argument of its own constructore function? Or is better to use an aggregate root (or an Entity identifier). So, which way is better:
class Entity {
public constructor (arg1, arg2, Entity parent) {
...
this.setParent(parent);
}
}
or this way:
class Entity {
public constructor (arg1, arg2, int parent_id) {
...
this.setParentId(parent_id);
}
}
Just because you have a tree like structure doesn't mean that all Entities in this structure should be part of the same Aggregate.
You can design your system to have each Entity instance in it's own aggregate. Since each entity has a parent you have to reference this parent.
One way to do this is to have an Object reference like in your first example
Another way is to use Reference by identity like in your second example
If you use Object reference that means that you must load all the objects referenced together from the DB. This may cause you to load huge amount of them. If you application doesn't require you to do so it's best avoided.
If you choose to use Object reference then you can pass an Entity to the Constructor like in your ecample.
If you use Reference by ID you can only load one object, then if needed, you can load another by using the ID. This is useful if you want to have multiple aggregates that only need each other in specific situations and you don't need to load them all the time together because your application doesn't require you to do so.
Here's an example:
public TreeNode {
public Guid ParentID { get; private set; }
}
public void DoSomethingToNode(Guid nodeId) {
var node = TreeNodeRepository.GetById(nodeId);
var parent = TreeNodeRepository.GetById(node.ParentID);
// do stuff with parent and child.
}
If you haven't read the DDD book, I recommend it.
This essay from Vaughn Vernon is also great on modeling aggregates
Lets abstract say i want to program two classes that have a relation of 1 to n(many) and I don't know what the best approach to take. Programming Language doesn't matter!!!
class Parent
{
string name;
date birthdate;
array children[]; // is it better to declare here an array of children and add childrenobjects to >this or is it better at the childclass to have an variable pointer to an object of type Parent????
... constructor setters getters ....
function addChild(Childtype childvar)
{
this->children push childvar
}
function removeChild(Childtype childvar)
{
}
function saveDB()
{
//what do I save there only parent or also the children that were created during runtime >and added to an instance of this object????
insert into relational_db_table values (name, birthdate);
//really not sure whats the best and why
foreach key->value of children do
{
child->saveDB()
}
}
}
class Child {
Parent myparent;
string name;
string description;
....constructors setters getters... //doesnt matter
saveDB { //
INsert into relational_db_table VALUES (name, description, myparent);
}
}
So i will repeat now my 2 questions:
1. What is best and why?
a) to declare at the parent class an array which holds the children
b) to declare a variable at the child class that holds a reference to the parent object
c) do both of the above
Regarding saving to databases what is the best and why?
If i take a) form 1st question approach do i have to save the children as i wrote from the parent class cause i cant see how else i can save the children to the db for later use. is here any othere method??
If I take b I will have to manage somehow the childrens of a parent in memory that will be don with a collection no problem extra which is not a problem. but in this case if anything changes to a propery i can save it separatly hmmm not sure.
Please thing of these questions with a database in the back of the application the database is not necessary a relational one its fine for me also with nosql databases. I'm only interested to do design these classes very good so in future if something has to be changed the things will be easy to change and i want do use the best programming patterns possible. I have read also almost all of the existing OOP programing patterns around but i still cant decide what to do here best.
PS: sorry code is not tabbed
Thanks alot!
I would go with first approach,
class Parent {
private String id;
private List<Child> childList;
public List<Child> getChildList() {
return childList;
}
public String getId() {
return id;
}
}
class Child {
private String id;
public String getId() {
return id;
}
}
You can insert data of multiple parent as,
List<Parent> parentList = getParentList();
for (Parent parent : parentList) {
String parentId = parent.getId();
for (Child child : parent.getChildList()) {
String childId = child.getId(); // Parent info
// Add to DB - you can pass parent info & child info
// insert parentId, childId
}
}
Why not each child having reference to its parent?
In this case, you need to have a list which contain children, which will break OOPS concept. (For Eg: Parent, as an object need to know about its children)
How is it useful for DB?
In this case, you can easily navigate to required parent (If not require for now, for future) & insert ONLY its corresponding children elements into DB. If you take option 2, you need to loop over ALL child elements (Which may be VERY long - Not efficient)
Were would you place the functions to insert the data into the database?
Commented in code.
Consider we have a BankCard Entity that is a part of Client Aggregate. Client may want to cancel her BankCard
class CancellBankCardCommandHandler
{
public function Execute(CancelBankCardCommand $command)
{
$client = $this->_repository->get($command->clienId);
$bankCard = $client->getBankCard($command->bankCardId);
$bankCard->clientCancelsBankCard();
$this->_repository->add($client);
}
}
class BankCard implements Entity
{
// constructor and some other methods ...
public function clientCancelsBankCard()
{
$this->apply(new BankCardWasCancelled($this->id);
}
}
class Client implements AggregateRoot
{
protected $_bankCards;
public function getBankCard($bankCardId)
{
if (!array_key_exists($bankCardId, $this->_bankCards) {
throw new DomainException('Bank card is not found!');
}
return $this->_bankCard[$bankCardId]);
}
}
Finally we have some domain repository instance which is reponsible for storing Aggregates.
class ClientRepository implements DomainRepository
{
// methods omitted
public function add($clientAggregate)
{
// here we somehow need to store BankCardWasCancelled event
// which is a part of BankCard Entity
}
}
My question is whether AggregateRoot responsible for tracking its Entities' events or not. Is it possible to get events of an Entity which is a part of an Aggregate from within its Aggregate or not?
How to actually persist the Client with all changes made to the bank card saving its consistency?
I would say the aggregate as a whole is responsible for tracking the changes that happened to it. Mechanically, that could be "distributed" among the aggregate root entity and any other entities within the aggregate or the aggregate root entity as the sole recorder or some external unit of work. Your choice, really. Don't get too hung up on the mechanics. Different languages/paradigms, different ways of implementing all this. If something happens to a child entity, just consider it a change part of the aggregate and record accordingly.
I have an aggregate that includes the entities A, AbstractElement, X, Y and Z. The root entity is A that also has a list of AbstractElement. Entities X,Y and Z inherit from AbstractElement. I need the possibility to add instances of X, Y and Z to an instance of A. One approach is to use one method for each type, i.e. addX, addY and addZ. These methods would take as arguments the values required to create instances of X, Y and Z. But, each time I add a new type that inherits from AbstractElement, I need to modify the entity A, so I think it's not the best solution.
Another approach is to use an abstract add method addAbstractElement for adding AbstractElement instances. But, in this case, the method would take as argument an instance of AbstractElement. Because this method would be called by entities located outside of the aggregate, following DDD rules/recommandations, are these external entities authorized to create instances of AbstractElement? I read in the Eric Evans book that external entities are not authorized to hold references of entities of an aggregate other than the root?
What is the best practice for this kind of problem?
Thanks
From Evan's book, page 139:
"if you needed to add elements inside a preexisting AGGREGATE, you might create a FACTORY METHOD on the root of the AGGREGATE"
Meaning, you should create a factory method on the root (A) which will get the AbstractElement's details. This method will create the AbstractElement (X/Y/Z) according to some decision parameter and will add it to its internal collection of AbstractElements. In the end this method return the id of the new element.
Best Regards,
Itzik Saban
A few comments. As the previous answerer said, it's a good practice to use a factory method. If you can avoid it, never create objects out of the blue. Usually, it's a pretty big smell and a missed chance to make more sense out of your domain.
I wrote a small example to illustrate this. Video is in this case the aggregate root. Inside the boundaries of the aggregate are the video object and its associated comments. Comments can be anonymous or can have been written by a known user (to simplify the example, I represented the user by a username but obviously, in a real application, you would have something like a UserId).
Here is the code:
public class Video {
private List<Comment> comments;
void addComment(final Comment.Builder builder) {
this.comments.add(builder.forVideo(this).build());
// ...
}
}
abstract public class Comment {
private String username;
private Video video;
public static public class Builder {
public Builder anonymous() {
this.username = null;
return this;
}
public Builder fromUser(final String username) {
this.username = username;
return this;
}
public Builder withMessage(final String message) {
this.message = message;
return this;
}
public Builder forVideo(final Video video) {
this.video = video;
return this;
}
public Comment build() {
if (username == null) {
return new AnonymousComment(message);
} else {
return new UserComment(username, message);
}
}
}
}
public class AnonymousComment extends Comment {
// ...
}
static public class UserComment extends Comment {
// ...
}
One thing to ponder on also is that aggregate boundaries contain objects and not classes. As such, it's highly possible that certain classes (mostly value objects but it can be the case of entities also) be represented in many aggregates.