Atualmente, estou trabalhando como desenvolvedor solo no meu projeto atual. Eu herdei o projeto de outro desenvolvedor, que deixou a empresa. É um aplicativo da web no estilo model-view-controller em C #. Ele usa o Entity Framework para mapeamento relacional de objetos. E há dois conjuntos diferentes de classes para os tipos no modelo de domínio. Um conjunto é usado para interagir com o ORM e o outro é usado como modelos no sistema MVC. Por exemplo, pode haver duas classes da seguinte maneira:
public class Order{
int ID{get;set;}
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
}
e
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
}
}
Posso pensar em várias desvantagens dessa abordagem (mais lugares para alterar o código se algo mudar, mais objetos guardados na memória, mais tempo gasto copiando dados), mas não tenho certeza de quais são as vantagens aqui. Mais flexibilidade para as classes de modelos, suponho? Mas eu poderia conseguir isso subclassificando as classes de entidade também. Minha inclinação seria mesclar esses dois grupos de classes ou, possivelmente, fazer com que as classes de modelo sejam subclasses das classes de entidade. Então, estou perdendo algo importante aqui? Esse é um padrão de design comum que não conheço? Existem boas razões para não continuar com o refator que estou pensando?
ATUALIZAR
Algumas das respostas aqui estão me fazendo perceber que minha descrição inicial do projeto carecia de alguns detalhes importantes. Também existe um terceiro grupo de classes no projeto: as classes de modelo de página. Eles são os que realmente estão sendo usados como o modelo de backup da página. Eles também contêm informações específicas da interface do usuário e não seriam armazenadas com um pedido no banco de dados. Um exemplo de classe de modelo de página pode ser:
public class EditOrderPagelModel
{
public OrderModel Order{get;set;}
public DateTime EarliestDeliveryDate{get;set;}
public DateTime LatestAllowedDeliveryDate{get;set;}
}
Vejo totalmente a utilidade desse terceiro grupo aqui distinta e não tenho planos de fundi-lo com outra coisa (embora eu possa renomeá-lo).
Atualmente, as classes no grupo de modelos também são usadas pela API do aplicativo, que eu também estaria interessado em ouvir sobre se isso é uma boa ideia.
Também devo mencionar que o cliente que está sendo representado como uma string aqui foi para simplificar o exemplo, não porque ele está sendo representado dessa maneira no sistema. O sistema real tem o cliente como um tipo distinto no modelo de domínio, com suas próprias propriedades
fonte
Respostas:
SIM
Embora pareçam a mesma coisa e representem a mesma coisa no domínio, eles não são os mesmos objetos (OOP).
Um é o
Order
conhecido pela parte do código de armazenamento de dados. O outro é oOrder
conhecido pela interface do usuário. Embora seja uma coincidência agradável que essas classes tenham as mesmas propriedades, elas não são garantidas .Ou, para examiná-lo de outra perspectiva, considere o Princípio da Responsabilidade Única. O principal motivador aqui é que "uma classe tem um motivo para mudar". Especialmente ao lidar com estruturas abrangentes, como uma estrutura ORM e / ou UI, seus objetos precisam estar bem isolados, pois as alterações na estrutura geralmente causam alterações nas entidades.
Ao vincular suas entidades às duas estruturas, você está tornando as coisas muito piores.
fonte
O objetivo do modelo de exibição é fornecer desacoplamento de duas maneiras: fornecendo dados na forma que o View exige (independente do modelo) e (especialmente no MVVM) empurrando parte ou toda a lógica do View de volta do View para o modelo de exibição.
Em um modelo totalmente normalizado, o Cliente não seria representado no Modelo por uma sequência, mas por um ID. O modelo, se precisar do nome do cliente, procuraria o nome da tabela Customers, usando o CustomerID encontrado na tabela Orders.
Um modelo de exibição, por outro lado, pode estar mais interessado no
Name
cliente, não no ID. Ele não precisa do ID, a menos que o Cliente esteja sendo atualizado no Modelo.Além disso, o View Model pode, e geralmente assume, uma forma diferente (a menos que seja puro CRUD ). Um objeto Modelo de exibição de fatura pode ter nome, endereço e itens de linha, mas o modelo contém clientes e descrições.
Em outras palavras, as faturas normalmente não são armazenadas da mesma maneira que são exibidas.
fonte
De certa forma, você está certo: os dois se referem ao mesmo objeto de domínio, chamado
order
. Mas você está errado na medida em que não é uma duplicação real do que uma representação diferente - originada de propósitos diferentes. Se você deseja manter seu pedido, por exemplo, deseja acessar todas as colunas. Mas você não quer vazar isso para o exterior. Além de empurrar entidades inteiras através do fio, não é o que você realmente deseja. Conheço casos em que uma coleção de MBsorders
foi enviada ao cliente, onde alguns kb seriam suficientes.Para resumir uma longa história - eis as principais razões pelas quais você deseja fazer isso:
1) Encapsulamento - ocultação de informações da sua aplicação
2) Os modelos pequenos são rápidos de serializar e fáceis de transmitir
3) Eles servem a propósitos diferentes, embora estejam sobrepostos, e portanto devem haver objetos diferentes.
4) Às vezes, faz sentido ter para consultas diferentes objetos de valor diferentes . Não sei como é em C #, mas em Java é possível usar um POJO para coletar resultados. Se eu precisar de um único
order
, uso o Order -Entity, mas se precisar apenas de algumas colunas preenchidas com quantidades de dados, usar Objetos menores será mais eficiente.fonte
(Isenção de responsabilidade: eu só vi sendo usada dessa maneira. Talvez eu tenha entendido mal o real objetivo de fazê-lo. Trate esta resposta com desconfiança.)
Aqui está outro bit que falta: a conversão entre
Order
eOrderModel
.A
Order
classe está vinculada ao seu ORM, enquanto aOrderModel
está vinculada ao design do seu View Model.Normalmente, os dois métodos serão fornecidos "de uma maneira mágica" (às vezes chamados DI, IoC, MVVM ou outra coisa). Ou seja, em vez de implementar esses dois métodos de conversão como parte dele
OrderModel
, eles pertencerão a uma classe dedicada à interconversão dessas coisas; essa classe será, de alguma forma, registrada na estrutura, para que ela possa ser facilmente pesquisada.O motivo para fazer isso é que sempre que houver uma passagem do
OrderModel
para oOrder
ou vice-versa, você sabe que alguns dados devem ter sido carregados ou salvos no ORM.fonte