在我找到article:
之前,我不知道特定于角色的存储库而不是一个包含暴露每个方法的catch-all存储库 太阳,我们可以选择应用接口隔离原则 用于基于角色的接口,并定义仅公开内容的接口 一类需要。
public interface IProductRepositoryForNewOrder { Product[] FindDiscontinuedProducts(); }
单个存储库实现实现所有产品存储库 接口,但只有所需的单个方法被公开和使用 来电者。
a)两者之间的区别在于特定存储库我们每个聚合根有一个特定的合同,而特定于角色的存储库我们可以有几个合同Aggregate Root,这些合同中的每一个都根据在Aggregate Root上运行的特定调用者的需求而定制?
b)在您看来,这两种模式各有哪些优缺点?
谢谢
更新
昨天我发现你的一个answers本质上你认为应该使用特定于角色的存储库模式:
“另一种选择是使用lambda而不是OrdersSelectorService。 如果你的语言没有lambdas那么它应该是一个 接口。传递OrderRepository的好处是基于 界面隔离原则的目标是减少 不必要的耦合。客户需要的行为不太可能 OrderRepository上的所有方法,而不是需要特定的方法 功能,所以要明确。“
为什么在上面摘录中您提倡使用特定于角色的存储库模式,但在此您似乎建议仅在特殊情况下使用它。另一个主题中的示例是一个特殊情况(除此之外 - 我绝不会说你自相矛盾,我只是看不出两个例子在使用或不使用角色特定模式方面有何不同) ?
答案 0 :(得分:2)
a)是的。这是界面隔离原则;使角色/用例明确。好处是减少和“清理”依赖性。
b)对我来说,角色特定方法的主要方面是接口的扩散以及由此导致的布线,参考等的增加。然而,这可以被视为不是由于原理的缺陷,而是更多 - 在编程语言中。在功能语言中,例如F#,由于函数而不是接口的扩散,接口隔离是默认方法。从某种意义上说,功能是一种“更清晰”的工具。非特定于角色的方法的专家是它可以被视为定义数据访问合同的单个语言元素,接口或类。在某些情况下,从技术角度评估架构是很有价值的。
答案 1 :(得分:2)
我全都是SOLID代码,但接口隔离原则确实有其局限性,尤其是在DDD环境中。
[nitpicker mode]
如果您在信件中使用ISP,您几乎可以从文章中获取有关存储库的声明并稍微更改一下来说明
使用域实体的类很少使用其中的每个方法。
因此,对于每个域实体,您应该创建与实体客户端一样多的接口,并且每个接口中只有与客户端相关的方法,并使实体实现这些接口。
当然,这是荒谬的,没有人会这样做。但是,嘿,ISP应该是一个普遍的OO概念,不是吗?
[/ nitpicker mode]
现在,如果我们回顾一下ISP的原始原因,它应该与胖接口作斗争,即那些没有凝聚力的接口。但是它本身不是一个有凝聚力的存储库吗?它不是一个基本的原子DDD构建块吗?它应该被分成几十个迷你查询对象吗?此外,我们领域的每个课程都不应该与普适语言保持一致吗? ProductRepoInterfaceForClient1
,ProductRepoInterfaceForClient2
,ProductRepoInterfaceForClient3
等接口的情况几乎不存在......
不要误解我的意思,ISP仍然有用,特别是作为一种方法来检测接口的合同何时比它应该更加异构。 ISP上的Bob叔叔original paper有很好的例子 - 请参阅“接口污染”段落和ATM示例。
但是,一旦达到了合理的凝聚力,ISP就不应该盲目地应用IMO,特别是如果它与基本的DDD原则相冲突,或者使你的代码库充斥着成为维护噩梦的数百个接口。