Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to model inheritance on DDD?

I am currently trying out DDD and reading Evans book. I have arrived at a model that has an aggregate whose root is Student. Now I need to have (or be able to distinguish) a RegisteredStudent and an EnrolledStudent (inherits RegisteredStudent). I don't know how to handle inheritance in DDD.

  1. Should the 2 inherited classes be inside the aggregate? If so, are they also considered aggregate roots since their identity is the same as the root (there are only added properties to them)? If not, how do I give access to them from other entities?

  2. Or should I not be using inheritance? Why?

  3. And also, what if you have an entity in an aggregate that isn't a root, but you need it to inherit an entity outside? How should you go about it?

like image 685
g_b Avatar asked May 31 '14 10:05

g_b


People also ask

Is it possible to use inheritance in a database model?

However, it is also possible to use inheritance when defining a database model. When we create the logical model, we can apply the concept of inheritance to represent the idea that an entity (often called the child entity) is derived (i.e. it inherits) from another entity (the parent entity).

What is inheritance in a logical model?

When we create the logical model, we can apply the concept of inheritance to represent the idea that an entity (often called the child entity) is derived (i.e. it inherits) from another entity (the parent entity). Usually, the child entity has all the elements of its parent entity, plus some additional attributes.

What are the columns in the inheritance model of the vehicle?

Note that the table vehicle has columns taken from four different entities in the inheritance model: vehicle, car, bike, and electrical_bike. Many columns are nullable; in this table we can represent car objects or bike objects; thus, if a record is representing a car, all bike related attributes will be NULL.

What is a generated inheritance table?

In other words, all the attributes from any entity in the inheritance will be in the generated table. It is important to note that the generated inheritance table will have an additional column called discriminator, which will be used to identify what type of entity in the hierarchy the record is representing.


1 Answers

What you need to ask yourself here is whether a RegisteredStudent and an EnrolledStudent are different concepts. Are they not both students, but just in a different state?

In general, you should favor composition over inheritance.

Here's an example of what I would do. (Note that it's just my example, I don't know the domain, so it's not a definitive solution).

You could have a Student class, which is your aggregate root and then a few different state classes: Registered and Enrolled. That way you don't need to expose these state classes on the student but you could just expose methods on the Student. A small example in C#:

class Student
{
    State _currentState;
    void Enroll()
    {
        if(!_currentState is Registered)
            throw new InvalidOperationException("Cannot enroll student who is not registered");

        this._currentState = new Enrolled();
    }

    void Register(string name)
    {
        this._currentState = new Registered(name);
    }
}

class StudentState{}

class Enrolled : StudentState
{}

class Registered : StudentState
{
    public Registered(string name)
    {
        Name = name;
    }
    public string Name {get; private set;}
}

This is a simple application of the State design pattern, you could externalize more parts of it and build a complete state-machine, but I'll leave that up to you. (Also it's typed directly in to the SO-editor, so there could be syntax errors)

EDIT after comments

Whether you need to expose a State-property or not depends on the context. In general I would recommend not to do that, because you're exposing the internals of the Student. It would be better to expose a method called CanEnroll for example. That way you can change the internal implementation of your state pattern without affecting any clients.

As for question 3, it's hard to say without a use case. However, here are some guidelines:

  • Favor composition over inheritance (again, I know).
  • You can have a reference from inside an aggregate to the outer world, you shouldn't have a reference the other way around though.
like image 137
Kenneth Avatar answered Oct 01 '22 11:10

Kenneth