Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DDD entity constructor parameters

If you have an entity with a value object as an attribute.

Which would be the parameters of the entity constructor, the value object? Or the primitive types of the value object?

First I did it building the value object outside the entity and I passed the value object to the entity constructor... but then I realized that maybe it would be the entity itself that has to build the value object.

I thought this because the entity and the value object are in fact an aggregate, and it is supposed that you have to access the inside of an aggregate through the aggregate root, i.e., through the entity.

So which is the right way? Is it allowed to deal with the value object outside the entity? Or the value object just can be used by the entity?

Thank you.

EDIT:

For example, I have an entity "Task" that is the aggregate root. This entity has a value object "DeliveryDate" (in format "dd/mm/yyyy hh:mm"). The entity has more value objects too.

class DeliveryDate extends ValueObject {

    private String formattedDeliveryDate;

    private DeliveryDate() {
        super();
    }

    DeliveryDate ( String formattedDeliveryDate ) {
        this();
        this.setFormattedDeliveryDate ( formattedDeliveryDate );
    }

    private void setFormattedDeliveryDate ( String formattedDeliveryDate ) {
        << check that the string parameter "formattedDeliveryDate" is a valid date in format "dd/mm/yyyy hh:mm" >>
        this.formattedDeliveryDate = formattedDeliveryDate;
    }

    ........     

The entity constructor:

Task ( TaskId taskId, Title title, Delivery deliveryDate, EmployeesList employeesList ) {
    this();
    this.setTaskId(taskId);
    this.setTitle(title);
    this.setDeliveryDate(deliveryDate);
    this.setEmployeesList(employeesList);
}

My doubt is: Is this ok? (passing to the constructor the DeliveryDate object) Or should I pass the string? (and the constructor creates the DeliveryDate object)

I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"

In general my doubt is about any value object of any entity, not just Task and DeliveryDate (this is just an example).

I have asked the question about the constructor, but it's valid for factories too (if the process of creating an instance is complicated)... should the aggregate factory parameter be the value object? or the primitives to create the value object?

like image 302
choquero70 Avatar asked Oct 15 '25 14:10

choquero70


2 Answers

In your case it might seem that the two solutions are similar. It doesn't really matter if you create the value object outside or inside of the entity. But think about when your entity will have more than one value object, the entity constructor will contain too much logic in order to make sure it creates the VOs correctly and at the same time enforce the entity's invariants.

One solution to avoid this unnecessary complexity is to use factories. The factory will abstract the creation process and this will keep you entity code simple.

In DDD, factories are very useful for creating aggregates. In the blue book there is a whole chapter about factories and here is good article about the use of factories in DDD http://culttt.com/2014/12/24/factories-domain-driven-design/

Edit

My doubt is: Is this ok? (passing to the constructor the DeliveryDate object) Or should I pass the string? (and the constructor creates the DeliveryDate object)

Yes, it is ok. Task should not know about how to create the value objects. You should not pass the strings cause that will add more complexity and responsibilities to the Task constructor.

I think it's more a question of "should the outside of the aggregate know about the DeliveryDate concept?"

Yes, it is not problems that the outside of the aggregate knows about the DeliveryDate. It is the same as knowing about strings and integer. Value objects are simple to deal with and reason about and they are part of the domain so I think there is no problems in dealing with them outside of the aggregate.

should the aggregate factory parameter be the value object? or the primitives to create the value object?

Here I would say the Factory should receive the primitive types and encapsulate the objects creation. cause if you pass the values objects to the factory it will just pass the same parameters to the Entity constructor and that is a middleman code smell.

like image 112
Mohamed Bouallegue Avatar answered Oct 18 '25 08:10

Mohamed Bouallegue


Domain Driven Design doesn't offer any specific guidance here.

A common case might look something like this: we've retrieved a DTO from the database, and now want to create a Entity from it....

class Entity {
    private Value v;

    Entity (Value v) {
        if (null == v) throw new IllegalArgumentException();

        this.v = f;
    }

    Entity (DTO dto) {
        this(new Value(dto));
    }

    // ...
}

Does it really matter if you invoke the second constructor rather than the first? Not much.

A language check:

DTOs are not retrieved from database. What you retreive from a database is an aggregate, not a DTO

I had to abandon that idea - that definition leads to too many problems.

For example, in event sourced designs, the database typically stores representations of events, not aggregates.

Even in traditional designs, it doesn't hold up -- the boundaries of your aggregates are defined by the constraints enforced by the domain model. Once you take the data out of the domain model, what you have left is just representations of state. Expressed another way, we save state in the database, but not behaviors, and not constraints -- you can't derive the constraints from the saved data, because you can't see the boundaries.

It's the model, not the database, that decides which data needs to be kept internally consistent.

I tend to use the term DTO because that's its role: to carry data between processes -- in this particular instance, between the data base and the domain model. If you wanted to use message or document instead, I wouldn't quibble.

like image 21
VoiceOfUnreason Avatar answered Oct 18 '25 10:10

VoiceOfUnreason



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!