1

我有一个聚合根“汽车”汽车有一个包含“车轮”对象的值对象“车轮”列表。由于没有轮子的汽车不应该存在(至少根据我们的业务逻辑),为了构建汽车,这在适当的领域驱动设计中是否有效:

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

我的问题基本上是,在聚合根之外实例化值对象以构造聚合根(在构造函数中传递值对象)是否是一种好习惯。我不想在无效状态下创建聚合根,并希望遵循最佳实践。如果上面的代码不是最佳实践,应该怎么做?

4

3 回答 3

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.

于 2014-03-24T21:55:17.247 回答
1

我喜欢这种方法。在测试用例中,我们可以将 stub/mock Wheels 注入 Car。

如果在制造车轮或汽车时存在复杂的业务限制,我会介绍 CarFactory。

于 2014-03-23T12:30:23.600 回答
1

在这个具体的例子中,我会给 Car 的构造函数指定半径,让它自己构建轮子。这样,您将隐藏客户端代码中的实例化详细信息(聚合之外的知识较少),并且您的客户端不会受到 Car 聚合的内部更改的影响。

您应该更喜欢仅在一个步骤/操作/操作中构建聚合。如果这不仅仅是一个步骤,那么您的聚合不可避免地会显示其内部结构的一些细节。

于 2014-03-25T10:00:18.960 回答