Основной проблемой здесь является сцепление. Идея модели , обозначающей букву «M» в «MVC», заключается в том, что она не имеет внешних зависимостей. Это «ядро» вашего приложения. Дерево зависимостей хорошо спроектированной архитектуры приложения должно выглядеть примерно так:
+---------------------------------------> Views
| |
| |
| v
Controllers ----+-> Model Transformer -----> View Model
| \ |
| \ |
v \ v
Data Access <---- Persistence --------> Domain Model
| /
| /
v /
Mapper ------+
Теперь я понимаю, что не совсем убедительно просто сказать «вот архитектура, это то, что вы должны использовать», поэтому позвольте мне объяснить, что здесь происходит:
- Контроллер получает запрос.
- Контроллер вызывает какой-то постоянный уровень (то есть хранилище).
- Слой постоянства извлекает данные, а затем использует сопоставитель для сопоставления с моделью домена.
- Контроллер использует преобразователь для преобразования модели предметной области в модель представления.
- Контроллер выбирает необходимый вид и применяет к нему модель вида.
Итак, почему это хорошо?
Модель домена не имеет никаких зависимостей . Это очень хорошая вещь, это означает, что легко выполнять валидацию, писать тесты и т. Д. Это означает, что вы можете изменить что-либо еще в вашей архитектуре, и это никогда не нарушит модель. Это означает, что вы можете повторно использовать модель в разных проектах.
Постоянный уровень возвращает экземпляры модели домена . Это означает, что его можно смоделировать как полностью абстрактный, независимый от платформы интерфейс. Компонент, который должен использовать постоянный уровень (например, контроллер), не принимает никаких дополнительных зависимостей. Это идеально подходит для внедрения зависимостей в слой постоянства и, опять же, в тестируемость. Комбинация постоянства, доступа к данным и картографа может существовать в своей собственной сборке. В более крупных проектах вы даже сможете дополнительно отделить маппер и заставить его работать с общим набором записей.
Контроллер имеет только две нижестоящие зависимости - модель домена и уровень персистентности. Модель должна меняться редко, так как это ваша бизнес-модель, и поскольку уровень постоянства является абстрактным, контроллер почти никогда не нужно менять (кроме добавления новых действий).
Представления зависят от отдельной модели пользовательского интерфейса. Это изолирует их от изменений в доменной модели. Это означает, что если ваша бизнес-логика меняется, вам не нужно менять каждое представление в вашем проекте. Это позволяет представлениям быть "тупыми", как и должно быть представлениями - они не намного больше, чем заполнители для данных представления. Это также означает, что должно быть просто воссоздать представление с использованием пользовательского интерфейса другого типа, то есть приложения интеллектуального клиента, или переключиться на другой механизм представления (Spark, NHaml и т. Д.)
Теперь, при использовании O / R Mappers, таких как Linq to SQL или Entity Framework, очень заманчиво рассматривать классы, которые они генерируют, как модель вашего домена. Это, конечно, выглядит как модель домена, но это не так. Почему?
Классы сущностей привязаны к вашей реляционной модели, которая со временем может и будет значительно отличаться от вашей доменной модели;
Классы сущностей глупы. Трудно поддерживать какие-либо сложные сценарии проверки или интегрировать какие-либо бизнес-правила. Это называется модель анемичной области .
Классы сущностей имеют скрытые зависимости. Хотя они могут казаться обычными POCO, на самом деле они могут иметь скрытые ссылки на базу данных (т.е. ленивая загрузка ассоциаций). Это может привести к возникновению проблем, связанных с базой данных, к логике представления, где вы меньше всего сможете правильно проанализировать происходящее и отладить.
Но самое главное, «модель предметной области» больше не является независимой. Она не может существовать вне какой-либо сборки, имеющей логику доступа к данным. Ну, это как-то может, есть способы пойти на это, если вы действительно работаете над этим, но большинство людей так не делают, и даже если вы это сделаете, вы обнаружите, что фактический дизайн модели предметной области ограничены вашей реляционной моделью и, в частности, поведением EF. Суть в том, что если вы решите изменить свою модель персистентности, вы сломаете модель домена, и ваша модель домена станет основой для всего всего остального в вашем приложении.
Классы Entity Framework являются , а не моделью домена. Они являются частью реляционной модели данных и имеют те же или похожие имена, которые вы можете дать классам в модели предметной области. Но это разные миры с точки зрения управления зависимостями. Использование классов, сгенерированных из инструмента ORM, в качестве модели вашего домена может привести только к чрезвычайно хрупкой архитектуре / дизайну; Каждое изменение, которое вы вносите в почти любую часть приложения, будет иметь множество предсказуемых и непредсказуемых каскадных эффектов.
Многие люди считают, что вам не нужна сплоченная, независимая модель предметной области. Обычно оправданием является то, что (а) это небольшой проект, и / или (б) их модель предметной области на самом деле не имеет никакого поведения. Но небольшие проекты становятся большими, и бизнес-правила становятся (намного) более сложными, и анемичная или несуществующая модель предметной области - это не то, что вы можете просто реорганизовать.
Это на самом деле самая коварная черта дизайна сущностей как модель; кажется, на некоторое время нормально работает . Вы не узнаете, какая это большая ошибка, до тех пор, пока через год или два вы не утонете в сообщениях о дефектах и запросах на изменения, отчаянно пытаясь собрать реальную модель предметной области.