地精是正确的,很少有情景我可以想像这将要求你可能想摆脱它的AddressRepository。
这就是说,您要查找的设计概念是“Aggregate Root”。这很快就意味着要识别对象图中没有其他对象不存在的对象。这些是需要存储库的类,它们最终将成为对象图的网关。
当我第一次了解它时,这让我感到困惑 - 我不认为识别这些对象会这么简单。出路是“Bounded Context”的附加概念。这可能是最不适用的设计原则。
总之,考虑你正在解决以下两个用户故事。
- 正如我希望能够在网站上存储所有之前的送货地址,以便我可以下订单
- 作为物流管理员时访问它们更易于用户想打印出所有地址的,我们需要运送到明天,这样我可以计划航线相应
所以,你已经得到的东西像下面的模型:
这似乎很难解剖。如果Person是根,那么当用户只是简单地改变他们的信息时,我们必须用Orders关联加载Person对象。如果他们下了很多订单(比如他们为公司管理库存),这可能会成为一个巨大的性能问题。
选择订单作为聚合根也不能解决问题。如果订单没有对某人的引用,那么我们将如何检查所选地址是否有效?
另一方面:旧学校对这些问题的回答分别是“懒加载”和“双向关联”。然而,这些技术都伴随着他们自己的复杂问题,我相信他们通常比他们的价值更麻烦。
解决这个看似冲突的原因(为什么我觉得我在沟通Eliyahu Goldratt?)就是承认这两个故事存在于不同的意义上下文中。当用户存储地址时,他们不关心订单,同样,当管理员正在检查地址时,他们并不关心它的用途。定义有冲突。当两种情境都说“地址”时,他们指的是相同的物理对象,但只是作为两个完全不同概念的试金石!就个人而言,地址只是他们存储的一个测试块。就物流经理而言,地址唯一的要求应该是与真实地点相关联。
那么为什么即使他们是同一个对象呢?
你看到发生了什么?您已经将问题分解为两个离散的和不相关的系统,正如我们现在所知道的那样,小型,离散和集中的系统是可维护软件的关键。
那么当这些上下文需要沟通时会发生什么?由于两个上下文中的地址对象可能在不同的时间使用(并且其中一个是只读的),因此可以使用相同的数据库。但是,这并不推荐(尽管很多人反正这样做)。相反,两个域上下文之间的通信应该通过显式消息传递和映射机制(例如事件聚合器/消息传递总线)(如果有人知道两者之间的区别)来在代码中处理。
感谢这样一个彻底的答案:)。 – gmn 2010-08-28 21:22:08