9

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;
 }
Robert
  • 3,353
  • 4
  • 32
  • 50

3 Answers3

8

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
Ilya Palkin
  • 14,687
  • 2
  • 23
  • 36
  • 2
    So input parameters which are sent to application service, are used to construct value objects which will be sent to aggregate factory or constctors – Robert Sep 08 '16 at 18:40
  • Yes. And you can get less parameters, more specific types for you parameters and more expressive language in your model. – Ilya Palkin Sep 08 '16 at 23:23
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;
}
Vladimir
  • 1,630
  • 2
  • 18
  • 28
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.

VoiceOfUnreason
  • 52,766
  • 5
  • 49
  • 91