repositorio pro org language for design-patterns activerecord architectural-patterns

design patterns - org - Active Records vs. Repository: pros y contras?



r for linux download (2)

Ambos enfoques tienen sus pros y sus contras.

Imagine que está pasando un objeto con estilo de Active Record a algún lugar (en el interior de BL). Puedes leerlo, puedes cambiarlo, puedes GUARDARLO. En este caso, esa pieza de BL solo se combina con la interfaz de tu entidad. Con la arquitectura en capas, debe pasar el repositorio a ese código de alguna manera. Lo pasarás explícitamente o usarás IoC-container, depende de ti.

El otro punto es que cuando tienes el concepto de repositorio, puedes definir fácilmente conceptos como we-have-a-new-object-in-repository, o one-object-has-been-deleted-from-repository que son básicamente notificaciones bastante útiles si estás trabajando con un entorno distribuido.

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

Si bien esto es agradable y simple, ¡he descubierto que mis clases se vuelven muy hinchadas con una gran combinación de lógica!

Al usar un diseño de 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?

  • La validación del nivel de la entidad en el Name setter => permanece (puede hacerlo a través de una Anotación de datos)
  • Validación de lógica / regla de negocios (Nombre único) => movido de entidad a un nuevo ContactValidator separado
  • Save logic => movido a una clase de patrón de Repositorio por separado (también con un UnitOfWork)
  • Load logic => movido al Repositorio separado
  • La interacción con el repositorio es a través de un nuevo ContactService (que hará cumplir el uso de ContactValidator, ContactRepository, UnitOfWork, etc., ¡y se opone a que la persona que llama pierda contacto con ContactRepository!).

Estoy buscando la aprobación / sugerencias de los compañeros para este diseño en capas. ¡Normalmente no diseño fuera del tipo de registro activo! Cualquier comentario apreciado.

NB: este ejemplo es deliberadamente simple (el UnitOfWork no se usa realmente y el newing del Repository / Validator se manejaría de manera diferente).


Realmente depende de cuán compleja es la lógica de tu dominio. Por ejemplo, si estuviera escribiendo un blog simple, entonces el registro activo estará bien, la mayoría de las aplicaciones guardan y cargan datos. Su patrón de registro simple y activo es la herramienta adecuada para el trabajo.

Sin embargo, si estaba escribiendo software para una empresa naviera en la que existen muchas reglas y procesos comerciales complejos, el uso del patrón de repositorio, junto con otros patrones de diseño impulsados ​​por el dominio proporcionarán un código mucho más sostenible a largo plazo.

Al utilizar el diseño impulsado por el dominio, utilizará el patrón de especificación para lograr su validación.