DDD/NHibernate 聚合根的使用及其对网页设计的影响 - 例如。编辑聚合根的子级
希望这个虚构的例子能够说明我的问题:
假设您正在编写一个系统,用于跟踪软件产品的投诉以及有关该产品的许多其他属性。在这种情况下,SoftwareProduct 是我们的聚合根,而 Complaints 是只能作为产品子项存在的实体。换句话说,如果软件产品被从系统中删除,投诉也会随之消失。
在系统中,有一个类似于网页的仪表板,它显示单个软件产品的许多不同方面。仪表板中的一个部分以类似网格的方式显示投诉列表,仅显示每个投诉的一些非常高级的信息。当管理员类型用户选择其中一项投诉时,他们将被定向到编辑屏幕,允许他们编辑单个投诉的详细信息。
问题是:编辑屏幕检索单个投诉的最佳方式是什么,以便可以将其显示用于编辑目的?请记住,我们已经将软件产品建立为聚合根,因此不应允许直接访问投诉。另外,系统使用 NHibernate,因此急切加载是一个选项,但我的理解是,即使通过 SoftwareProduct 急切加载单个投诉,只要访问投诉集合,就会加载该集合的其余部分。那么,如何通过 SoftwareProduct 获取单个投诉,而又不会产生加载整个投诉集合的开销?
Hopefully, this fictitious example will illustrate my problem:
Suppose you are writing a system which tracks complaints for a software product, as well as many other attributes about the product. In this case the SoftwareProduct is our aggregate root and Complaints are entities that only can exist as a child of the product. In other words, if the software product is removed from the system, so shall the complaints.
In the system, there is a dashboard like web page which displays many different aspects of a single SoftwareProduct. One section in the dashboard, displays a list of Complaints in a grid like fashion, showing only some very high level information for each complaint. When an admin type user chooses one of these complaints, they are directed to an edit screen which allows them to edit the detail of a single Complaint.
The question is: what is the best way for the edit screen to retrieve the single Complaint, so that it can be displayed for editing purposes? Keep in mind we have already established the SoftwareProduct as an aggregate root, therefore direct access to a Complaint should not be allowed. Also, the system is using NHibernate, so eager loading is an option, but my understanding is that even if a single Complaint is eager loaded via the SoftwareProduct, as soon as the Complaints collection is accessed the rest of the collection is loaded. So, how do you get the single Complaint through the SoftwareProduct without incurring the overhead of loading the entire Complaints collection?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
这有点涉及语义和宗教信仰,但在编辑投诉的上下文中,投诉是根对象。当您编辑投诉时,父对象(软件产品)并不重要。它显然是一个具有独特身份的实体。因此,您将有一个服务/存储库专门用于保存更新的投诉等。
另外,我认为您有点过于消极。投诉? “评论”怎么样?还是“建设性批评”?
This gets a bit into semantics and religiosity, but within the context of editing a complaint, the complaint is the root object. When you are editing a complaint, the parent object (software product) is unimportant. It is obviously an entity with a unique identity. Therefore you would would have a service/repository devoted to saving the updated complaint, etc.
Also, i think you're being a bit too negative. Complaints? How about "Comments"? Or "ConstructiveCriticisms"?
@Josh,
我不同意你的说法,尽管我注意到有些人只是为了性能而这样设计他们的“Web”应用程序,而不是基于域模型本身。
我也不是 DDD 专家,但我确信您已经阅读过传统的 Order 和 OrderItem 示例。所有 DDD 书籍都说 OrderItem 属于 Order 聚合,而 Order 是聚合根。
根据您的说法,OrderItem 不再属于 Order 聚合,因为用户可能希望直接编辑 Order 不重要的 OrderItem (就像编辑 Complain 其父软件产品不重要一样)。而且您知道,如果遵循这种方法,则无法强制执行任何订单不变量,这对于电子商务系统而言非常重要。
有人有更好的方法吗?
莫什
@Josh,
I don't agree with what you are saying even though I have noticed some people design their "Web" applications this way just for the sake of performance, and not based on the domain model itself.
I'm not a DDD expert either, but I'm sure you have read the traditional Order and OrderItem example. All DDD books say OrderItem belongs to the Order aggregate with Order being the aggregate root.
Based on what you are saying, OrderItem doesn't belong to Order aggregate anymore since the user may want to directly edit an OrderItem with Order being unimportant (just like editing a Complaing with its parents Software Product being unimportant). And you know if this approach is followed, none of the Order invariants could be enforced, which are extremely important when it comes to e-commerce systems.
Anyone has any better approaches?
Mosh
回答你的问题:
使用聚合是为了保持一致性。例如,如果从父对象(聚合根)添加/修改/删除子对象会导致不变量破坏,那么您需要在那里进行聚合。
但是,在您的问题中,我相信 SoftwareProduct 和 Compliant 属于两个单独的聚合,每个聚合都是其自己聚合的根。您无需加载 SoftwareProject 和分配给它的所有 N 个投诉,只需添加新的投诉即可。对我来说,在添加新投诉时,您似乎没有任何需要评估的业务规则。
因此,总而言之,创建 2 个不同的存储库:SoftwareProductRepository 和 ComplaintRepository。
此外,当您删除软件产品时,您可以使用数据库关系来级联删除并删除关联的投诉。出于数据完整性的目的,应该在您的数据库中完成此操作。您不需要在域模型中控制它,除非除了删除链接对象之外还有其他不变量。
希望这有帮助,
莫什
To answer your question:
Aggregates are used for the purpose of consistency. For example, if adding/modifying/deleting a child object from a parent (aggregate root) causes an invariant to break, then you need an aggregate there.
However, in your problem, I believe SoftwareProduct and Compliant belong to two separate aggregates, each being the root of their own aggregates. You don't need to load the SoftwareProject and all N Complaints assigned to it, just to add a new Complaint. To me, it doesn't seem that you have any business rules to be evaluated when adding a new Complaint.
So, in summary, create 2 different Repositories: SoftwareProductRepository and ComplaintRepository.
Also, when you delete a SoftwareProduct, you can use database relationships to cascade deletes and remove the associated Complaints. This should be done in your database for the purpose of data integrity. You don't need to control that in your Domain Model, unless you had other invariants apart from deleting linked objects.
Hope this helps,
Mosh
我将 NH 用于另一个业务环境,但与您的类似的实体关系。我不明白你为什么说:
我在我的
Article
和Publisher
实体中拥有此内容,如果Publisher
不再存在,那么所有依赖的Artcle实体。我允许自己直接访问每个
Publisher
和各个实体的Article
集合。在Article
类的 DB/Mapping 中,Publisher
是成员之一,不能接受Null
。愿意详细说明你的和我的之间的区别吗?
抱歉,这不是直接答案,但太长,无法添加为评论。
I am using NH for another business context but similar entity relationships like yours. I do not understand why do you say:
I have this in mine,
Article
andPublisher
entities, ifPublisher
cease to exist, so do all the dependentArtcle
entities. I allow myself to have direct access to theArticle
collections of eachPublisher
and individual entities. In the DB/Mapping of theArticle
class,Publisher
is one of the members and cannot acceptNull
.Care to elaborate the difference between yours and mine?
Sorry this is not a direct answer but too long to be added as a comment.
我同意莫什的观点。这两个实体都有自己的聚合根。让我用现实生活来解释一下。假设一家公司开发了一款软件。该软件存在一些错误,让您烦恼。你要去公司并让他们了解这个问题。该公司给您一张表格,由您填写。
该表格有一个字段 - 部分 - 指示软件名称和描述。此外,它还有一些供您投诉的部分。这个表格和软件说明书一样吗?不是,是与软件相关的表格。这不是软件。这个表格有ID吗?是的。确实如此。也就是说,您可以在第二天致电该公司,向接线员询问您的投诉信。很明显,接线员会询问你的Id。
这一证据表明,这种形式有其自身的实体,不能与软件本身相混淆。两个不同实体之间的任何关系并不意味着其中一个实体属于另一个实体。
I agree with Mosh. Each ones of these two entities has its own aggregate root. Let me to explain it in the real life. suppose that a company has developed a software. There are some bug in this software, that made you annoy. you are going to go to the company and aware them from this problem. this company gives you a form to be filled by you.
This form has a field - section - indicates to the software name and description. additionally, it has some parts for your complaint. Is this form the same as the software manual? No. It is a form related to the software. It is not the software. Does this form has any ID? yes. It has. In other words, you can call the company in the next day and ask the operator about your letter of complaint. It is obvious that the operator will ask you about the Id.
This evidence shows that this form has its own entity and it could not be confused with the software itself. Any relation between two different entity does not mean one of them belongs to the other.