DDD存储库应该是什么:
findAllByPurchaseId(purchaseId)
findAllOfPurchaseDueBefore(purchaseId, limitDate)
amountExpectedToBePaidBefore(purchaseId, limitDate)
我的域模型有两个聚合:
Purchase(purchaseId)
Installment(purchaseId, dueDate, amount)
在我的一项申请服务中,我必须回答有关在特定日期之前预期支付的总分期付款金额的问题。
初始InstallmentRepository
实现(Groovy + Grails + GORM + Hibernate):
def findAllByPurchaseId(purchaseId) {
Installment.executeQuery(
'from Installment where purchaseId = :purchaseId',
[purchaseId: purchaseId]
)
}
应用程序服务进一步过滤和计算:
def amountExpectedToBePaidBefore(purchaseId, limitDate) {
def installments = installmentRepository.findAllByPurchaseId(purchaseId).
findAll { it.dueBefore limitDate }
installments*.amount.sum()
}
我意识到我的应用服务有域逻辑 - 它做了额外的过滤和计算。另一方面,我的存储库似乎太 DAOish - 它做了简单的聚合访问而没有任何额外的业务价值。
我考虑两个重构选项:
dueDate
中的过滤放入存储库中,并将域中的金额加入由于存储库应该模仿专门的聚合集合,而API基于无处不在的语言,因此选项 2。对我更有吸引力。
是否应执行可能由许多服务使用的通用搜索?
存储库查找器应该/可能是应用程序服务/用例特定吗?
在存储库中进行其他(虽然简单)计算是否可以?
答案 0 :(得分:2)
没有。域存储库查询通常是GetById()。这不是一个硬性规则,但这是域需要99%的时间。不要重复使用域存储库界面进行演示/报告查询。也就是说,具体类可以处理所有内容,但抽象应该根据上下文需求进行定制。
如果域名需要,则存储库方法会获得一个可以使用的条件。
如果处理不需要业务规则那么它就可以了。然而,这不是真正的存储库语义,而是恰好在DAL中实现的服务。是的,但不要将其称为存储库:)