Let's say I have the typical entity Car
class Car : Entity
{
public double MaxSpeed { get; set; }
public Color Color { get; set; }
/* ... */
}
This entity, in my domain model, would be the root entity of an Aggregate.
Now let's say I specialize cars. I create a Ferrari, and the happy owners of Ferraris like to call them by a nickname:
class Ferrari : Car
{
public string Nickname { get; set; }
}
Let's say I have another entity, the Company entity. It would be the root entity of another Aggregate. There are many people working on a company, represented by the entity Person. Persons may have cars. But the President of a company is usually very rich and this kind of people, they have Ferraris:
class President : Person
{
public Ferrari Ferrari { get; set; }
}
In this situation, I have the entity President, who is inside the Company Aggregate, that is holding a reference to a Ferrari, an specialization of the root entity of another aggregate.
Is this correct in view of DDD? Can/should I consider the specialization of root entities themselves as root entities of the same aggregate? I mean, in the domain I described, is the entity Ferrari also the root entity of the Car Aggregate (since Ferrari is also a Car)?
Now let's say I have to persist this model to a Database. I think that my question does not depend on the OR/M framework I will use.
How should I build the table holding Cars? Should I build a single table Cars, with a "CarType" column (possible values: "Car", "Ferrari"), and a nullable Nickname column?
Or should I build a table for Cars and a table for Ferraris, the latter one having its PK a FK of Cars?
Thanks!
Generally when you cross root aggregate boundaries you only allow the reference to be of the ID of the other root aggregate. You then use that ID to look up the other aggregate in its repository.
So in your case you would want President to have a Car ID and if you ever needed to do something to the President's car you would use the Car ID to go to the repository to get the car. President would not have a reference to the Car itself.
Now about that Ferrari. It's kind of difficult to enforce that in standard DDD terminology. Normally you would put some validation on the assignment of a Car to a President. Or perhaps there is a CarBuyingService just for Presidents that makes sure you get it right. Normally in DDD specializations are not themselves root aggregates.
You shouldn't use inheritance to model your domain because you will soon run into trouble once model starts to get complex.
President is simply a role of the person and person can have multiple roles. Maybe president got just one role but that's simply accidental by choosing wrong example.
Ferrari shouldn't be inherited from car either. It's not obvious on Ferrari example, because they only do one type of cars but consider company making many types like vans, sedans, hatchbacks, trucks and so on. You will probably want to make classes for every type that will inherit from car class. And then what... are you going to make five Toyota classes that will inherit from each type? Such as...
Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback
That would be ridiculous.
Disclaimer: I know nothing about about cars. However...
Don't use inheritance to model your domain. Ever.
Try it without inheritance and it will also became obvious how to persist your domain.
I think you start losing a lot of the flexibility of the system by creating concrete types of these entities. The type of relationship that you are implying is something I generally hand with a "Type" entity. For example, you have a car. A Ferrari is a type of car. The two entities that are borne from that are a Car and a CarType.
The way that you are talking about doing it, you would have to add new entities every time a new type is introduced. If all that you are trying to capture is the "nickname" of the car, I would think that is just another piece of data, and not another entity. Unless you have different data (i.e. different property names) and/or behavior differences in Car entities for different types, you do not gain much with this approach. I would rather have repository methods like FindCarByType() and deal with one type of entity, to reduce risk.
I am by no means a DDD expert, and I am struggling with some concepts (or more like struggling with the multiple interpretations of some concepts). I am finding that there is not a 100% pure implementation, and that there are nuances to each implementation that I have seen.
Edit Follows
I see that I misread part of what you had written. I see that nickname is not for all vehicles, but just for Ferrari : Car. I think that the answer is really "it depends". How much domain specialization do you have in the rest of your model? Having a nickname might be prevalent amongst Ferrari entities, but is it exclusive? It isn't only about the actual data, but the requirements. Basically it comes down to how much specialization your are expecting in these entities.
Related
In OOP when a class forms a HAS-A relationship with another class, it's called an Aggregation, a simple example of that is below where a Car has an Engine but an engine can exist without a car:
class Engine {
start() {
console.log('Engine started');
}
}
class Car {
engine: Engine;
constructor(engine: Engine) {
this.engine = engine;
}
}
Question:
If i had to do the inverse of Aggregation such that i could answer a query Give me all the cars associated with this Engine, what is that called in OOP?
The aggregation (or composition, or association) is a concept: it allows to say that A has a B. You can invert the composition (B has an A) but the concept itself has no "inverse". Or it would be: A does not have B !
has-a as a static relationship gets translated to Aggregation. In a typical Object oriented modeling, after identifying the static relationship between two entities, next question we ask is which is more frequent direction in which we will be raising the queries.
In your example it is one-to-one relationship between objects (vehicle has only one engine and engine is mounted on only one vehicle at given moment).
If most of the time the query is getMeThisVehiclesEngine() (container to contained), then Vehicle holds the reference of engine, if the query is opposite (I think this is kind of your inverse) like getMeTheVehicleWhichIsHoldingThisEngine() (content to container. Here container and content terms are from the domain perspective), then engine will hold the reference of vehicle, and I would call it association. If we need bidirectional navigation, both objects keep each others reference. (In general we avoid bidirectional relationship). with one to one relationship, its not that obvious, but imagine an example of shared aggregation with has-a relationship between Athletics Team and member-student. member-students can be part of different teams simultaneously. From team to student-member I would call it as aggregation and Team will hold collection of Students. From Student-member to Team I would call it association (Student is associated with Athletics Team) and Student will hold either simple reference of Athletics team, or collection of Teams, if Student can be member of multiple teams simultaneously.
Example : Having a human that can own 1 or more pets of different types (cat, dog, elephant, seal etc) .
I would think of making an aggregate that would have Human as root (that holds petCollection as reference to Pet) and another aggregate that would have Pet as root (with cat, dog, elephant, eagle as children for this aggregate) .
The problem is that each pet type can have different behaviour (example : a seal can swin() but it won't fly() / an eagle can fly() but it won't swim() ) . So a state or strategy pattern does not seem right . How can a human tell a pet object to run() if it doesn't know it's type ? Using the state/strategy pattern, the objects need to have similar behaviour . Doing an if/else (for the case of polymorphism to check the object type) check again , doesn't seem a proper design .
How should i design this domain or what patterns can help me here ?
Generally speaking, if something (only/always) is something, you should use Inheritance.
If something does something, you should use an Interface.
If something plays the role of something (e.g. a Legal Party plays the role of a Customer and/or a Supplier) you should use Composition.
So Seal inherits Animal and implements Swim, Bark
and
Dog inherits Animal and implements Run, Bark
If you want your animals to swim, then either iterate them checking if they implement Swim and then call swim(), or filter the collection prior to iterating through it to get the animals that implement Swim.
Aggregate roots and inheritance is not a very good idea typically.
You probably want to avoid one Aggregate to have a collection of other Aggregates.
The idea of the Aggregate (well, one of them) is that it represents transaction boundary, therefore there, ideally, should be no need in this structure.
It is normal, however, when one Aggregate has a collection of other Aggregates IDs.
I'm not sure there's anything really architecture or DDD related here. It's just basic OO (polymorphism).
If your starting point is a single pet and you want to trigger a behavior particular to its species, no secret - the caller has to know which subtype the pet is and reference the object with its real subtype, not Pet.
If your starting point is a Human and you want to call some behavior across all or part of its pets, you need to reason about something more abstract. If I understand the domain well, something like "an action that a human can tell an animal to perform".
Once you've found the proper name for that, create an abstract method with that name on Pet and have every subclass of Pet implement it in its own way. Then, thanks to polymorphism, you can tell a collection of pets to do it regardless of whether they are cats, dogs, or elephants.
We are trying to adopt Domain-Driven Design in our project for the first time. The problem I have is with associations between entities. How do you do them right?
Say, I've got entities Employee and Contract, a simple one-to-many association. How do I model it?
Option 1: Aggregate.
Problem: The problem here is that, if I understand it correctly, all entities in an aggregate must be loaded when an aggregate object is created. I can't lazy-load entities when they are needed because it would require referencing a repository from an entity, which apparently is bad. But fetching all of an employee's contracts from the database every time would be a big performance issue.
Option 2: Fetching an employee's contracts by using a repository (e.g. ContractRepository.GetContractsForEmployee()) and adding EmployeeId property to Contract class.
Problem: it makes hard to put any business logic into entities. I would like to have a method, say, Employee.Dismiss(), but it would also need to update the employee's contract. This means I would need to put this logic in a service. The problem is, I can't think of much logic operating only on an Employee and thus the model would become somewhat anemic, with most logic inside services.
How do you deal with these issues in DDD?
This is just my take on it... without knowing your domain.
First, here is a good resource to read (part about Aggregates and Roots).
In DDD terminology, Employee and Contract are both entities (because they both have an identity).
"Aggregates draw a boundary around one or more Entities. and also: Each Aggregate has a Root Entity, which is the only member of the Aggregate that any object outside the Aggregate is allowed to hold a reference to."
The question is: do Employee and Contract form an aggregate, with Employee being the root entity? Obviously not, because other domain entities could also have a reference to a contract, and the contract id's are globally unique, not only within a Customer.
So, taking into account these rules, Employee and Contract are both aggregate roots.
Then: "Only aggregate roots can be obtained directly with queries; so this means that we should have a repository per aggregate root."
So in this case, we have an EmployeeRepository and a ContractRepository.
Taking all of this into account, I would not add a relation between employees and contracts in the domain model; but treat them separately. After all, if you need an Employee, you don't necessarily need his contracts too, they are both different aspects.
Option 2 is what I would choose: use the ContractRepository to get the contracts you are interested in. And if needed you could add a domain service that is responsible for aggregating employees and contracts if needed.
If you also define a Company entity, then dismissing an employee could be the job of that entity.
We recently got into the DDD approach as well. If I were to do it, I would have the following (attributes are simplified for brevity):
public class Employee() {
String name;
Set<ContractNumber> contracts;
public void addContract(ContractNumber contractNumber) {
this.contracts.add(contractNumber);
}
}
public class Contract() {
ContractNumber contractNumber;
Date effectiveDate;
}
public class ContractNumber() {
String contractNumber;
}
ContractNumber is a Value Object that is referred to from within Employee. In this example, Employee is within a BoundedContext that deals with Employees and their respective contracts. There may be other representations of Employee in other bounded contexts.
As discussed in other answers, there will be repositories for both Employee and Contract.
You need to find your true invariants.
Here you could have an invariant such as: you cannot dismiss an Employee that has already been dismissed.
If this is the only real invariant, then you could make one Employee aggregate, which would only have the IDs of the associated contracts.
Contract would be another aggregate (if needed).
If the dismiss() method succeeds, you could load the needed contracts and make the necessary changes.
I'm wondering if my textbook has a non-standard definition. I've red this question and it is not a duplicate. The book defines entities and entity sets as
An entity is an abstract object of some sort, and a collection of
similar entities forms an entity set. An entity is some ways resembles
an "object" in the sense of object-oriented programing. Likewise, an entity set bears some
resemblance to a class of objects.
When they say "class of objects" are they referring to a class as in the thing you instantiate to make new objects (I know this is just a loose comparison). It sounds like an entity set is more general than just an entity, but in this question a reply states "An entity set usually represents a slice of an entities data" which is the opposite.
I thought an entity is like a table in a database, then what's an entity set?
An entity is a real world object such as a person, a place or a thing or an abstract object such as a course, a flight reservation, etc. Here we use article 'a' or 'an' to indicate an instance of a specific person, a specific place or a specific thing as an entity. For example, I, by name 'Vidyasagar' is an entity and you are also an entity. All similar entities form entity set. Similar means each entity has the same (for simplicity) properties. All person entities will have same properties such as first name, middle name, last name, date of birth, etc. Entity and entity sets are analogous to relational database terms row/tuple and table/relation repectively. These are also analogous to OOPS terminology of objects and collection of objects respectively.
Obviously we can not store real world entities such as persons, toys, cities, etc., in a database! We can store only data about real world entities. The data consists of values for each property of entities. For example, data for city entities could be 'London' and 'UK' for London city entity, 'Paris' and 'France' for Paris city entity and 'Bangalore' and 'India' for Bangalore city entity. We use values of one or more properties (key) to refer to an entity for convenience. Hence when we say Paris entity, we mean the city Paris which is in France. That is we are referring to the pair of values Paris and France. The pair of values together is an entity. The three entities are ('London', 'UK'), ('Paris', 'France') and ('Bangalore', 'India'). There is no significance to parentheses used as such. These three entities will form an entity set, say, CITIES. Hope this is clear.
The definiton in your textbook in my opinion is not so clear. I find it very confusing.
I think you should stop at the first part of the definition:
An entity is an abstract object of some sort, and a collection of similar entities forms an entity set.
A set is simply a collection, a group of these entities. Usually the type of these entities is the same, so I suppose that saying:
an entity set bears some resemblance to a class of objects.
it means that objects in this collection/set are instance of the same class.
An entity is an abstract object of some sort, and a collection of similar entities forms an entity set. An entity is some ways resembles an "object" in the sense of object-oriented programing. Likewise, an entity set bears some resemblance to a class of objects
I am trynig to create a set of Models for our Enterprise App. It has never had them being tied very tightly to the Databases. At this point I am trynig to simply answer the "Is-A" or "Has-A" questions. I am basing this off the DB structure but I do not want to, neccesarily, be tied to that.
For starters I have the, very, obvious Person model with the typical "Has-A" Phone and Address. Almost everything works off of that Person model and is a "Has-A".
However, we have Members. In our DB/Current System a Member is a Person who has an Enrollment. To be specific an Enrollment of a certain type that is Dis-Enrolled(by Date).
On one hand I feel that Member would Inherit form Person as a "Is-A" relationship. However I am very new to this type of thing and I wonder if I am over thinking it. Does my Person "Has-A" Enrollment or does that imply something else?
It makes me wonder, if I do have a Member should I have different "Is-A" models for Pre-Enrollments, Enrollments, Former Enrollments? It seems that is more a question of State but again, I am new at this. If it is a question of state am I back to just having a Person model that "Has-A" Enrollment?
I understand this is, somewhat, opinion based and I welcome each persons opinion on this.
It makes more sense that Person be higher up in the heirarchy. From the group of all People, you have some members, some ex-members, and some members-to-be.
If you try to look at it the other way and say From the group of all Members, all are people...but some are Dis-Enrolled? It makes less sense that way since if they are Dis-Enrolled, then they are no longer members.
Unless being a Member and Enrollment are not connected (ie. if you can be dis-enrolled and still be a member).
Well, I'll try to answer you question though I don't fully understand what is "Enrollment" (I'm not native english speaker) I guess it some kind of Membership.
Suppose you will decide to use IS-A relationship, so you would end up with:
Member:Person, VIPMember:Member, ExMember:Member, etc. What would you do if you Person object changes to Member or anything else? You will have to convert you object to this type, create a Member object copy values from Person object... thats lots of boilerplate work.
If Object changes it Type after it's creation better use some property to distinguish it's type. Cosider Apple : Fruit (Apple is always Fruit, it can't become Tomato), and CanceledOrder : Order (Order can become CancledOrder so I would prefer Order.State). This is especially true for languages when once the object is created you can't change it's type (like C#).
As for your case from what I understood I would create:
public class Person
{
public IEnumerable<Membership> Memberships {get;}
public bool IsMember
{
get
{
return Memberships.Any();
//Or what ever logic you imply
}
}
}