- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
假设我有一个实现以下业务规则/策略的域服务:
If the total price of all products in category 'family' exceeds 1 million, reduce the price by 50% of the family products which are older than one year.
使用基于集合的存储库
我可以简单地创建一个域服务,使用规范模式加载“家庭”类别中的所有产品,然后检查条件,如果为真,则降低价格。由于产品由基于集合的存储库自动跟踪,因此域服务根本不需要发出任何显式基础设施调用——本应如此。
使用基于持久性的存储库
我运气不好。我可能会使用存储库和规范将产品加载到我的域服务中(和以前一样),但最终,我需要发出不属于域层的 Save
调用。
我可以在应用层加载产品,然后将它们传递给域服务,最后在应用层再次保存它们,如下所示:
// Somewhere in the application layer:
public void ApplyProductPriceReductionPolicy()
{
// make sure everything is in one transaction
using (var uow = this.unitOfWorkProvider.Provide())
{
// fetching
var spec = new FamilyProductsSpecification();
var familyProducts = this.productRepository.findBySpecification(spec);
// business logic (domain service call)
this.familyPriceReductionPolicy.Apply(familyProducts);
// persisting
foreach (var familyProduct in familyProducts)
{
this.productRepository.Save(familyProduct);
}
uow.Complete();
}
}
但是,我发现此代码存在以下问题:
FamilyProductsSpecification
) 和策略之间的内聚性丢失,基本上允许某人将错误的产品传递到域服务中。请注意,在域服务中再次过滤产品(内存中)也无济于事,因为调用者可能只传递了所有产品的一个子集。问题:有没有更好的策略来应对这种情况?
我考虑过一些复杂的事情,比如调整基于持久性的存储库,使其在域服务中显示为基于集合的存储库,在内部跟踪由域服务加载的产品,以便在需要时再次保存它们域服务返回。
最佳答案
首先,我认为为这种不属于特定聚合的逻辑选择域服务是个好主意。
而且我也同意你的观点,域服务不应该关心保存更改的聚合,将这样的东西保留在域服务之外也允许你关心管理事务 - 如果需要的话 - 应用程序。
我会务实地解决这个问题,并对您的实现做一些小改动以保持简单:
// Somewhere in the application layer:
public void ApplyProductFamilyDiscount()
{
// make sure everything is in one transaction
using (var uow = this.unitOfWorkProvider.Provide())
{
var familyProducts = this.productService.ApplyFamilyDiscount();
// persisting
foreach (var familyProduct in familyProducts)
{
this.productRepository.Save(familyProduct);
}
uow.Complete();
}
}
产品领域服务中的实现:
// some method of the product domain service
public IEnumerable<Product> ApplyFamilyDiscount()
{
var spec = new FamilyProductsSpecification();
var familyProducts = this.productRepository.findBySpecification(spec);
this.familyPriceReductionPolicy.Apply(familyProducts);
return familyProducts;
}
这样一来,遍历一年以上的所有系列产品然后应用当前折扣 (50%) 的整个业务逻辑就被封装在域服务中。然后应用层再次只负责编排以正确的顺序调用正确的逻辑。命名以及您希望通过提供参数使域服务方法变得多么通用当然可能需要调整,但如果无论如何只有一个特定的业务需求,我通常会尝试使任何东西都不通用。因此,如果那是当前的家庭产品折扣,我就会知道我到底需要在哪里更改实现 - 仅在域服务方法中。
老实说,如果应用程序方法没有变得更复杂并且您没有不同的分支(例如 if 条件),我通常会像您最初建议的那样开始,因为应用程序层方法也只是调用域服务(在您的情况下是存储库)具有相应的参数并且其中没有条件逻辑。如果它变得更复杂,我会将其重构为域服务方法,例如我提议的方式。
注意:由于我不知道 FamilyPriceRedcutionPolicy 的实现,我只能假设它会调用产品聚合上的相应方法,让它们应用价格折扣。例如。通过在 Product 聚合上使用诸如 ApplyFamilyDiscount() 之类的方法。考虑到这一点,考虑到循环遍历所有产品并调用折扣方法将只是聚合之外的逻辑,具有从存储库获取所有产品的步骤,调用 ApplyFamilyDiscount() 方法所有产品和保存所有更改的产品确实可以只驻留在应用层。
在考虑域模型纯度与域模型完整性(参见下面关于 DDD trilemma 的讨论)方面,这将再次朝着纯度的方向移动实现,但也使如果循环遍历产品并调用 ApplyFamilyDiscount() 就是它所做的一切,域服务就会有问题(考虑到通过存储库获取相应产品是预先在应用层完成的,并且产品列表已经传递给域服务)。同样,没有教条主义的方法,了解不同的选择及其权衡是相当重要的。例如,还可以考虑通过在询问价格时应用所有适用的可能折扣,让产品始终按需计算当前价格。但同样,这种解决方案是否可行取决于具体要求。
关于domain-driven-design - DDD : The problem with domain services that need to fetch data as part of their business rules,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67254749/
我是 DDD 的初学者。 我不知道谁负责 API 请求的流程。 我不知道谁负责间接依赖于基础设施层的功能。 如带有 Web API 请求的函数。 例如我正在创建在线购物系统,系统支持取消订单。 我想我
我有一个dispatcher-servlet.xml和一个applicationContext.xml。 我一直在做一些重构,并感动 从dispatcher-servlet.xml到applica
哪些工具可用于元建模? 特别是开发图表编辑器,目前正在试用Eclipse GMF 想知道还有哪些其他选择? 有什么可比性吗? 最佳答案 由于许多方面,您的问题对于单一答案来说太宽泛了。 首先,元建模不
我前段时间学习了决策树和决策表。我觉得决策表可以帮助处理条件 If-Then-Else 语句。特别是,我觉得决策表没有副作用,例如,如果您没有注意到您还需要一个“else if”语句。 但我不确定如何
我们的团队开始实现事件驱动设计。我们现在正在确定记录这些事件的模式的最佳工具和实践是什么。 用于此用例的常用工具有哪些? 任何链接或建议表示赞赏。 最佳答案 我将从常见的 CloudEvents sp
我听说过最小化代码和最大化数据的概念,并且想知道其他人在构建自己的系统时如何/为什么应该这样做的建议? 最佳答案 通常,数据驱动的代码更易于阅读和维护。我知道我已经看到数据驱动被极端化并且最终变得非常
我的工作任务是为物流应用程序编写详细的工程计划,我们正在编码该计划以向客户提出建议。有人告诉我这是一个数据驱动的应用程序。对于应用程序来说,“数据驱动”意味着什么?相反的是什么?尽管在网络搜索时我可以
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗?更新问题,使其仅关注一个问题 editing this post . 关闭 4 年前。 Improve this que
我是 DDD 的新手。现在我在看领域事件。我不确定我是否正确理解了这个领域事件,但我只是在想如果领域事件发布失败会发生什么? 我这里有一个案例。当买家从我的网站订购商品时,首先我们将创建一个对象,Or
当我在我的软件项目中实践 DDD 时,我一直面临这样的问题:“为什么我应该在实体中实现我的业务规则?它们不应该是纯数据模型吗?” 请注意,根据我对 DDD 的理解,域模型可以由持久模型和值对象组成。
我有一个名为 Campaigns 的聚合,每个聚合都有一个名为 campaign 的根实体,这个根实体有一个尝试列表(实体) public class Attempts: IEntity
我正在尝试使用分层架构实现 DDD 应用程序。我有: 基础架构层 - 实现应用程序特定技术部分的层。 领域层——包含领域模型的层。 应用层 - 包含与域模型交互的干扰的层。 和接口(interface
最近学习ddd,里面说两个相关的bounded context之间的关系是upstream和downstream。 但是有没有可能在一种情况下A是上游B是下游,而在另一种情况下B是上游又是下游? 但是
我有一个名为 Order 的实体,以及一个聚合根 OrderManager,它根据来自应用层的请求更新订单状态和一些其他信息(AppLayer 调用 OrderManager,OrderManager
让我们假设场景: 我们有系统的用户 每个 User 都有他们的 Clients(Client 总是分配给一个且只有一个 User)< Users 上传不同的 Documents 并且 Document
这是一个 ASP.NET MVC 网站。 在领域驱动设计之后,我们有一个服务层。我们的 Controller 要求应用程序服务类执行各种任务,然后将结果路由到 View 。 业务逻辑由服务类执行。 例
不,这不是重复问题。我有很多关于这个主题的资源,但我仍然觉得我没有完全理解它。 这是我目前掌握的关于什么是聚合和聚合根的信息(来自多个来源,无论是文章、视频等...): 聚合是多个值对象\实体引用和规
我正在重建一个会计软件。该软件可以处理多种类型的交易,例如销售、库存补货和费用。我没有会计背景,但我在网上学到了一些概念。我正在尝试根据这些原则对域进行建模: 一个日记账分录由几条记录组成,每条记录要
我正在从头开始学习 DDD 主题,在许多 DDD 示例中,我看到“存储库接口(interface)”位于域中。这个存储库的真正目的是什么/它到底做了什么或解决了什么问题?这与持久层实现是否对应或有某种
假设我们有以下内容: DDD聚合了A和B,A可以引用B。 管理 A 的微服务公开以下命令: 创建一个 删除 A 链接 A 到 B 取消 A 与 B 的链接 管理 B 的微服务公开以下命令: 创建 B
我是一名优秀的程序员,十分优秀!