views:

462

answers:

3

Hello. I'm new to DDD.

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!

+2  A: 

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.

joseph.ferris
Fantastic! Thank you!Actually, in my "real" system, "Cars" are very important, but the "Ferrari" is the single most imporant thing in my domain, that I can't loose track of, I must do statistics on it.
Bruno Reis
+2  A: 

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.

lubos hasko
Thanks, lubos. But in this case, in my "real" domain, I *have* "cars", and there are "generic" cars and 2 special kinds of cars, "Ferrari" and "Porsche" that must be tracked down, although they are essentially "Cars".
Bruno Reis
still, avoid inheritance. even if you don't, you will have to in one or two years because your model will likely get more complicated in the future to capture new requirements and inheritance will cause lots of pain in your design. textbook examples to explain inheritance like Cat and Dog are both Animals and Circle and Square are both Shapes are giving wrong impression what is inheritance really for and programmers often abuse this powerful concept for modeling domains. read more here: http://www.geocities.com/tablizer/oopbad.htm#overeng (I'm not the author)
lubos hasko
Very good article! Thanks!
Bruno Reis
+2  A: 

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.

Mike Two