领域驱动设计 - 关于将对非根实体的引用传递给外部对象,几乎没有令人困惑的事情



根实体可以将对内部实体的瞬态引用传递给外部对象,但在操作完成后外部对象不保留该引用的情况下

1)

a) 为什么外部对象在单个操作的持续时间内具有引用(内部实体)是可以接受的,但在两个操作的持续时间内保留该引用是不可接受的? 我的观点是,如果在两个操作的持续时间内保留引用是不好的,那么在单个操作的持续时间内保留它可能同样糟糕?!

b) 假设聚合SomeRootEnt内部实体SomeIntEnt的瞬态引用传递给外部对象,外部对象应该如何请求SomeIntEnt?通过在上调用特定方法 – 例如 SomeRootEnt.BorrowMeIntEnt(...) - 或者应该直接内部实体公开为其属性(例如 SomeRootEnt.SomeIntEnt )?

2)

a) 假设SomeRootEnt根传递对内部实体SomeIntEnt外部对象的引用,进而对SomeIntEnt进行一些修改,那么这是否意味着根无法在这些修改上应用适当的不变逻辑(即无法检查修改SomeIntEnt的完整性

b) 同样,至少据我了解,root 也没有办法在完成单个操作后强制外部对象删除对内部实体的引用?

谢谢

更新:

2一)

这是正确的,这就是为什么最好确保通过 对象不会被修改,但以不可变的方式使用。此外, 传递的实体仍然可以自行保持一定程度的完整性。

主要是聚合根(部分由传递的实体)或外部对象(接收瞬态引用)负责确保传递的实体不被修改吗?如果是后者,那么这个聚合体的一致性真的不是受开发外部对象的人的摆布吗?

2b)

正确,您有责任确保这一点。就像你一样 必须确保给定值对象是不可变的(如果需要),您 必须考虑传递引用的完整性。

我认为在大多数情况下,外部对象有责任在操作完成后立即删除引用?

1a) 可能需要对实体的引用来支持域操作,但是该引用应该是暂时的,因为它不会在操作后保留。它仅在操作期间保持,而不是在操作之后,因此它不会通过感应得出它可以保持两个操作。这样做的目的是确保将引用传递给外部实体的聚合可以保持对其组成部分的控制。您不希望其内部实体被其他聚合接管,因为那样就更难推理行为。

1b) 它可以采用任何一种方式,具体取决于用例。属性只是伪装的方法。

2a)这是正确的,这就是为什么最好确保传递的对象不会被修改,而是以不可变的方式使用。此外,通过的实体仍然可以自行保持一定程度的完整性。

2b) 正确,您有责任确保这一点。就像你必须确保 give value 对象是不可变的(如果需要)一样,你必须考虑传递的引用的完整性。

其中大部分是一般准则,因为它会产生"行为良好"、易于推理且易于制作一致的聚合。

更新

2a)鉴于编程语言的局限性,聚合对自身的保护程度是有限的。因此,需要"人为干预",尤其是在像这样更复杂的场景中。的确,总体可能会受到另一个人的摆布,这就是制定这些准则的原因。

2b) 是的。外部对象可以使用另一个聚合的内部实体,但它的引用应该是暂时的 - 这意味着它不会被持久化。

如果具有私有实体的对象获取了锁,将对实体的引用传递给外部方法,该方法永远不允许将其复制到该方法离开范围后仍然存在的任何位置,然后释放锁,则可以确保在释放锁时,没有外部实体将持有引用。 即使锁中某处的代码引发异常,该不变性也将保持不变。 如果允许外部方法将对实体的引用存储在可能比它存活的时间更长的任何位置,即使它承诺某些其他操作将销毁该引用,则确保销毁外部引用所需的操作在释放锁之前实际发生将变得更加困难。

最新更新