Active Records vs. Repository - плюсы и минусы? - PullRequest
9 голосов
/ 29 июня 2011

Используя 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 => многоуровневый дизайн?

  • Проверка уровня объекта в установщике имен => остается (возможно с помощью аннотации данных)
  • Проверка бизнес-логики / правила (уникальное имя) => перемещена из сущности в новый отдельный ContactValidator
  • Сохранить логику => перемещено в отдельный класс шаблонов репозитория (также с UnitOfWork)
  • Загрузка логики => перемещена в отдельный репозиторий
  • Взаимодействие с репозиторием осуществляется с помощью новой службы ContactService (которая будет обеспечивать использование ContactValidator, ContactRepository, UnitOfWork и т. Д., В отличие от того, чтобы вызывающая сторона теряла связь с ContactRepository!).

Я ищу одобрение / предложения коллег для этого многоуровневого дизайна - я обычно не проектирую за пределами типа Active Record! Любой комментарий приветствуется.

NB. - Этот пример намеренно прост (UnitOfWork на самом деле не используется, и обновление Repository / Validator будет обрабатываться иначе).

Ответы [ 3 ]

7 голосов
/ 25 августа 2011

Это действительно зависит от того, насколько сложна логика вашего домена. Например, если я писал простой блог, тогда с активной записью все будет в порядке, в основном приложение сохраняет и загружает данные. Его простой и активный шаблон записи является подходящим инструментом для работы.

Однако, если я писал программное обеспечение для транспортной компании, в которой существует много сложных бизнес-правил и процессов, то использовал шаблон хранилища вместе с другими шаблонами, управляемыми доменом , которые обеспечили бы гораздо более удобный для сопровождения код в долгосрочной перспективе.

При использовании доменного дизайна вы можете использовать шаблон спецификации для проверки.

2 голосов
/ 01 февраля 2018

Эта статья выглядит как хорошее и краткое описание обоих: https://hashnode.com/post/which-design-pattern-do-you-prefer-active-record-or-repository-cilozoaa5016o6t53mhsdu6nu

Одна вещь, которую я хотел бы добавить, это не просто «активная запись хороша, когда ваши постоянные потребности просты, а репозиторий хорош, когда ваши постоянные потребности сложны». Выбор паттерна здесь во многом зависит от того, как вы относитесь к Закону Деметры. Если вы хотите, чтобы разные части вашей архитектуры были полностью разделены, чтобы кто-то мог понять одну часть, не понимая другую, тогда вам нужен закон Деметры. Тем не менее, я думаю, что особенно в начале проекта, когда спецификация может измениться, ОЧЕНЬ опасно становиться слишком одержимым этими видами абстракции. Не пытайтесь угадать будущих сопровождающих вашего проекта, они могут быть умными, и они должны иметь возможность думать о более чем одной вещи за раз, а если они не могут, то у вас могут возникнуть более серьезные проблемы, которые невозможно предотвратить с помощью шаблона Repository .

2 голосов
/ 19 июля 2011

Оба подхода имеют свои плюсы и минусы.

Представьте, что вы передаете объект в стиле Active Record куда-то (глубоко внутри BL).Вы можете прочитать его, вы можете изменить его, вы можете сохранить его.В этом случае этот фрагмент BL связан только с интерфейсом вашей сущности.С многоуровневой архитектурой вам нужно как-то передать хранилище в этот код.Вы бы либо передавали его явно, либо использовали IoC-контейнер - на ваше усмотрение.

Другой момент заключается в том, что когда у вас есть концепция хранилища, вы можете легко определить такие понятия, как we-have-a-new-объект в репозитории или один объект был удален из репозитория, которые в основном являются весьма полезными уведомлениями, если вы работаете с распределенной средой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...