How to model inheritance on DDD?

domain-driven-design

Solution

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.

Problem

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. 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? Or should I not be using inheritance? Why? 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?

Original source