【问题标题】:Is Repository Pattern with Domain Driven Design become Anti-Pattern? [closed]具有领域驱动设计的存储库模式会成为反模式吗? [关闭]
【发布时间】:2013-08-08 08:46:15
【问题描述】:

首先,我想澄清一下,我是域驱动设计的新手,我之所以提出这个问题,是因为我读过一个叫做贫血域模型的东西。

大多数时候我在使用存储库模式时会看到以下内容。

  1. 我们有一个通用存储库
  2. 我们的模型仅包含一组公共属性,但不包含任何方法(因此根据 DDD 的定义,它成为贫血域模型),因为这里存储库类处理该实体或模型的其他进程。

请为我的查询提供您宝贵的答案。

让我澄清几件事。

Generic Repository 是指由实体存储库实现的通用接口。

我的困惑是关于以下事情

例如: 假设我想保存

    public class User
    {
        public int Id { get; set;}
        public string Name { get; set};
    }

    public class UserRepository : IRepository<User>  
    {  
        // All Operation Like Save / Get /  UserEntity (Domain Object)       
    }

所以这里是我的 User 类什么都不做,它只有属性和其他操作句柄 UserRespository。所以我的用户是贫血域模型。 (因为它没有做任何具体的事情)

在附图中我考虑ProductRepository 所以我的问题是:我的产品类是贫血模型吗?

请考虑按照我想说的示例图片。

【问题讨论】:

  • 您能详细说明一下吗?是什么让你认为 Repository 会是一个反模式?有人的意见?你自己?如果您期望得到有价值的答案,请在问题中添加一些价值:)
  • Repository 是反模式不是我自己的,但我混淆了贫血域模型定义和存储库模式的方式。像存储库模式一样负责保存实体,但实体本身没有任何保存方法。
  • 这在 DDD 中完全有效,将存储库视为服务。
  • 这里是 DDD\CQRS 邮件列表上有关此问题的主题:groups.google.com/d/msg/dddcqrs/krOf_dqnD8o/qpTc0OPQSMQJ
  • “我们有一个通用存储库”是什么意思。每个聚合都应该有特定的存储库,而不是通用的。

标签: c# domain-driven-design


【解决方案1】:

我同意IRepository 接口通常是浪费时间。如果我把基本的 CRUD 操作放在我的IRepository 接口中,那么我该如何处理审计数据之类的数据呢?在哪里删除它是被禁止的。当我尝试调用Delete() 时,我应该只返回InvalidOperationException 吗?

有些人建议使用较小的接口,例如 IReadableIWriteableIUpdateableIDeleteable。我认为这种方法更加混乱。

就个人而言(这只是我自己的解决方案,在对其他所有内容进行了很好的测试之后),对于 DDD,我更喜欢为每个存储库使用一个接口(主要用于 IoC 和单元测试)。这给了我IUserRepositoryIAuditLogRepository 等。我的存储库也接受(作为参数)并返回域实体(聚合根或单个实体)。这样就没有贫血的 DTO 对象来维护或弄乱我的解决方案。但是,我仍然使用视图模型将敏感数据排除在我的视图之外。

网上有很多支持和反对存储库模式的论据。

【讨论】:

    【解决方案2】:

    存储库模式本身并不是一种反模式,但我已经看到很多 DDD 实现,其中存储库模式提供的价值很少或没有。将你的 n-tier-provide-no-value 分层架构交给务实的核心专家开发人员,他可能会给你“反模式”的批评(我可能会说是有效的)。

    存储库模式专家:

    1. 底层持久性技术的抽象
    2. 可以定义聚合根,只有聚合根应该有存储库
    3. 一种明确说明哪些操作对相关聚合根有效的方式,例如,如果删除您的实体无效,则您的存储库应该没有删除方法。
    4. 无需数据库即可轻松测试(存根存储库)

    存储库模式缺点:

    1. 贴近您的持久性技术。
    2. 又一个层次

    我个人更喜欢在做 DDD 时使用存储库模式,但您的解决方案听起来更像是活动记录模式,因此首先消除了使用存储库的大部分好处。我从不做通用存储库,因为它们删除了优点 2 和 3(我可以有一个通用实现,但我不直接将它暴露给存储库消费者代码)。

    另外:不要使用存储库来填充 DTO、ViewModel 等。使用单独的模型和技术来建模写入(DDD 可以很好地工作)和读取。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多