【问题标题】:Where repository classes should be?存储库类应该在哪里?
【发布时间】:2015-12-12 23:00:39
【问题描述】:

当我尝试将 DDD 与 .NET 和 C# 一起使用时,我通常的过程是为域模型构建一个项目,为数据访问构建另一个项目,为应用程序本身构建另一个项目,例如 ASP.NET Web API。通常会涉及更多项目,但我通常会使用这三个。

我的意思是,在域模型项目中,我放置了所有业务规则。在那里我定义了域类型(实体、值类型、聚合等)和存储库接口。

我的意思是,在我定义了存储库接口之后,我会在一个单独的项目中实现。该项目是数据访问项目。我这样做的原因是,为了实现数据访问,我通常需要这样做的技术(如 ADO.NET、EF、Dapper 等)。

出于某些原因,我自己认为将这些依赖项耦合到 Domain 项目是一种不好的形式。我喜欢 Domain 项目是自包含的并且与任何技术分离。

另一方面,我有时听说存储库可能包含业务规则,应该在域项目内部实现。

哪种方法是正确的?我的方法是将存储库实现与域项目分离,以避免将技术依赖项耦合到域项目,还是允许存储库中的业务规则从而使存储库存在于域项目中的方法?

存储库真正应该在哪里?与域类型一起在域项目中还是在数据访问项目中?

【问题讨论】:

    标签: c# .net oop domain-driven-design repository-pattern


    【解决方案1】:

    你的方法是正确的。存储库应该在基础设施层实现。

    另一方面,我有时听说存储库可能包含业务规则,应该在域项目内部实现。

    存储库的唯一职责应该是持久性。如果您最终在存储库中使用业务逻辑,则应该重构它们。将业务逻辑移至域模型并将存储库保留在基础架构中。

    如果您在查询中有业务逻辑,在 C# 中处理它的一种简单方法是从存储库返回 IQueryable<T>。然后,您可以使用 LINQ 在应用程序或域服务中创建查询。有些人可能会争辩说这是一种泄漏的抽象——您将存储库的实现限制为与IQueryable 配合良好的数据访问技术。易用性通常值得一试。

    【讨论】:

      【解决方案2】:

      存储库是域和数据映射器之间的边界。我会说存储库不是关于数据访问,而只是谁使用数据映射器将域转换为某种数据,并且它还执行从数据到域的反向转换。

      而不是在域项目之外定义和实现它们,如果您想将它们保留为 tech-agnostic,也许您可​​以在域项目上定义存储库接口并创建一个 Domain。 [SomeTech] 其中 SomeTech 可能是 EFDapper 等等,以及您将在哪里实施技术-特定的存储库。

      现在您的应用程序项目将需要同时引用 Domain 和例如 Domain.EF 项目。

      顺便说一句,根据我自己的经验,就代码文件的组织方式而言,良好的关注点分离不如解决方案在软件层方面的架构那么重要。

      也就是说,如果您的项目完全使用像实体框架这样的 OR/M,那么您将来更改它的机会是微不足道的,因此,不要浪费您的时间来创建一个包含太多项目而类很少的解决方案每个人都专注于代码中关注点的良好分离。

      总有时间拆分项目,而错误的架构只是浪费时间。

      【讨论】:

        【解决方案3】:

        请记住,每个代码库、每个项目、每个域都是不同的。没有硬性规定。设计最适合您项目的代码。

        我有时听说存储库可能包含业务规则

        如果是这样,那么它们不仅仅是存储库。从最严格的意义上说,存储库只是将内容持久化到某个存储中。

        现在,存储库中可以有 业务驱动 逻辑,但仍然只是 持久性 逻辑。在您描述的标准 3 层设置中,这种持久性逻辑可能需要在该层的任何其他实现中复制。这不是世界末日。

        但这确实引出了您要问的问题。而且,正如我所说,确实没有硬性规定。您需要为您的项目决定要维护哪些规则并围绕这些规则设计代码。

        例如...

        • 您可以将此“业务逻辑”移动到模型或其他域代码中,并保持存储库简单。
        • 您可以将此“业务逻辑”保留在存储库中,并在其他存储库实现中重新实现。
        • 您可以在传统域和应用此“业务逻辑”的简单存储库之间创建一个薄层。您可以将这些视为存储库接口的域拥有的包装器。这些对象不是真正的业务模型,而是与存储库相关的概念逻辑类型,其唯一目的是专门包含此逻辑。

        最后,这真的取决于你。除了对您的代码库最有意义并产生简单、可维护的代码的答案之外,没有正确的答案。

        【讨论】:

          【解决方案4】:

          您的解决方案 [*1] 表示数据管理、人机交互、系统交互的对象和您的问题域之间应该有逻辑上的分离(问题对象模型)。

          物理分离(比如项目)是完全可选的。许多人会认为这是一种良好的组织实践。

          数据管理对象(例如存储库)应该只具有持久化和检索持久化数据的功能,而不是业务逻辑或规则。

          [*1] 包括为您的问题建模的对象(“问题域”),以及生成完整工作系统所需的所有支持对象。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2018-10-28
            • 1970-01-01
            • 2023-04-07
            • 2014-03-06
            • 1970-01-01
            • 2015-05-03
            • 2019-04-25
            相关资源
            最近更新 更多