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