Почему это не хорошая идея передать объекты как Модели в MVC?

Мы разрабатываем довольно крупное приложение с MVC 2 RC2, и мы получили некоторую обратную связь на способе, которым мы используем Ленивую Загрузку Платформы Объекта.

Мы просто получаем объекты в контроллере и отправляем их как модели к Представлениям, который вызывает это, код представления просит у Базы данных свойства навигации, которые мы используем в нем. Мы читали об этом, и это появляется, не хороший дизайн, но мы задавались вопросом почему?

Можно ли помочь нам понять эту проблему проектирования?

Спасибо!

14
задан sabanito 24 February 2010 в 23:41
поделиться

4 ответа

Основная проблема здесь - связь. Идея модели , которая обозначается буквой «M» в «MVC», заключается в том, что она не имеет внешних зависимостей. Это «ядро» вашего приложения. Дерево зависимостей хорошо спроектированной архитектуры приложения должно выглядеть примерно так:

                       +---------------------------------------> Views
                       |                                           |
                       |                                           |
                       |                                           v
                  Controllers ----+-> Model Transformer -----> View Model
                       |           \         |
                       |            \        |
                       v             \       v
Data Access <---- Persistence --------> Domain Model
                       |             /
                       |            /
                       v           /
                     Mapper ------+

Теперь я понимаю, что не совсем убедительно просто сказать «вот архитектура, это то, что вы должны использовать», поэтому позвольте мне объяснить, что здесь происходит:

  1. Контроллер получает запрос.
  2. Контроллер обращается к некоему уровню сохраняемости (т.е. репозиторию).
  3. Уровень сохраняемости извлекает данные, а затем использует преобразователь для сопоставления с моделью предметной области.
  4. Контроллер использует преобразователь для преобразования модели предметной области в модель представления.
  5. Контроллер выбирает необходимое представление и применяет к нему модель представления.

Так чем же это хорошо?

  • Модель предметной области не имеет зависимостей . Это очень хорошо, это означает, что легко выполнять проверку, писать тесты и т. Д. Это означает, что вы можете изменить что-либо еще в любом месте вашей архитектуры, и это никогда не нарушит модель. Это означает, что вы можете повторно использовать модель в разных проектах.

  • Уровень сохраняемости возвращает экземпляры модели предметной области . Это означает, что его можно смоделировать как полностью абстрактный, платформенно-независимый интерфейс.Компонент, который должен использовать уровень сохраняемости (например, контроллер), не принимает никаких дополнительных зависимостей. Это идеально подходит для внедрения зависимостей на уровне персистентности и, опять же, тестируемости. Комбинация постоянства, доступа к данным и средства отображения может находиться в отдельной сборке. В более крупных проектах вы даже можете дополнительно отделить преобразователь и заставить его работать с общим набором записей.

  • Контроллер имеет только две нисходящие зависимости - модель предметной области и уровень сохраняемости. Модель должна редко меняться, поскольку это ваша бизнес-модель, а поскольку уровень сохраняемости является абстрактным, контроллер почти никогда не нужно менять (кроме добавления новых действий).

  • Представления зависят от отдельной модели пользовательского интерфейса. Это изолирует их от изменений в модели предметной области. Это означает, что если ваша бизнес-логика изменится, вам не нужно менять каждое представление в вашем проекте. Это позволяет представлениям быть «тупыми», какими они должны быть - они не более чем заполнители для данных представления. Это также означает, что должно быть просто воссоздать представление с использованием другого типа пользовательского интерфейса, например интеллектуального клиентского приложения, или переключиться на другой механизм представления (Spark, NHaml и т. Д.)


