两部分问题
我有一个产品聚合;
价格 PackagingOptions ProductDescriptions ProductImages 等
我已经为一个产品存储库建模,并没有为任何子类创建单独的存储库。所有数据库操作都通过产品存储库处理。
到目前为止,我是否正确理解DDD概念?有时,我想到的问题是,拥有一个存储库,让我们说包装选项可以通过使用其ID直接从数据库中获取包装选项而不是要求产品存储库在其PackagingOptions集合中找到它并让它给我..
第二部分是使用ASP.MVC框架工作管理编辑创建操作
我目前正在尝试通过产品控制器管理所有这些子产品系列的添加编辑删除(声音对吗?)。
我现在面临的一个挑战是:
如果我通过
编辑产品的特定包装选项MYDOMAIN /产品/ editpackagingoption / 10
我可以访问包装选项的ID
但我没有自己的产品ID,这迫使我写一个查询,首先找到具有此特定包装选项的产品,然后编辑该产品和重新包装选项。我可以这样做,因为所有包装选项都有其唯一ID,但如果我的集合没有唯一ID,则会失败。
感觉非常错误。
我想到的下一个选项是在网址上发送产品和包装选项ID,如:
MYDOMAIN /产品/ editpackagingoption / 3/10
但我不确定这是否也是一个好设计。
所以我觉得我有点困惑。可能会对所有这些产生根本性的误解......
如果你忍受长期问题并帮助我把它放在一起,我将不胜感激。谢谢!
答案 0 :(得分:3)
在我看来,这是DDD中出现的那些泥泞的东西之一。
在代码中,我将聚合根视为它拥有的任何“关系”的容器,以及没有聚合根时不能存在的任何实体对象。
例如,让我们采取客户 - >订单 - > LineItem->产品示例,现在已被击毙。我在这个场景中显示的聚合根是客户。这就是说,您并不总是希望通过客户获得订单。您可能希望在特定日期查找订单。
将它打开,你也没有没有订单的客户。两者处于一种有点共生的关系中,因此一个不是另一个的集合根。
关键是您不希望通过订单加载客户,但您不一定要通过客户加载订单。
从订单开始,您不太可能只想检索LineItem,而且您肯定不会在没有订单的情况下创建它们。为此,Order作为LineItems的门户。 LineItems不需要自己的控制器或存储库。它们只存在于订单本身中,因此是订单的一部分(在这种情况下,订单成为聚合根),并由订单实体管理。
但是,LineItem可能与系统中的产品有关系。产品将拥有自己的控制器,存储库等,因为它们可以存在于聚合根之外。
总而言之,我倾向于以这种方式看待它:如果一个实体本身可以存在,它应该有一个控制器。不能独立存在的实体(本例中为LineItems)应仅由其容器(聚合根)管理。
如果我错了,某些DDD纯粹主义者会纠正我吗?
关于你问题的第二部分,我需要更多关于你如何设想这些其他实体工作的细节。根据您的内容,我认为PackagingOptions与产品相关,并且是Product聚合根的一部分。现在,暗示你正在编辑它们的问题是这是一个系统中的查找表还是一次性值,因此应该被视为值对象?
答案 1 :(得分:1)
Kaivalya,
关于你的最后评论(无状态http):
这取决于具体情况。在详细介绍之前,我应该告诉你一个关于聚合的基本原则:
聚合定义了一组相关对象,这些对象应被视为一个单元以进行数据更改。
这非常重要。拥有Aggregates的目的是强制执行不变量。例如,您可能有一个类似“订单不能超过500美元”的政策。然后,要强制执行此策略,请将Order和OrderItem放在Order Aggregate中。这样,无论何时添加新的OrderItem,都应该通过Order对象添加。在那里,您可以检查总价格并确保它不超过500美元。如果您的域中没有此类不变量,则无需将所有这些对象加载到一起。
现在,回到你的评论:
如果你确实有应该强制执行的不变量,那么即使它可能有一些开销,也可以加载整个聚合。是的,HTTP是无状态的,你加载整个聚合只是为了修改它的一个子对象,然后把它扔掉。好的,可以。最重要的是你正在强制执行不变量。这就是DDD的用途。
DDD的目的是捕获域中的所有业务逻辑。如果您不必加载整个聚合,那么您肯定可以获得更好的性能,但是如何强制执行不变量?您很可能必须在存储过程中执行此操作。是的,它有效,并且速度很快,但在维护期间处理存储过程中的业务逻辑是一场噩梦。这就是DDD发展的原因。因此,您可以使用面向对象的语言/工具来模拟业务需求,以便更容易理解和修改。
请记住,DDD是一种很好的方法,但不适用于所有类型的项目。如果您正在处理一个项目,其中有很多业务逻辑,并且由于业务性质而导致它们发生变化的可能性很高,那么您应该使用DDD。但是,如果您的项目更多的是“阅读某些东西/写东西”而没有涉及太多的业务逻辑,那么使用DDD是一个令人头疼的问题。您可以简单地使用LINQ to SQL(或SqlDataAdapters)并将您的对象发送到您的视图。您甚至不必担心找到实体,值对象,聚合,存储库等。
希望这有帮助,
MOSH