DDD: Instantiate Value objects inside Aggregate or pass it as parameter?
Asked Answered
N

3

10

When creating aggregates, should we create value objects inside aggregates, or we should pass already created value objects to ctor or factory.

 public Booking(DateTime arrivalDate, DateTime departureDate)
 {
      this.ArrivalAndDepartureinformation = new ArrivalAndDepartureInfo(arrivalDate, departureDate);
 }

or

 public Booking(ArrivalAndDepartureinformation arrivalAndDepartureInfo)
 {
            this.ArrivalAndDepartureinformation = arrivalAndDepartureInfo;
 }
Nietzsche answered 6/9, 2016 at 13:7 Comment(1)
The question is: How do you use those constructors and where do those constructor parameters come from?Hardison
H
9

Instantiate Value objects inside Aggregate or pass it as parameter?

  • If we speak about passing parameters into constructor, it depends on how it is used. There might be some infrastructure limitations that can require usage of primitive types.

  • If we speak about passing parameters into methods then Value Objects is 100% my choice.

In general, I'd say it is better to pass value objects into your aggregates.

Value Objects can:

  • make language of you model more expressive
  • bring type safety
  • encapsulate validation rules
  • own behavior
Hardison answered 8/9, 2016 at 18:25 Comment(2)
So input parameters which are sent to application service, are used to construct value objects which will be sent to aggregate factory or constctorsNietzsche
Yes. And you can get less parameters, more specific types for you parameters and more expressive language in your model.Hardison
T
6

The general guideline I would recommend is this:

  • Inside the domain model, use value objects as much as possible.
  • Convert primitives into value objects at the boundary of the domain model (controllers, application services).

For example, instead of this:

public void Process(string oldEmail, string newEmail)
{
    Result<Email> oldEmailResult = Email.Create(oldEmail);
    Result<Email> newEmailResult = Email.Create(newEmail);

    if (oldEmailResult.Failure || newEmailResult.Failure)
        return;

    string oldEmailValue = oldEmailResult.Value;
    Customer customer = GetCustomerByEmail(oldEmailValue);
    customer.Email = newEmailResult.Value;
}

Do this:

public void Process(Email oldEmail, Email newEmail)
{
    Customer customer = GetCustomerByEmail(oldEmail);
    customer.Email = newEmail;
}
Thresathresh answered 13/9, 2016 at 0:20 Comment(0)
A
3

The domain model should speak domain, not implementation primitives.

Your application component normally owns the responsibility of taking raw data and expressing it in the model's language.

Abcoulomb answered 6/9, 2016 at 14:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.