Orm DDD:子类和;根实体

Orm DDD:子类和;根实体,orm,domain-driven-design,entity,aggregate,Orm,Domain Driven Design,Entity,Aggregate,假设我有一辆典型的实体车 在我的域模型中,这个实体将是聚合的根实体 现在让我们假设我专门研究汽车。我创造了一辆法拉利,法拉利的快乐车主喜欢给他们起个绰号: class Ferrari : Car { public string Nickname { get; set; } } 假设我有另一个实体,公司实体。它将是另一个聚合的根实体。有许多人在一家公司工作,以实体人为代表。人们可能有汽车。但是一家公司的总裁通常非常富有,这种人有法拉利: class President : Person

假设我有一辆典型的实体车

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

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

class Ferrari : Car
{
    public string Nickname { get; set; }
}
假设我有另一个实体,公司实体。它将是另一个聚合的根实体。有许多人在一家公司工作,以实体人为代表。人们可能有汽车。但是一家公司的总裁通常非常富有,这种人有法拉利:

class President : Person
{
    public Ferrari Ferrari { get; set; }
}
在这种情况下,我有一位实体总裁,他在公司集合中,持有法拉利的参考,法拉利是另一个集合的根实体的专门化

<强>从DDD看这是正确的吗?< /强>我是否应该考虑根实体的专业化作为同一个聚合的根实体?我的意思是,在我描述的领域中,实体法拉利也是汽车集合的根实体吗(因为法拉利也是一辆汽车)


现在让我们假设我必须将此模型持久化到数据库中。我认为我的问题不取决于我将使用的OR/M框架

我应该如何建立容纳汽车的表格?我是否应该构建一个单表Cars,其中包含一个“CarType”列(可能的值为:“Car”、“Ferrari”)和一个可为空的昵称列

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


谢谢

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

按照您所说的方法,每次引入新类型时都必须添加新实体。如果您试图捕获的只是汽车的“昵称”,我会认为这只是另一段数据,而不是另一个实体。除非您在不同类型的汽车实体中有不同的数据(即不同的属性名称)和/或行为差异,否则这种方法不会带来太多好处。我宁愿使用像FindCarByType()这样的存储库方法,并处理一种类型的实体,以降低风险

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

编辑以下内容


我看出我误读了你写的部分内容。我知道这个绰号并不是适用于所有的汽车,只是适用于法拉利:汽车。我认为答案是“视情况而定”。在模型的其余部分中,您有多少领域专门化?拥有一个昵称在法拉利实体中可能很普遍,但它是排他性的吗?这不仅与实际数据有关,还与需求有关。基本上,这取决于您对这些实体的期望专门化程度。

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

总统只是一个角色,一个人可以扮演多种角色。也许总统只扮演了一个角色,但选择了错误的例子,这纯属偶然

法拉利也不应该继承自汽车。这在法拉利的例子中并不明显,因为他们只做一种类型的汽车,但是考虑到公司制造了很多类型,如厢式车、轿车、掀背车、卡车等等。您可能希望为从car类继承的每种类型创建类。然后呢。。。您是否要创建五个Toyota类来继承每种类型?比如

Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback
那太荒谬了

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

不要使用继承对域进行建模。永远。


在不继承的情况下尝试它,也会发现如何持久化您的域。

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

因此,在你的情况下,你会希望总统有一个汽车ID,如果你需要对总统的汽车做些什么,你会使用汽车ID去仓库取车。总统不会提及汽车本身


现在说说那辆法拉利。在标准的DDD术语中很难实现这一点。通常情况下,你会对一辆车交给总统的任务进行确认。或者,也许有一个专门为总统提供的CarBuyingService,可以确保你做对了。通常在DDD中,专业化本身不是根聚合。

太棒了!非常感谢。事实上,在我的“真实”系统中,“汽车”非常重要,但“法拉利”是我的领域中最重要的东西,我不能忘记,我必须对它进行统计。谢谢,卢布斯。但在这种情况下,在我的“真实”领域中,我有“汽车”,有“通用”汽车和两种特殊类型的汽车,“法拉利”和“保时捷”,尽管它们本质上是“汽车”。不过,还是要避免继承。即使您不这样做,您也必须在一两年内完成,因为您的模型在将来可能会变得更加复杂,以捕获新的需求,继承将在您的设计中带来很多痛苦。教科书上解释遗传的例子,如猫和狗都是动物,圆圈和正方形都是形状,给人的印象是什么是遗传
Car -> Sedan -> ToyotaSedan
Car -> Truck -> ToyotaTruck
Car -> Hatchback -> ToyotaHatchback