【问题标题】:Active Records vs. Repository - pros and cons?Active Records vs. Repository - 优点和缺点?
【发布时间】:2011-09-25 04:57:34
【问题描述】:

使用 ActiveRecord 你可以定义一个这样的类:

class Contact
{
  private String _name;
  public String Name
  {
    get { return _name; }
    set 
    { 
      if (value == String.IsNullOrWhiteSpace())
        throw new ArgumentException(...);
      else
        _name = value;
    }
  }

  public Boolean Validate() { ... /* check Name is unique in DB */  }

  public Boolean Save() { ... }

  public static List<Contact> Load() { ... }
}

虽然这很好而且很简单,但我发现我的课程变得非常臃肿,逻辑混杂在一起!

使用分层/域设计,您可以定义相同的类,例如:

class Contact
{
    [Required(AllowEmptyStrings=false)]
    public String Name { get; set; }
}

class ContactService : IService
{
    public List<Contact> LoadContacts() { return (new ContactRepository()).GetAll(); }
    public Contact LoadContact(int id) { return (new ContactRepository()).GetById(id); }
    public Boolean SaveContact(Contact contact)
    {
        if (new ContactValidator().Validate(contact))
            new ContactRepository().Save(contact);
    }
}

class ContactRepository : IRepository
{
    public List<Contact> GetAll() { ... }
    public Contact GetById(int Id) { ... }
    public Boolean Save(Contact contact) { ... }
}

class ContactValidator : IValidator
{
    public Boolean Validate(Contact contact) { ... /* check Name is unique in DB */ }
}

class UnitOfWork : IUnitOfWork
{
    IRepository _contacts = null;
    public UnitOfWork(IRepository contacts) { _contacts = contacts; }
    public Commit() { _contacts.Save(); }
}

它是如何从 Active Record => 分层设计迁移而来的?

  • 名称设置器中的实体级别验证 => 保留(通过 DataAnnotation 实现)
  • 业务逻辑/规则验证(唯一名称)=> 从实体移动到新的单独 ContactValidator
  • 保存逻辑 => 移至单独的存储库模式类(也带有 UnitOfWork)
  • 加载逻辑 => 移至单独的存储库
  • 与存储库的交互是通过新的 ContactService 进行的(它将强制使用 ContactValidator、ContactRepository、UnitOfWork 等,而不是让调用者使用 ContactRepository!)。

我正在为这种分层设计寻求同行的认可/建议 - 我通常不会在 Active Record 类型之外进行设计!任何意见表示赞赏。

注意 - 这个例子是故意简单的(UnitOfWork 并没有真正使用,并且新的 Repository/Validator 会以不同的方式处理)。

【问题讨论】:

    标签: design-patterns activerecord architectural-patterns


    【解决方案1】:

    这实际上取决于您的域逻辑有多复杂。例如,如果我正在写一个简单的博客,那么活动记录就可以了,主要是应用程序正在保存和加载数据。其简单而活跃的记录模式是适合这项工作的工具。

    但是,如果我为一家航运公司编写软件,其中有许多复杂的业务规则和流程,那么从长远来看,使用存储库模式以及其他 Domain Driven Design 模式将提供更易于维护的代码。

    使用域驱动设计,您将使用specification pattern 来实现验证。

    【讨论】:

      【解决方案2】:

      这篇文章似乎是对两者的良好而简洁的描述: https://hashnode.com/post/which-design-pattern-do-you-prefer-active-record-or-repository-cilozoaa5016o6t53mhsdu6nu

      我想补充的一点是,它不仅仅是“当你的持久性需求很简单时,活动记录很好,当你的持久性需求很复杂时,存储库很好”。这里模式的选择与你对得墨忒耳法则的感觉有很大关系。如果您希望将架构的不同部分完全分开,以便某人可以理解一个部分而不理解另一个部分,那么您需要得墨忒耳定律。话虽如此,我认为,尤其是在规范可能发生变化的项目早期,对这些抽象过于执着是非常危险的。不要再猜测您项目的未来维护者,他们可能很聪明,他们应该能够一次考虑不止一件事,如果他们不能,那么您可能会遇到使用存储库模式无法避免的更大问题.

      【讨论】:

        【解决方案3】:

        这两种方法各有利弊。

        假装,您正在将 Active Record 样式的对象传递到某个地方(BL 深处)。你可以阅读它,你可以改变它,你可以保存它。在这种情况下,那块 BL 只与您实体的接口耦合。使用分层架构,您必须以某种方式将存储库传递给该代码。你要么明确地传递它,要么使用 IoC 容器 - 由你决定。

        另一点是,当您有了存储库的概念时,您可以轻松定义诸如 we-have-a-new-object-in-repository 或 one-object-has-been-deleted-from-repository 之类的概念如果您正在使用分布式环境,这基本上是非常有用的通知。

        【讨论】:

          猜你喜欢
          • 2015-12-09
          • 1970-01-01
          • 2011-02-25
          • 2019-08-04
          • 1970-01-01
          • 1970-01-01
          • 2015-05-18
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多