.net - net - ¿Es malo inyectar DAO en las entidades?
net core microservices (3)
Así que, como la mayoría de los nuevos desarrolladores de .NET, comienzas a pasar DataSets a todas partes y, aunque las cosas funcionen bien, no parece correcto.
La próxima progresión suele ser crear objetos de entidad que extienden una clase base DAL para que tenga, por ejemplo,
public class User : UserDAL
{
//User specific methods
}
public class UserDAL
{
//Bunch of user specific properties
public User Load(int Id)
{
//Some low level ADO calls
}
private User LoadFromDataSet(DataSet ds)
{
//Load entity properties from DataSet
}
}
El usuario extiende los objetos UserDAL que tienen llamadas de bajo nivel de acceso a datos usando ADO.NET.
A partir de aquí, descubres que esta implementación significa que estás vinculado a una capa de acceso a datos y haces uso de una entidad separada, un objeto de acceso a datos y una interfaz DAO para burlar o cambiar fácilmente el DAO si es necesario. es decir
public UserDAO : IUserDAO
{
//Data access Functions
}
Con el uso de genéricos y reflexión o un buen ORM puede aliviar algunas de las operaciones CRUD de acceso a datos más comunes, es decir,
Public UserDAO<User> : BaseDAO<User>, IUserDAO
{
//BaseDAO deals with basic crud so more custom data access methods can go here
}
Así que, básicamente, allí es donde me encuentro actualmente, aparte de otras prácticas agradables, como usar IoC para resolver el IUserDAO específico que quiero. Pero aunque veo la ventaja de esta estructura, también me da la sensación de que extraño las antiguas llamadas al método User.Load (1).
Lo que me preguntaba es, ¿sería tan malo inyectar mi IUserDAO en la entidad de usuario y hacer que se encarguen de las operaciones básicas de CRUD?
Tengo entendido que, como POCO, la entidad Usuario no tendría problemas al pasar por el cable y agregar métodos como Guardar (), Cargar (), etc. no tendría ninguna relación en el sentido de un objeto de transferencia de datos.
Pero dicho esto, mis entidades usualmente tienen colecciones cargadas perezosas que no significan nada en un sentido DTO. Además, con WFP, creo que puedo escoger y elegir qué propiedades quiero serializar, o al menos podría crear un nuevo UserDTO cuando necesite enviarlo a través del cable.
Entonces, básicamente, aparte de ese problema, ¿cuáles son los otros problemas al hacer que mi entidad de usuario incluya métodos relacionados con DataAccess? También podría alguien aclarar si a lo que me refiero se lo conoce como un patrón de registro activo o se trata de otra cosa?
EDITAR:
cristianlibardo señaló:
En cuanto a los posibles inconvenientes, existe un mayor acoplamiento al código de permanencia, resistencia al seguimiento / actualización de asociaciones, comprobabilidad y consulta.
Habría un mayor nivel de acoplamiento, pero lo que estaba pensando era algo así como lo siguiente:
public class User
{
IUserDAO userDAO;
public User()
{
userDAO = IoCContainer.Resolve<IUserDAO>;
}
public User(IUserDAO userDAO)
{
this.userDAO = userDAO;
}
//DAL methods
}
Entonces, el acoplamiento debe ser mínimo y en cuanto a la capacidad de prueba, no lo veo como un problema, ya que puedo inyectar un DAO simulado en la entidad.
Gracias a Brian Hasden, estos son realmente buenos recursos, pero creo que solo quería una justificación para algo que obviamente iba a hacer. Gracias por dar la dicha justificación.
Llegué a la misma conclusión. La carga generalmente no tiene sentido en la entidad porque una vez que tienes una instancia, estás creando una nueva entidad o ya tienes una entidad cargada. He estado utilizando entidades con Guardar (crear y actualizar) y Eliminar desde hace años sin problemas. Dicho esto, generalmente es útil tener un DAO para hacer otras cosas, por lo que no se está combinando exactamente el DAO y la entidad. La mayoría de las veces para mis entidades, los métodos de Guardar y Eliminar solo llaman a los métodos de Guardar y Eliminar de DAO.
Por cierto, generalmente combino una bandera sucia con la entidad para saber cuándo se han cambiado las propiedades para que no realice llamadas innecesarias para guardar cuando la entidad no ha cambiado.
Por lo general, las entidades que realmente no hacen nada pero que contienen getters y setters para miembros privados significa que estás trabajando con un modelo de dominio anémico. Es un antipatrón que es bastante controvertido.
Puede encontrar más información al respecto en:
http://www.martinfowler.com/bliki/AnemicDomainModel.html http://wrschneider.blogspot.com/2005/01/avoiding-anemic-domain-models-with.html http://www.dotnetjunkies.com/ WebLog / richardslade / archive / 2007/03/07 / 209401.aspx
Sí, lo que está describiendo suena como un registro activo (una fila de base de datos hecha en un objeto con la lógica para persistir desde / hacia la base de datos). Es una técnica efectiva, sin dudas.
En cuanto a los posibles inconvenientes, existe un mayor acoplamiento al código de permanencia, resistencia al seguimiento / actualización de asociaciones, comprobabilidad y consulta.
Mantener la persistencia fuera de los modelos de herencia de las clases de su dominio sirve en gran medida al objetivo de escribir un código entendible y mantenible.
La persistencia es una preocupación ortogonal a las responsabilidades reales de su clase. Me di cuenta de que el enfoque heredar-de-DAO divide arbitrariamente el mundo en dos categorías de clases que, desde el punto de vista de las responsabilidades y los comportamientos, no son diferentes. De qué lado caerá una clase a menudo cambiará con el tiempo. No desea que ese cambio afecte la API de esa clase y las interacciones con otras clases.
Ejemplo: digamos que hoy, su clase de Producto utiliza un IPriceCalculator, recuperado a través de IoC. Mañana, usted decide que necesita permitir la modificación de los algoritmos por producto, por lo que su IPriceCalculator se basa en datos. Esto podría ser un cambio doloroso, especialmente si sus calculadoras de precios ya tienen una clase base que proporciona una funcionalidad importante.
Este ejemplo resalta otra consideración: heredar de una clase DAO significa que su clase de usuario ha perdido la capacidad de heredar una clase Person que puede tener comportamientos útiles. (En el mundo .NET, MarshalByRefObject es una clase base común que la gente necesita para heredar y que puede entrar en conflicto con los requisitos DAO basados en herencia.) Con la herencia única, no es ideal heredar para obtener funcionalidades que probablemente sean una preocupación aparte.