设计模式——特定角色存储库vs特定存储库



我不知道角色特定存储库,直到我发现了这篇文章:

而不是一个公开所有方法的全部存储库但是,我们可以选择应用接口隔离原则对于基于角色的接口,并定义只公开内容的接口一个班级需要。

public interface IProductRepositoryForNewOrder
{
    Product[] FindDiscontinuedProducts();
}

单个存储库实现实现所有产品存储库接口,但只公开所需的单个方法并由调用者。

a)两者之间的区别在于特定存储库我们每个聚合根有一个特定的契约,而角色特定存储库我们每个聚合根可以有几个契约,每个契约都适合在聚合根上操作的特定调用者的需求?

b)在你看来,这两种模式的优缺点是什么?

谢谢

更新:

昨天我发现了你的一个答案,本质上你认为应该使用特定于角色的存储库模式:

"另一个选择是使用lambda而不是OrdersSelectorService。如果lambda在你的语言中不可用,那么它应该是接口。传递OrderRepository的好处是基于界面隔离原则的目标是减少不必要的耦合。这是不可能的行为,以客户的需求所有的方法都在OrderRepository上,相反,它需要一个特定的函数,明确一点。"

为什么在上面的摘录中你提倡使用特定于角色的存储库模式,但在这里你似乎只建议在特殊情况下使用它。另一个主题中的例子是一个特殊的情况吗(顺便说一下,我不是说你在自相矛盾,我只是看不出这两个例子在使用或不使用角色特定模式方面有什么不同)?

a)是的。这就是界面隔离原理在起作用;明确角色/用例。这样做的好处是减少和"清理"依赖关系。

b)对我来说,角色特定方法的主要缺点是接口的激增以及由此导致的连线、引用等的增加。然而,这并非由于原理上的缺陷,而是由于编程语言的缺陷。在函数式语言中,例如f#,接口隔离是默认的方法,因为函数而不是接口的扩散。从某种意义上说,函数是一种"更锐利"的工具。

非角色特定方法的优点是,它可以被视为定义数据访问契约的单个语言元素、接口或类。在某些情况下,从技术角度评估体系结构是有价值的。

我完全支持SOLID代码,但是接口隔离原则确实有其局限性,特别是在DDD上下文中。

[nitpicker mode]

如果你把ISP应用到这个字母上,你可以把文章中关于存储库的陈述稍微改变一下,说

使用域实体的类很少使用其中的每个方法。

因此,对于每个域实体,您应该创建与该实体的客户端数量相同的接口,并且在每个接口中只使用与该客户端相关的方法,并使实体实现这些接口。

当然,这是荒谬的,没有人会那样做。但是,ISP应该是一个通用的OO概念,不是吗?

[/nitpicker mode]

现在,如果我们回顾一下ISP的最初原因,它应该对抗胖接口,即那些不内聚的接口。但是存储库本身不是内聚的吗?难道它不是一个基本的、原子的DDD构建块吗?它应该被分割成几十个迷你查询对象吗?此外,我们领域中的每个类不都应该与泛在语言保持一致吗?对于ProductRepoInterfaceForClient1, ProductRepoInterfaceForClient2, ProductRepoInterfaceForClient3等接口,情况几乎不是这样。

不要误解我的意思,ISP仍然是有用的,特别是作为一种检测接口的契约是否比它应该的更异构的方式。Bob大叔关于ISP的原始论文中有很好的例子——参见"接口污染"段落和ATM的例子。

但是,一旦达到了合理的内聚水平,ISP就不应该盲目地应用IMO,特别是如果它与基本的DDD原则相冲突,或者用数百个接口淹没你的代码库,成为维护的噩梦。

最新更新