16

使用 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 => 分层设计迁移而来的?

  • Name setter => 中的实体级别验证仍然存在(通过 DataAnnotation 实现)
  • 业务逻辑/规则验证(唯一名称)=> 从实体移动到新的单独 ContactValidator
  • 保存逻辑 => 移至单独的存储库模式类(也带有 UnitOfWork)
  • 加载逻辑 => 移动到单独的存储库
  • 与存储库的交互是通过一个新的 ContactService(它将强制使用 ContactValidator、ContactRepository、UnitOfWork 等 - 反对让调用者与 ContactRepository 松散!)。

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

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

4

3 回答 3

11

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

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

使用领域驱动设计,您将使用规范模式来实现您的验证。

于 2011-08-25T02:32:41.787 回答
4

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

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

于 2018-02-01T14:51:38.297 回答
3

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

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

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

于 2011-07-19T19:14:35.107 回答