Теперь при использовании O / R Такие программы преобразования, как Linq to SQL или Entity Framework, очень соблазняют рассматривать генерируемые ими классы как модель предметной области. Конечно, выглядит как модель предметной области, но это не так. Почему?

  • Классы сущностей привязаны к вашей реляционной модели, которая со временем может и будет значительно отличаться от вашей модели предметной области;

  • Классы сущностей глупы.Сложно поддерживать какие-либо сложные сценарии проверки или интегрировать какие-либо бизнес-правила. Это называется моделью анемической области .

  • Классы сущностей имеют скрытые зависимости. Хотя они могут показаться обычными POCO, на самом деле они могут иметь скрытые ссылки на базу данных (т.е. ленивую загрузку ассоциаций). Это может привести к тому, что проблемы, связанные с базой данных, перейдут в логику представления, где вы меньше всего сможете правильно анализировать происходящее и отлаживать.

  • Но, что наиболее важно, «модель предметной области» больше не является независимой. Он не может существовать вне какой-либо сборки, имеющей логику доступа к данным. Что ж, это вроде как может, есть способы сделать это, если вы действительно над этим работаете, но большинство людей так не делают, и даже если вы это сделаете, вы обнаружите, что реальный дизайн модели предметной области ограничены вашей реляционной моделью и, в частности, тем, как ведет себя EF. Суть в том, что если вы решите изменить свою модель устойчивости, вы нарушите модель предметной области, а ваша модель предметной области станет основой почти для всего всего остального в вашем приложении.

Классы Entity Framework не модель предметной области. Они являются частью реляционной модели данных и имеют те же или похожие имена, которые вы можете дать классам в модели предметной области. Но с точки зрения управления зависимостями они совершенно разные.Использование классов, созданных с помощью инструмента ORM, в качестве модели предметной области может привести только к чрезвычайно хрупкой архитектуре / дизайну; каждое изменение, которое вы вносите в почти любую часть приложения, будет иметь множество предсказуемых и непредсказуемых каскадных эффектов.

Многие люди, кажется, думают, что вам не нужна связная, независимая модель предметной области. Обычно оправдание состоит в том, что (а) это небольшой проект и / или (б) их модель предметной области на самом деле не имеет никакого поведения. Но небольшие проекты становятся большими, а бизнес-правила становятся (намного) более сложными, а анемичная или несуществующая модель предметной области - это не то, от чего можно просто отказаться.

Фактически, это самая коварная черта дизайна сущностей как модели; кажется какое-то время нормально работает. Вы не узнаете, насколько это большая ошибка, до тех пор, пока через год или два вы не утонете в отчетах о дефектах и ​​запросах на изменение, отчаянно пытаясь по частям собрать реальную модель предметной области.

22
ответ дан 1 December 2019 в 09:32
поделиться

Одна потенциальная проблема с этим дизайном заключается в том, что представление может повторять итерацию по объектам модели (которые загружаются с отложенной загрузкой) более одного раза и вызывать ненужные накладные расходы. Например, если веб-страница отображает одни и те же данные в двух разных формах в паре разных мест на странице, она дважды перебирает запрос и вызывает два обращения к базе данных (посмотрите на теги под вопросом и на боковой панели на этой странице и предположим, что они пришли из одного запроса). Представление могло бы справиться с этой проблемой, кэшируя результаты один раз и дважды повторяя кэшированные данные, но это не то, с чем должно иметь дело представление. Он должен предоставлять данные, не беспокоясь об этом.

2
ответ дан 1 December 2019 в 09:32
поделиться

Проблема в том, что ваш пользовательский интерфейс больше привязан к вашей сущности, чем это необходимо.

Если ваша сущность инкапсулирована ViewModel, то ваш пользовательский интерфейс может не только содержать сущность (данные, которые он хочет в конечном итоге сохранить), но также может добавлять дополнительные поля и дополнительные данные, которые могут использоваться контроллером для создания решения и использоваться View для управления отображением. Чтобы передавать одни и те же данные за пределы ViewModel, вам потребуется использовать параметры метода действия и конструкции ViewData, которые не масштабируются, особенно для сложных ViewModel.

2
ответ дан 1 December 2019 в 09:32
поделиться

Взгляд глуп и невежественен. Он не должен и не хочет ничего знать. Оно очень поверхностно и сосредоточено только на показе. Это хорошо, поскольку представление делает то, что у него получается лучше всего.

Делая это по-своему, вы сливаете то, что должно быть заботой о данных, представлению, и более того, вы ограничиваете представление только получением данных от вашей сущности как сильно типизированной модели.

Более того, вы позволяете зависимости от EF пройти весь путь до представления и проникнуть в ваше приложение, где вы должны стараться быть настолько слабо связанными с этой зависимостью, насколько это возможно.

2
ответ дан 1 December 2019 в 09:32
поделиться
Другие вопросы по тегам:

Похожие вопросы: