我何时以及为何要使用域名服务?

时间:2016-11-11 12:40:40

标签: domain-driven-design

我有一个聚合根的租赁实体。除此之外,它还维护了一个分配列表(保留的时间块)。

如何添加新分配?由于Rental是聚合根,因此任何新的分配都应该通过它,但在我们尝试将分配保存在数据库中之前,无法确定是否可以分配租金。另一个用户可以在此期间保留它。我猜,我应该使用域名服务吗?

我不想每次需要新租用时都要注入任何但注入域名服务而不是存储库之间的区别是什么?除了术语不同之外?

2 个答案:

答案 0 :(得分:2)

  

何时以及为何要使用域名服务?

您使用域服务允许聚合运行查询。税收计算是一种不时显示形式的示例。聚合将一些状态传递给计算器,计算器报告税收,聚合决定如何处理该信息(忽略它,拒绝需要它的更新等)。

运行查询不会以任何方式修改域服务实例,因此您可以根据需要随时重复查询,而不必担心计算会相互污染。

认为只读服务提供商。

  

由于Rental是聚合根,因此任何新的分配都应该通过它,但在我们尝试将分配保存在数据库中之前,无法确定是否可以分配租金。另一个用户可以在此期间保留它。我猜,我应该使用域名服务吗?

不 - 完全是错误的用例。

如果分配是Rental聚合的一部分,那么租赁聚合可以创建自己的分配。您不需要为此服务(如果您希望分离关注点,您可以将工作委托给工厂)。

如果"另一个用户可以同时保留该分配",那么您就有争用 - 两个用户试图同时更改同一个聚合。这通常以两种方式之一进行管理。

锁定:您只允许一个用户一次修改Rental聚合。所以在数据竞争中,失败者必须等待胜利者完成,然后聚合可以拒绝失败者的命令,因为已经采取了特定的分配。

乐观并发:允许两个用户同时修改聚合的不同副本,但只有在原始状态未更改时才允许保存。思考"比较和交换&#34 ;;比赛是在这两个指令之间的保存

state.compareAndSwap(originalState, loserState)
state.compareAndSwap(originalState, winnerState)

获胜者的比较和交换成功,但失败者失败(因为originalState!= winnerState),因此输家修改被拒绝。

无论哪种方式,只允许一次写入数据库保留分配。

  

如果我理解正确,那么您是说在这种情况下可以在租赁域实体内部使用存储库吗?

不,你不应该 - 作为Rental聚合的一部分,分配由内存中的聚合创建,并在保存聚合时首先出现在数据存储中。

  

为什么要使用聚合,如果必须将所有后果提取到周围的代码或工厂中呢?

这里的一些答案是关注点的分离 - 聚合的主要关注点是强制执行业务不变性:确保创建具有某些特定状态的分配与其他所有内容一致。工厂负责确保所创建的对象正确连接。

使用你的例子:工厂将负责在内存中创建分配,但不需要知道任何关于确保分配是唯一的。聚合描述并强制执行确保分配唯一的规则。

答案 1 :(得分:0)

使用静态工厂方法创建Rental对象。

public static class RentalFactory
{
    public Rental CreateRental()
    {
        var allocationSvc = new RentalAllocationService();
        return new Rental(allocationSvc);
    }
}

存储库应该只关注对底层存储的持久性。 域服务主要关注的是执行涉及实体或值对象的某些行为。