DDD:存储库合约

Ben*_*min 5 orm domain-driven-design design-by-contract repository ddd-repositories

我在很多地方读到,DDD 中的一项重要要求是为存储库制定有限制的合同:

findByName(string name)
findByEmail(string email)
etc.
Run Code Online (Sandbox Code Playgroud)

并且不提供通用的查询接口:

findBySpecification(Specification spec)
Run Code Online (Sandbox Code Playgroud)

我确实理解为什么这很重要:能够模拟存储库进行测试,或更改底层的持久性框架。

虽然在整个应用程序中执行此规则并不难,但在为用户提供“高级搜索”表单时,我不知道如何执行它。

假设我有一个表单,允许按关键字、按日期、按作者等搜索博客文章。

这些标准可以自由组合,我显然无法为每个用例提供一种方法:

findByKeyword(string keyword)
findByDateRange(Date from, Date to)
findByKeywordAndDateRange(string keyword, Date from, Date to)
findByDateRangeAndAuthor(Date from, Date to, User author)
etc.
Run Code Online (Sandbox Code Playgroud)

我是否遗漏了什么或者它是规则的例外之一?

Dmi*_*try 2

将规范作为参数传递给存储库没有任何问题。这实际上是解决存储库接口上方法爆炸的一个非常好的方法。看看这个答案。对于“高级搜索”场景,“过滤器”可能比“规范”更合适。我认为这段代码不会违反任何 DDD 准则:

Filter filter = new FilterBuilder()
    .WithinDateRange(dateRange)
    .IncludingKeywords("politics", "news")
    .ByAuthor("John Smith")
    .Build();

blogs.FindByFilter(filter);
Run Code Online (Sandbox Code Playgroud)

请注意,创建过滤器的代码可以位于域之外。因为它不会违反任何域规则。如果有“匿名作者发布的博客应得到版主批准”之类的规则怎么办?虽然可以用Filter来表达,但是这样做会将业务逻辑具体化。将此规则放入域代码中并拥有专用的存储库方法会更有意义,例如:

blogs.RequireModeratorAttention();
Run Code Online (Sandbox Code Playgroud)