Domain driven design 从域(DDD)访问存储库的替代方案

Domain driven design 从域(DDD)访问存储库的替代方案,domain-driven-design,Domain Driven Design,我见过很多这样的问题,但它们似乎总是与我的想法不匹配。 我认为这是因为我对聚合根实体和值对象之间的关系理解不周 在我看来,完成的解决方案就像DTO一样,因为所有的东西(所有的逻辑)似乎都在存储库中结束。也许我看EF教程看得太多了 假设我们有一个非常简单的类,带有repo的第一个版本(忽略它只处理一个人): 现在,我想从UI(比如,按下按钮)执行的操作是而不是: person.MakeOlder(); _repo.Save(person); 但也许只是: person.MakeOlder();

我见过很多这样的问题,但它们似乎总是与我的想法不匹配。 我认为这是因为我对聚合根实体和值对象之间的关系理解不周

在我看来,完成的解决方案就像DTO一样,因为所有的东西(所有的逻辑)似乎都在存储库中结束。也许我看EF教程看得太多了

假设我们有一个非常简单的类,带有repo的第一个版本(忽略它只处理一个人):

现在,我想从UI(比如,按下按钮)执行的操作是而不是

person.MakeOlder();
_repo.Save(person);
但也许只是:

person.MakeOlder();
对我来说,“MakeOlder”操作应该触发保存。但这当然需要亲自提及回购协议。 我能想到的唯一选择是:

_repo.MakePersonOlder(person);
(看起来很糟糕。)

(从UI pov中没有收益,这就是我现在看到的)

或者是它的一些变体;事件、AOP等。以某种方式发出信号或捕获应进行保存

我想我也可能把我对DDD的看法与事件来源和类似概念混为一谈

我是否完全错误地认为,
SavePerson
调用UI代码感觉脏


“正确”的做法是什么?

您不应该将存储库传递给个人。使用该模型,您必须将存储库传递给每个方法。通常,如果使用EF或其他ORM,则有一个内置的概念。工作单元跟踪在定义的交互中已更改的所有对象。当您提交一个工作单元时,它会提交其中的所有更改。代码看起来更像:

person.MakeOlder();
_unitOfWork.Commit();
当多个实体发生更改时,可以使用此方法。由于ORM跟踪更改,因此不必显式保存作为工作单元一部分的每个对象

一个更好的选择,也解决了您的问题,就是用一个。应用程序服务将具有如下方法:

public void MakeOlder(int personId)
{
   var person = this.personRepository.Get(personId);
   person.MakeOlder();
   this.unitOfWork.Commit();
}

然后UI将直接调用应用程序服务而不是域对象。

非常同意。您缺少ApplicationService概念。应用层非常重要

我只是不同意你的观点:

在我看来,完成的解决方案就像DTO,因为所有东西(所有逻辑)最终都会>在存储库中

这是因为您需要更好地理解层。表示层(UI)将调用na应用程序服务(Façade)。建议的MakePersonOlder(int personId)

应用层负责协调操作:)

这些操作之一可能是保存到存储库、登录到文本文件、发送电子邮件等

明白了


布鲁诺

尤勒夫比我跑得快。我要补充的是,用户不需要使用存储库的原因是关注点分离。Person是一个域对象,它对域进行建模,它一点儿也不关心持久性,也不关心实际使用的位置或用户。这根本不是它的责任。好吧,好吧,但我仍然觉得示例缺少一些实际的代码来获得完整的上下文。然后我假设UI仍然会看到域对象,并且我们将“命令”与查询分开,也就是CQR?或者UI代码应该调用ApplicationService.GetPerson()(“洋葱架构”?)?您可以让应用程序服务将域对象返回到UI或只读对象,使其更像CQR。我更喜欢后一种方法,因为它让应用程序服务完全封装了域。
class Person : IMyEntityBaseType { ...
    void MakeOlder() { 
        Age++; 
        EntityDataWasChangedNowIWantToBeSaved(); 
    }
}
person.MakeOlder();
_unitOfWork.Commit();
public void MakeOlder(int personId)
{
   var person = this.personRepository.Get(personId);
   person.MakeOlder();
   this.unitOfWork.Commit();
}