1

I have an aggregate root "Car" A car has a list of value objects "Wheels" containing "Wheel" objects. Since a car should not exist without wheels (at least according to our business logic), in order to construct a car is this valid in proper domain driven design:

double radius = 17.0;
List<Wheel> carWheels = new List<Wheel>();
carWheels.add(new Wheel(radius));
Car aCar = new Car(carWheels);

My question is basically, is it good practice to instantiate value objects outside of an aggregate root in order to construct an aggregate root (passing value objects in constructor). I don't want to create an aggregate root in an invalid state and would like to follow best practices. If the above code is not best practice, how should it be done?

Ilan Y
  • 107
  • 9

3 Answers3

3

IMHO it is neither a bad practice nor a good practice. All depends on the actual domain which you are trying to model. It might make sense to create those VOs outside the aggregate in some cases and in others it will just open up your domain for malicious usage. DDD forces you to forget a bit about technical problems and bad/good practices in order to focus on the actual domain:

  1. Would it make sense in any scenario to create a car with 26 wheels? Your example model allows that
  2. Whould it make sense in any scenario to create a car with 4 wheels, each having different radius? Your example model allows that
  3. Whould it make sense to create a wheel with radius 17.3284546? Again, your model allows that to happen

Therefore, in my opinion for the example which you've shown, it might be better to handle those invariants inside the aggregate itself because you can nicely constrain the number of things than can be done to car and wheels when both are created. However, that comes from a closer look at the domain itself rather than relying on widely known good or bad practices. Just to reiterate, there will be cases in which you'll be better off by creating VOs outside the aggregate. All depends on the domain.

dmusial
  • 1,504
  • 15
  • 14
  • The allowed size of any wheel may be validated inside Wheel. The number and configuration of wheels per car may be validated inside Car. There are two independent validations here. Somewhere in the application, it may also make sense to manufacture 100 wheels (i.e.: not just 4 at a time). I accept your answer that it is not a good or bad practice and that it depends on the domain. Thank you. – Ilan Y Mar 25 '14 at 01:37
1

I like this approach. In test cases, we could inject stub/mock Wheels to Car.

I would introduce a CarFactory if there are complex business constraints in the construction of wheels or car.

Yugang Zhou
  • 7,123
  • 6
  • 32
  • 60
  • Thanks. What do you think about validation inside Wheel? – Ilan Y Mar 23 '14 at 16:10
  • @IlanY You may find something helpful [here](http://stackoverflow.com/questions/22263646/unit-testing-value-objects-in-isolation-from-its-dependencies) – Yugang Zhou Mar 24 '14 at 01:14
1

In this concrete example, I would give radius to Car's constructor and let it build wheels by itself. That way you would hide instantiation details from your client's code (less knowledge outside of your aggregate) and your client would not be affected by internal changes of Car aggregate.

You should prefer building aggregates in only one step/operation/action. If it's not just one step, your aggregate is inevitably showing some details of it's internal structure.

gseric
  • 649
  • 4
  • 11