c# - Tener un repositorio dependiente de otro repositorio
repository-pattern solid-principles (2)
El repositorio debe tener una responsabilidad única: persistir en un tipo de entidad. Ej. Empleados. Si tiene que eliminar algunos registros asociados de otro repositorio, parece una lógica empresarial. P.ej
Cuando el empleado es despedido debemos remover su registro de trabajo.
Y el lugar habitual para la lógica empresarial es un dominio de servicios. Este servicio tendrá ambos repositorios y hará todo el trabajo:
staffService.Fire(employee)
La implementación se verá como
public class StaffService
{
private IEmployeeRepository employeeRepository;
private IWorkLogRepository workLogRepository;
private IUnitOfWorkFactory uowFactory;
// inject dependencies
public void Fire(Employee employee)
{
using(var uow = uowFactory.SartNew())
{
workLogRepository.DeleteByEmployee(employee.Id);
employeeRepository.Delete(employee.Id);
uow.Commit();
}
}
}
Así que, consejos básicos.
- trate de mantener su lógica empresarial en un lugar, no extienda parte de ella a la interfaz de usuario, parte de ella a los repositorios, parte a la base de datos (a veces, debido a problemas de rendimiento, tiene que hacer algo de lógica en la base de datos, pero eso es una excepción)
- nunca permita que los repositorios hagan referencia a otros repositorios, el repositorio es un componente de muy bajo nivel de su aplicación con responsabilidades muy simples
Puede preguntarse qué hacer si tiene un empleado y tiene algún objeto anidado que se almacena en una tabla de base de datos diferente. Si usa ese objeto por separado del empleado, entonces todo es como antes: debe tener un repositorio separado y algún otro objeto (servicio) que manipule ambos repositorios. Pero si no usa ese objeto anidado por separado del empleado, el empleado es una raíz agregada y solo debe tener un repositorio de empleados, que consultará ambas tablas en su interior.
Recientemente he pasado tiempo leyendo los principios de SOLID y decidí ver cómo se compara el código base con el que trabajo.
En algunos de nuestros códigos hay un repositorio (repositorio A). Cuando se debe eliminar un registro del repositorio A, también debemos eliminar un registro asociado del repositorio B. Por lo tanto, el codificador original ha creado una dependencia para una implementación concreta del repositorio B. El método en el repositorio A está dentro de una transacción elimina el registro del repositorio A y luego llama al método en el repositorio B para eliminar los datos asociados.
Mi comprensión del principio S es que cada objeto debe tener solo 1 razón para cambiar, pero para mi repositorio A tiene 2 razones para cambiar? ¿O estoy fuera de lugar?
En este caso, debe hacer uso del patrón de despachador de eventos .
Después de la operación de eliminación en RepoA , puede enviar un evento como:
dispatch repositoryA.deleted(RecordA)
Eso contendrá la información del registro borrado.
A continuación, se suscribirá un panel de ventilación en dicho evento y, teniendo el Repositorio B como dependencia, invocará un borrado.
Usemos B como el nombre de la entidad, la declaración del oyente debe sonar como:
Listen RepositoryA.delete and invoke onDelete(Event)
Con este enfoque, se ha dado cuenta de un acoplamiento suelto entre repoA y repoB (aplicando el principio de apertura / cierre (en el lado cercano)) así que repoA tiene ahora (otra vez)
Saludos.