gpt4 book ai didi

domain-driven-design - 在域层中公开 IUnitOfWork 接口(interface)是否违反持久性无知规则?

转载 作者:行者123 更新时间:2023-12-04 08:23:19 24 4
gpt4 key购买 nike

1) 在大多数情况下,每个Aggregate Root 都应该定义自己的事务边界,在这种情况下我们不需要公开IUnitOfWork 领域层中的接口(interface)。

a) 我假设在这种情况下,一个不错的选择是repository(aggregate 使用它来强制在其中应用invariants)包含它自己的 UoW 实例(如果使用 EF,那么这个 UoW 实例可以只是 DbContext 类型)?

2)

a) 但是如果出于某种原因 transaction 跨越多个 aggregates (因此一次需要更改多个 aggregate ),那么Domain Layer是不是也需要包含IUnitOfWork接口(interface)呢?

b) 在 Domain Layer 中暴露 IUnitOfWork 接口(interface)不会违反 persistence ignorance rule 吗?

c) 如果 b) 是,那么公开 IUnitOfWork 是否会破坏拥有 repositories 的目的?

回复 Alexey Raga:

1)我建议不要将存储库暴露给聚合。存储库可以为您提供聚合,仅此而已。

a) 虽然我假设大多数 DDD 架构师对将 repo 公开给聚合没有问题(我问这个问题只是因为我阅读了几篇关于 repo 和 DDD 的文章,我的印象是作者不是反对将 repo 公开给聚合 - 但现在我不再那么确定了)?

b) 所以你也反对将存储库暴露给域服务?

c) 从您的回答来看,我猜您考虑将 IUnitOfWork 暴露为违反 PI 的行为?

2)请注意,尽管我的命令处理程序(在某种程度上是应用程序服务)...

您通常将命令处理程序实现为应用服务吗?

3)

public void Handle(ApproveOrderCommand command)
{
var order = Repository.Get(command.OrderId);
property.Approve(command.Comment, ServiceRequiredForOrderApproval);
Repository.Save(order);
}

property.Approve(...) 是打字错误吗?您实际上是指 order.Approve(...)

提前致谢

最佳答案

我建议不要将存储库暴露给聚合。存储库可以为您提供聚合,仅此而已。

这样看:您的域是一个“泡泡”,它只了解自己的内容。意思是,它只了解自己的值对象、它声明的领域服务接口(interface)等。我不会在此集合中包含存储库。

当您的域(聚合)需要某些东西时,它应该显式地公开它所需要的东西的依赖性,而不仅仅是请求一些存储库。

服务是将事物结合在一起的原因。例如,我的命令处理程序可能如下所示:

public class ApproveOrderCommandHandler  : IHandle<ApproveOrderCommand> 
{
//this might be set by a DI container, or passed to a constructor
public IOrderRepository Repository { get; set; }
public ISomeFancyDomainService ServiceRequiredForOrderApproval { get; set; }

public void Handle(ApproveOrderCommand command)
{
var order = Repository.Get(command.OrderId);
order.Approve(command.Comment, ServiceRequiredForOrderApproval);
Repository.Save(order);
}
}

请注意,虽然我的命令处理程序(在某种程度上是应用程序服务)处理存储库,但我的域(订单聚合)是持久性无知的。它对 UnitOfWorks 的存储库一无所知。

当我确实需要启动一个 UnitOfWork 时,我可以使用责任链模式组合它:

public class WithUnitOfWorkHandler<T> : IHandler<T>  {
private readonly IHandler<T> _innerHandler;

public WithUnitOfWorkHandler(IHandler<T> innerHandler) {
_innerHandler = innerHandler;
}

public void Handle(T command) {
using(var ouw = new UnitOfWork()) {
_innerHandler.Handle(command);
uow.Commit();
}
}
}

现在我可以通过使用 WithUnitOfWorkHandler“装饰”它来“链接”任何我的命令处理程序。并且一些处理程序甚至可能涉及多个存储库或聚合。不过,聚合对持久性、工作单元、事务等一无所知。

关于domain-driven-design - 在域层中公开 IUnitOfWork 接口(interface)是否违反持久性无知规则?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20616829/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com