具有域驱动设计的存储库模式是否成为反模式?

时间:2013-08-07 05:46:02

标签: c# domain-driven-design

首先,我想澄清一点,我是Domain Driven Design的新手,我问的是这个问题,因为我读过一些名为Anemic Domain Model的内容。

大部分时间我在使用Repository模式时都会看到以下内容。

  1. 我们有一个通用存储库
  2. 我们的Model只包含一组公共属性,但它不包含任何方法(因此它根据DDD的定义成为Anemic Domain Model),因为这里的存储库类处理该实体或模型的其他进程。
  3. 请为我的查询提供有价值的答案。

    让我澄清一些事情。

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

    我的困惑是关于以下事情

    例如:    假设我要保存

        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只有属性和其他操作句柄。所以我的用户是Anemic Domain模型。 (因为它什么都不具体)

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

    请考虑以下示例图片,以了解我要说的内容。

    enter image description here

2 个答案:

答案 0 :(得分:21)

我同意IRepository界面通常是浪费时间。如果我将基本CRUD操作放在IRepository接口中,那么如何处理审计数据等数据呢?如果删除它将被禁止。当我尝试拨打InvalidOperationException时,我应该返回Delete()吗?

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

就个人而言(这只是我自己的解决方案,在其他所有方面都能很好地运行),对于DDD,我更喜欢每个存储库使用一个接口(主要用于IoC和单元测试)。这给了我IUserRepositoryIAuditLogRepository等。我的存储库也采用(作为参数)并返回域实体(聚合根或仅单个实体)。这样就没有贫血的DTO对象来维持或混乱我的解决方案。但是我仍然使用视图模型来保护敏感数据不受我的观点影响。

网上有很多关于存储库模式的论据。

答案 1 :(得分:19)

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

存储库模式专业人员:

  1. 底层持久性技术的抽象
  2. 定义聚合根的可能性,只有聚合根应该有存储库
  3. 一种明确说明哪些操作对所讨论的聚合根有效的方法,例如,如果它对于删除您的实体无效,则您的存储库应该没有删除方法。
  4. 在没有数据库的情况下很容易测试的东西(存根你的存储库)
  5. 存储库模式缺点:

    1. 接近您的持久性技术。
    2. 又一层
    3. 我个人更喜欢在执行DDD时使用存储库模式,但您的解决方案听起来更像是活动记录模式,从而消除了首先使用存储库的大部分好处。我从不做通用存储库,因为他们删除了专业版2&amp; 3(我可以有一个通用实现,但我不直接将它暴露给存储库消费者代码)。

      此外:不要将存储库用于DTO,ViewModel等群体。使用单独的模型和技术来建模写入(DDD可以很好地工作)和读取。