Active Records vs. Repository - pros y contras?

Utilizando ActiveRecord puede definir una clase como esta:

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() { ... }
}

¡Aunque esto es agradable y simple, he descubierto que mis clases se hinchan mucho con una gran combinación de lógica!

Utilizando un diseño en capas / dominio, puede definir la misma clase como:

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(); }
}

¿Cómo se migró de Active Record => diseño en capas?

Validación de nivel de entidad en el Establecedor de nombres => permanece (habilitado a través de una Anotación de datos)Lógica de negocios / validación de reglas (Nombre único) => movido de la entidad a un nuevo ContactValidator separadoGuardar lógica => movido a una clase de patrón de Repositorio separada (también con un UnitOfWork)Load logic => movido al repositorio separado La interacción con el repositorio se realiza a través de un nuevo ContactService (que exigirá el uso de ContactValidator, ContactRepository, UnitOfWork, etc., ¡en lugar de dejar que la persona que llama pierda el ContactRepository!).

Estoy buscando aprobación / sugerencias de pares para este diseño en capas: ¡no suelo diseñar fuera del tipo de registro activo! Cualquier comentario apreciado.

NB: este ejemplo es deliberadamente simple (UnitOfWork no se usa realmente y la nueva actualización del Repositorio / Validador se manejaría de manera diferente).

Respuestas a la pregunta(3)

Su respuesta a la pregunta