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

ьзуя 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! Любой комментарий приветствуется.

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

Ответы на вопрос(3)

Ваш ответ на вопрос