Actualmente estoy trabajando como desarrollador en solitario en mi proyecto actual. Heredé el proyecto de otro desarrollador, que desde entonces dejó la empresa. Es una aplicación web de estilo modelo-vista-controlador en C #. Utiliza Entity Framework para el mapeo relacional de objetos. Y hay dos conjuntos diferentes de clases para los tipos en el modelo de dominio. Un conjunto se usa para interactuar con el ORM y el otro se usa como modelo en el sistema MVC. Por ejemplo, puede haber dos clases de la siguiente manera:
public class Order{
int ID{get;set;}
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
}
y
public class OrderModel{
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
public OrderModel( Order from){
this.Customer= from.Customer;
// copy all the properties over individually
}
public Order ToOrder(){
Order result =new Order();
result.Customer = this.Customer;
// copy all the properties over individually
}
}
Puedo pensar en varios inconvenientes de este enfoque (más lugares para cambiar el código si algo cambia, más objetos sentados en la memoria, más tiempo dedicado a copiar datos), pero no estoy realmente seguro de cuáles son las ventajas aquí. ¿Más flexibilidad para las clases de modelos, supongo? Pero podría obtener eso subclasificando las clases de entidad también. Mi inclinación sería fusionar estos dos grupos de clases, o posiblemente hacer que las clases modelo sean subclases de las clases de entidad. Entonces, ¿me estoy perdiendo algo importante aquí? ¿Es este un patrón de diseño común que no conozco? ¿Hay buenas razones para no seguir con el refactor que estoy contemplando?
ACTUALIZAR
Algunas de las respuestas aquí me hacen darme cuenta de que mi descripción inicial del proyecto carecía de algunos detalles importantes. También hay un tercer grupo de clases que existen en el proyecto: las clases de modelo de página. Son los que realmente se utilizan como modelo que respalda la página. También contienen información específica de la interfaz de usuario y no se almacenarían con un pedido en la base de datos. Una clase de modelo de página de ejemplo podría ser:
public class EditOrderPagelModel
{
public OrderModel Order{get;set;}
public DateTime EarliestDeliveryDate{get;set;}
public DateTime LatestAllowedDeliveryDate{get;set;}
}
Veo totalmente que la utilidad de este tercer grupo es distinta aquí, y no tengo planes de fusionarlo con otra cosa (aunque podría cambiarle el nombre).
Las clases en el grupo de modelos también son utilizadas actualmente por la API de la aplicación, que también me interesaría escuchar comentarios sobre si es una buena idea.
También debo mencionar que el cliente que se representa como una cadena aquí fue para simplificar el ejemplo, no porque en realidad se esté representando de esa manera en el sistema. El sistema real tiene al cliente como un tipo distinto en el modelo de dominio, con sus propias propiedades.
fuente
Respuestas:
SI
Si bien estos se parecen a la misma cosa y representan la misma cosa en el dominio, no son los mismos objetos (OOP).
Uno es el
Order
conocido por la parte de almacenamiento de datos del código. El otro es elOrder
conocido por la interfaz de usuario. Si bien es una coincidencia agradable que estas clases tengan las mismas propiedades, no están garantizadas .O para verlo desde otra perspectiva, considere el Principio de responsabilidad única. El motivador clave aquí es que "una clase tiene una razón para cambiar". Especialmente cuando se trata de marcos omnipresentes como un marco ORM y / o UI, sus objetos deben estar bien aislados, ya que los cambios en el marco a menudo harán que sus entidades cambien.
Al vincular sus entidades a ambos marcos, lo está haciendo mucho peor.
fuente
El propósito del modelo de vista es proporcionar desacoplamiento de dos maneras: proporcionando datos en la forma que requiere la vista (independiente del modelo) y (especialmente en MVVM) empujando parte o la totalidad de la lógica de vista de la vista al modelo de vista.
En un modelo totalmente normalizado, el Cliente no estaría representado en el Modelo por una cadena, sino por una ID. El Modelo, si necesita el nombre del cliente, buscaría el nombre de la tabla Clientes, utilizando el CustomerID que se encuentra en la tabla Pedidos.
Un modelo de vista, por otro lado, puede estar más interesado en el
Name
del cliente, no en el ID. No necesita la ID a menos que el Cliente se actualice en el Modelo.Además, el modelo de vista puede, y generalmente lo hace, tomar una forma diferente (a menos que sea CRUD puro ). Un objeto Modelo de vista de factura puede tener nombre de cliente, direcciones y líneas de pedido, pero el modelo contiene clientes y descripciones.
En otras palabras, las facturas normalmente no se almacenan de la misma manera que se muestran.
fuente
En cierto sentido tiene razón: ambos se refieren al mismo domainobject, que se llama
order
. Pero está equivocado en la medida en que no es una duplicación real que una representación diferente, originada con diferentes propósitos. Si desea conservar su pedido, por ejemplo, desea acceder a todas y cada una de las columnas. Pero no quieres filtrar eso al exterior. Además, empujar entidades enteras a través del cable no es lo que realmente quieres. Sé de casos en los queorders
se envió una colección de MBs al cliente donde unos pocos kb serían suficientes.Para resumir, estas son las razones principales por las que desea hacer eso:
1) Encapsulación: ocultación de información de su aplicación
2) Los modelos pequeños son rápidos de serializar y fáciles de transmitir
3) Sirven para diferentes propósitos, aunque se superponen y, por lo tanto, debe haber diferentes objetos.
4) A veces tiene sentido tener para diferentes consultas diferentes objetos de valor . No sé cómo es en C #, pero en Java es posible usar un POJO para recopilar resultados. Si necesito una sola
order
, uso Order -Entity, pero si solo necesito algunas columnas llenas de cantidades en los datos, usar objetos más pequeños es más eficiente.fuente
(Descargo de responsabilidad: solo vi que se usaba de esta manera. Podría haber entendido mal el verdadero propósito de hacerlo. Trate esta respuesta con sospecha).
Aquí hay otro bit que falta: la conversión entre
Order
yOrderModel
.La
Order
clase está vinculada a su ORM, mientras queOrderModel
está vinculada al diseño de su Modelo de vista.Por lo general, los dos métodos se proporcionarán "de forma mágica" (a veces llamados DI, IoC, MVVM, o incluso otra cosa). Es decir, en lugar de implementar estos dos métodos de conversión como parte de
OrderModel
, pertenecerán a una clase dedicada a la conversión de estas cosas; esa clase se registrará de alguna manera con el marco para que el marco pueda buscarlo fácilmente.La razón para hacer esto es que cada vez que hay un cruce desde el
OrderModel
haciaOrder
o viceversa, usted sabe que algunos datos deben haberse cargado o guardado en ORM.fuente