【问题标题】:Queries in repository pattern which are not related to the collection interface与集合接口无关的存储库模式中的查询
【发布时间】:2019-02-27 18:36:03
【问题描述】:
Repository 代表集合接口。您可以使用存储库存储、删除和查找对象。
但我经常看到存储库的接口包含封装了与集合接口无关的复杂查询的方法。
例如:返回一些 dto 的复杂统计计算方法。或者一些使用mysql返回布尔值的检查,比如“userHasSomething”
似乎存储库不是这些方法的最佳位置。
Repository 应该严格表示集合的接口还是应该完成与存储相关的所有工作?
在哪里放置这些查询?
【问题讨论】:
标签:
architecture
repository-pattern
ddd-repositories
【解决方案1】:
坦率地说,所有这些存储库的东西都是基于意见的。
Martin Fowler 是这样定义的:
具有复杂域模型的系统通常受益于一层,例如 Data Mapper (165) 提供的层,它将域对象与数据库访问代码的细节隔离开来。在这样的系统中,在查询构造代码集中的映射层之上构建另一个抽象层是值得的。当有大量域类或繁重的查询时,这变得更加重要。特别是在这些情况下,添加这一层有助于最大限度地减少重复查询逻辑。
存储库在域和数据映射层之间进行调解,就像内存中的域对象集合一样。客户端对象以声明方式构造查询规范,并将它们提交给 Repository 以获得满意。对象可以添加到存储库中,也可以从存储库中删除,就像它们可以从简单的对象集合中一样,存储库封装的映射代码将在幕后执行适当的操作。从概念上讲,存储库封装了持久化在数据存储中的一组对象以及对它们执行的操作,从而提供了一个更加面向对象的持久层视图。 Repository 还支持在域和数据映射层之间实现清晰分离和单向依赖的目标。
正如您在问题中指出的那样:
但我经常看到存储库的接口包含封装了与集合接口无关的复杂查询的方法。
在我的意见中,在 DDD 上下文中,存储库应该按照您在问题中解释的方式(集合界面)工作。休息是业务逻辑,应该转移到领域模型或服务。
理论仍然是理论;纯粹主义者严格遵守它。最重要的是业务需求。
模式很好,必须遵循这些模式。这些是由专家根据他们多年的经验构建的。如果遇到同样的问题,应该毫不犹豫地使用它。
存储库等模式比 GoF 模式更广泛。这使得存储库位基于意见。此外,存储库也广泛用于 DDD 上下文之外。这进一步增加了意见。
似乎存储库不是这些方法的最佳位置。
如果您这么认为,并且在您的设计中为这些方法提供了更好的位置,请继续将这些方法移至该位置。如果您的设计告诉您存储库是这些方法的最佳位置,请不要犹豫使用它。
在哪里放置这些查询?
由你决定。专注于手头的问题,专注于您的设计,专注于您的业务需求。不要在代码中添加不必要的复杂性只是为了正确地遵循模式。如果通过修复承诺的问题而产生新问题,那么该模式有什么用处?