【发布时间】:2018-02-02 22:55:51
【问题描述】:
我在尝试重新设计现有业务对象以采用更受领域驱动的设计方法时遇到了问题。
目前,我有一个产品退货聚合根,它处理与特定产品退货相关的数据。作为此汇总的一部分,需要提供一个日期来说明当前的回报月份(和年份)。
每个产品退货必须是连续的,因此每个产品退货必须在上一个月之后的下个月。尝试创建不遵循此模式的产品退货应该会导致异常。
我曾考虑将域服务传递给设置返回的 PeriodDate 的方法(或构造函数),但我不知道该怎么做。即使域服务引用了存储库,我也看不出在该存储库上放置“GetNextReturnDate()”是合适的。
对于背景,每个产品退货都与一个产品相关联。我不愿意让产品成为聚合根,因为加载所有产品返回只是为了添加一个似乎是一种极不高效的做事方式(考虑到这个库将与 RESTful Web API 一起使用)。
谁能提供关于我应该如何建模的建议?只是改变聚合根和处理性能的问题吗?域中是否有可以放置“查询”类型服务的地方?
例如,当前的构造函数 for product return 如下所示:
public ProductReturn(int productID, int estimateTypeID, IProductService productService)
{
// This doesn't feel right, and I'm not sure how to implement it...
_periodDate = productService.GetNextReturnDate(productID);
// Other initialization code here...
}
IProductService(及其实现)位于域层,因此无法直接从那里调用 SQL(而且我觉得这不是我应该在这里做的)
同样,我很可能已经对这个进行了非常糟糕的建模,或者我在设计聚合时遗漏了一些东西,因此我们将不胜感激!
我认为我在这里更广泛的问题是理解如何在域实体内部实现约束(无论是外来的、唯一的等),而不是通过域服务获取整个返回列表,当一个简单的 SQL查询会给我所需的信息
编辑:我确实看到了另一个问题的答案:https://stackoverflow.com/a/48202644/9303178,这表明在域中有“域查询”接口,听起来他们可以返回我想要的那种数据寻找。
但是,我仍然担心我的设计遗漏了一些东西,所以我再次对建议持开放态度。
编辑 2:为了回应 VoiceOfUnreason 下面的回答,我想我会澄清一些关于 PeriodDate 属性的事情。
关于它的规则如下:
- 不能为空
- 它必须与其他产品退货顺序一致,如果不满足则不能处于有效状态
这是一个棘手的问题。我不能依赖传入的日期,因为它很可能是乱序的,但是如果没有注入服务,我无法确定日期。我要将构造函数转换为工厂上的方法以删除“构造函数工作”反模式。
我可能对当前代码的方式过于防御,但感觉必须注入 ReturnService 的次数是错误的。请注意,有很多情况下必须重新计算返回值,但感觉好像在保存之前只是这样做很容易(但我想不出一个干净的方法这样做)。
总的来说,我只是觉得这个类有点味道(注入服务和诸如此类的东西),但我可能不必要地担心。
【问题讨论】:
-
您能否详细解释一下“每个产品退货必须是连续的”。我对 ProductReturn 的理解是:很多人从您的网站购买产品,如果有人想要退货,您正在创建一个 Product Return Agg。 ,在那种情况下,“每个产品退货必须是连续的”有什么意义。请澄清
-
我认为你应该在软件工程论坛上问这个问题,你会在那里得到很好的回应,因为它看起来是一个设计问题。链接 - softwareengineering.stackexchange.com
-
@SahilAggarwal 在引用其他网站时,指出cross-posting is frowned upon 通常会有所帮助
-
@techagrammer 指的是金融——产品本质上是一种投资。作为一项投资,它每月都有回报。