9

假设我有典型的实体Car

class Car : Entity
{
    public double MaxSpeed { get; set; }
    public Color Color { get; set; }
    /* ... */
}

在我的域模型中,这个实体将是Aggregate的根实体

现在假设我专攻汽车。我创造了一辆法拉利,而快乐的法拉利车主喜欢给他们起一个绰号:

class Ferrari : Car
{
    public string Nickname { get; set; }
}

假设我有另一个实体,即公司实体。它将是另一个Aggregate的根实体。有很多人在公司工作,由实体Person表示。人可能有汽车。但是一家公司的总裁通常都很有钱,这种人,他们有法拉利:

class President : Person
{
    public Ferrari Ferrari { get; set; }
}

在这种情况下,我的实体 President位于Company Aggregate内部,它持有对 Ferrari 的引用,这是另一个聚合的根实体的专业化。

鉴于 DDD,这是正确的吗?我可以/应该将根实体本身的专业化视为同一聚合的根实体吗?我的意思是,在我描述的领域中,实体 Ferrari 也是 Car Aggregate 的根实体(因为 Ferrari 也是 Car)?


现在假设我必须将此模型持久保存到 Database。我认为我的问题不取决于我将使用的 OR/M 框架。

我应该如何建造装有 Cars 的桌子?我应该构建一个带有“CarType”列(可能的值:“Car”、“Ferrari”)和一个可为空的 Nickname 列的 Cars 表吗?

或者我应该为汽车和法拉利建立一个表,后者的 PK 是汽车的 FK?

谢谢!

4

3 回答 3

4

您不应该使用继承来为您的域建模,因为一旦模型开始变得复杂,您很快就会遇到麻烦。

总统只是一个角色,人可以有多个角色。也许总统只有一个角色,但这只是通过选择错误的例子而偶然发生的。

法拉利也不应该从汽车继承。这在法拉利的例子中并不明显,因为他们只生产一种类型的汽车,但考虑到公司生产多种类型的汽车,如面包车、轿车、掀背车、卡车等。您可能希望为从汽车类继承的每种类型创建类。然后……你打算创建五个继承自每种类型的 Toyota 类吗?如...

Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback

那将是荒谬的。

免责声明:我对汽车一无所知。然而...

不要使用继承来为您的域建模。曾经。

在没有继承的情况下尝试它,如何持久化您的域也将变得显而易见。

于 2009-08-29T20:21:44.500 回答
4

通常,当您跨越根聚合边界时,您只允许引用是另一个根聚合的 ID。然后,您使用该 ID 在其存储库中查找另一个聚合。

因此,在您的情况下,您希望总统拥有汽车 ID,如果您需要对总统的汽车做某事,您将使用汽车 ID 去存储库获取汽车。总统不会提及汽车本身。

现在关于那辆法拉利。在标准的 DDD 术语中执行这一点有点困难。通常,您会对将汽车分配给总统进行一些验证。或者,也许有一个专为总统准备的 CarBuyingService,可以确保您做对了。通常在 DDD 中,特化本身并不是根聚合。

于 2009-08-29T20:23:18.727 回答
3

我认为通过创建这些实体的具体类型,您开始失去系统的很多灵活性。您所暗示的关系类型是我通常使用“类型”实体处理的。例如,你有一辆车。法拉利是一种汽车。从中产生的两个实体是 Car 和 CarType。

您正在谈论这样做的方式,每次引入新类型时都必须添加新实体。如果您要捕获的只是汽车的“昵称”,我会认为这只是另一条数据,而不是另一个实体。除非您在不同类型的 Car 实体中有不同的数据(即不同的属性名称)和/或行为差异,否则您不会通过这种方法获得太多收益。我宁愿拥有像 FindCarByType() 这样的存储库方法并处理一种类型的实体,以降低风险。

我绝不是 DDD 专家,我正在为一些概念苦苦挣扎(或者更像是在为一些概念的多种解释苦苦挣扎)。我发现没有 100% 的纯实现,而且我看到的每个实现都有细微差别。

编辑关注

我看到我误读了你写的部分内容。我看到这个昵称并非适用于所有车辆,而仅适用于法拉利:汽车。我认为答案确实是“取决于”。您在模型的其余部分有多少领域专业化?拥有昵称可能在法拉利实体中很普遍,但它是独一无二的吗?它不仅与实际数据有关,而且与要求有关。基本上,这取决于您对这些实体的期望程度。

于 2009-08-29T19:52:30.207 回答