Active Records vs. Repository - 优点和缺点?

时间:2011-06-29 14:09:19

标签: design-patterns activerecord architectural-patterns

使用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 =&gt;迁移?分层设计?

  • 名称设置中的实体级别验证=&gt;保持(通过DataAnnotation)
  • 业务逻辑/规则验证(唯一名称)=&gt;从实体移到新的单独的ContactValidator
  • 保存逻辑=&gt;移动到单独的Repository模式类(也使用UnitOfWork)
  • 加载逻辑=&gt;移到单独的存储库
  • 与存储库的交互是通过一个新的ContactService(它将强制使用ContactValidator,ContactRepository,UnitOfWork等 - 而不是让调用者通过ContactRepository松散!)。

我正在为这种分层设计寻找同行批准/建议 - 我通常不会在Active Record类型之外进行设计!任何评论都赞赏。

注意 - 这个例子非常简单(UnitOfWork并没有真正使用,而且Repository / Validator的新版本将以不同方式处理)。

3 个答案:

答案 0 :(得分:6)

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

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

使用域驱动设计,您可以使用specification pattern来验证。

答案 1 :(得分:2)

这两种方法都有其优点和缺点。

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

另一点是,当你有了存储库的概念时,你可以很容易地定义像我们有一个新的存储库对象或者一个对象已被删除的存储库这样的概念。如果您正在使用分布式环境,这些通知非常有用。

答案 2 :(得分:2)

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

我想补充的一件事是,当你的持久性需求很简单时,活动记录是好的,当你的持久性需求很复杂时,存储库是好的“。这里的模式选择与你对德米特定律的看法有很大的关系。如果您希望您的架构的不同部分完全分离,以便某人可以理解一个部分而不理解另一个部分,那么您需要Demeter法则。这就是说,我认为,特别是在规范可能发生变化的项目的早期,对这些抽象过于强迫是非常危险的。不要再猜测你的项目的未来维护者,他们可能很聪明,他们应该能够一次考虑多个事情,如果他们不能,那么你可能会遇到无法通过使用Repository模式阻止的更大问题