В настоящее время я работаю сольным разработчиком над моим текущим проектом. Я унаследовал проект от другого разработчика, который с тех пор покинул компанию. Это веб-приложение в стиле модель-вид-контроллер в C #. Он использует Entity Framework для реляционного отображения объектов. И есть два разных набора классов для типов в модели предметной области. Один набор используется для взаимодействия с ORM, а другой используется в качестве моделей в системе MVC. Например, может быть два класса следующим образом:
public class Order{
int ID{get;set;}
String Customer{get;set;}
DateTime DeliveryDate{get;set;}
String Description{get;set;}
}
а также
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
}
}
Я могу вспомнить несколько недостатков этого подхода (больше мест для изменения кода, если что-то меняется, больше объектов, сидящих в памяти, больше времени, затрачиваемого на копирование данных), но я не совсем уверен, какие здесь преимущества. Полагаю, больше гибкости для модельных классов? Но я мог бы получить это, создав подклассы классов сущностей. Я бы хотел объединить эти две группы классов или, возможно, чтобы классы моделей были подклассами классов сущностей. Так я что-то упустил здесь? Это общий шаблон дизайна, о котором я не знаю? Есть ли веские причины не доводить до конца рефакторинг, который я рассматриваю?
ОБНОВИТЬ
Некоторые ответы здесь заставляют меня понять, что в моем первоначальном описании проекта отсутствовали некоторые важные детали. Существует также третья группа классов, которые существуют в проекте: классы модели страницы. Они - те, которые фактически используются в качестве модели, поддерживающей страницу. Они также содержат информацию, относящуюся к пользовательскому интерфейсу, и не будут храниться с заказом в базе данных. Примером класса модели страницы может быть:
public class EditOrderPagelModel
{
public OrderModel Order{get;set;}
public DateTime EarliestDeliveryDate{get;set;}
public DateTime LatestAllowedDeliveryDate{get;set;}
}
Я полностью вижу полезность этой третьей группы здесь, и у меня нет планов объединять ее с чем-то другим (хотя я мог бы переименовать ее).
Классы в группе моделей также в настоящее время используются API-интерфейсом приложения, и мне также было бы интересно узнать, является ли это хорошей идеей.
Я должен также упомянуть, что клиент, представленный здесь в виде строки, должен был упростить пример, а не потому, что он действительно представлен таким образом в системе. Фактическая система имеет клиента как отдельный тип в модели предметной области со своими собственными свойствами.
источник
Ответы:
ДА
Хотя они выглядят одинаково и представляют одно и то же в домене, они не являются одинаковыми (ООП) объектами.
Один из них
Order
известен как часть кода, предназначенная для хранения данных. Другой,Order
как известно UI. Хотя это приятное совпадение, что эти классы имеют одинаковые свойства, они не гарантированы .Или взглянуть на это с другой точки зрения, рассмотрим принцип единой ответственности. Ключевым мотиватором здесь является то, что «у класса есть одна причина для изменения». Особенно при работе с распространяющимися инфраструктурами, такими как ORM и / или инфраструктура пользовательского интерфейса, ваши объекты должны быть хорошо изолированы, поскольку изменения в структуре часто приводят к изменению ваших сущностей.
Связывая ваши сущности с обеими структурами, вы делаете это намного хуже.
источник
Цель модели представления состоит в том, чтобы обеспечить разделение двумя способами: предоставляя данные в форме, которая требуется представлению (независимо от модели), и (особенно в MVVM), отодвигая часть или всю логику представления назад из представления. к модели просмотра.
В полностью нормализованной модели Customer будет представлен в модели не строкой, а идентификатором. Модель, если ей нужно имя клиента, будет искать имя из таблицы Customers, используя CustomerID, найденный в таблице Orders.
Модель представления, с другой стороны, может больше интересоваться
Name
клиентом, а не идентификатором. Идентификатор не нужен, если только Клиент не обновляется в Модели.Кроме того, модель представления может и обычно принимает другую форму (если это не чистый CRUD ). Объект Invoice View Model может иметь имя клиента, адреса и позиции, но модель содержит клиентов и описания.
Другими словами, счета-фактуры обычно хранятся не так, как они отображаются.
источник
В некотором отношении вы правы: они оба ссылаются на один и тот же предметный объект, который называется
order
. Но вы ошибаетесь в том, что это не реальное дублирование, а другое представление, исходящее из разных целей. Если вы хотите сохранить свой заказ, вы, например, хотите получить доступ к каждому столбцу. Но вы не хотите просочиться наружу. Кроме того, проталкивать целые сущности через провод - это не то, что вам действительно нужно. Мне известны случаи, когда клиентуorders
отправлялась коллекция из МБ, где было бы достаточно нескольких КБ .Короче говоря, вот основные причины, по которым вы хотите это сделать:
1) Инкапсуляция - скрытие информации вашего приложения
2) Малые модели быстро сериализуются и легко передаются
3) Они служат разным целям, хотя они частично совпадают, и поэтому должны быть разные объекты.
4) Иногда имеет смысл иметь для разных запросов разные объекты-значения . Я не знаю, как это в C #, но в Java можно использовать POJO для сбора результатов. Если мне нужно одно,
order
я использую Order -Entity, но если мне нужны только столбцы, заполненные данными, использование меньших объектов более эффективно.источник
(Отказ от ответственности: я только видел, как он используется таким образом. Возможно, я неправильно понял истинную цель этого. Относитесь к этому ответу с подозрением.)
Вот еще один недостающий бит: преобразование между
Order
иOrderModel
.Order
Класс привязан к вашему ОРМ, в то время какOrderModel
привязан к дизайну вашего вида модели.Как правило, эти два метода будут предоставлены «волшебным образом» (иногда называемые DI, IoC, MVVM или еще чем-то другим). То есть вместо того, чтобы реализовывать эти два метода преобразования как часть
OrderModel
, они будут принадлежать классу, предназначенному для взаимного преобразования этих вещей; этот класс будет каким-то образом зарегистрирован в фреймворке, чтобы фреймворк мог легко его найти.Причина этого в том , что всякий раз , когда есть переход от
OrderModel
к ,Order
или наоборот, вы знаете , что некоторые данные должны быть загружены из или сохранены в ОРМ.источник