Согласно традиционному подходу или теории, ViewModel должен быть частью уровня пользовательского интерфейса. По крайней мере, название говорит об этом.
Но когда вы приступите к реализации самостоятельно с помощью Entity Framework, MVC, Repository и т. Д., Вы поймете кое-что еще.
Кто-то должен сопоставить модели Entity / DB с ViewModels (DTO упоминается в конце). Должно ли это быть сделано в [A] слое пользовательского интерфейса (контроллером) или в [B] слое сервиса?
Я выбираю вариант Б. Вариант А - нет, потому что несколько моделей сущностей объединяются вместе, образуя ViewModel. Мы не можем передавать ненужные данные на уровень пользовательского интерфейса, тогда как в варианте B служба может играть с данными и передавать только необходимое / минимум на уровень пользовательского интерфейса после сопоставления (в ViewModel).
Но все же давайте выберем вариант A, поместим ViewModel на уровень пользовательского интерфейса (и модель сущности на уровень обслуживания).
Если уровень сервиса должен быть сопоставлен с ViewModel, тогда сервисный уровень должен получить доступ к ViewModel в слое пользовательского интерфейса. Какая библиотека / проект? Viewmodel должна находиться в отдельном проекте на уровне пользовательского интерфейса, и на этот проект должна ссылаться Service Layer. Если ViewModel не находится в отдельном проекте, тогда есть циклическая ссылка, так что не пойдем. Выглядит неудобно, когда уровень сервиса обращается к слою пользовательского интерфейса, но все же мы можем с этим справиться.
Но что, если есть другое приложение пользовательского интерфейса, использующее эту службу? Что делать, если есть мобильное приложение? Чем может отличаться ViewModel? Должен ли Сервис получать доступ к тому же проекту модели представления? Все ли проекты пользовательского интерфейса будут иметь доступ к одному и тому же проекту ViewModel или у них будет собственный?
После этих размышлений я бы ответил, что проект Viewmodel будет находиться на уровне обслуживания. Каждый слой пользовательского интерфейса в любом случае должен иметь доступ к уровню сервиса! И может быть много похожих ViewModels, которые все они могли бы использовать (следовательно, отображение упрощается для уровня сервиса). В наши дни сопоставления выполняются через linq, что является еще одним плюсом.
Наконец, есть обсуждение DTO. А также об аннотации данных в ViewModels. ViewModels с аннотациями к данным (Microsoft.Web.Mvc.DataAnnotations.dll) не могут находиться на уровне сервиса, вместо этого они находятся в слое пользовательского интерфейса (но ComponentModel.DataAnnotations.dll может находиться на уровне сервиса). Если все проекты находятся в одном решении (.sln), то не имеет значения, на какой слой вы его разместите. В корпоративных приложениях для каждого уровня будет собственное решение.
Таким образом, DTO на самом деле является ViewModel, потому что в большинстве случаев между ними будет сопоставление один на один (скажем, с AutoMapper). Опять же, DTO по-прежнему имеет логику, необходимую для пользовательского интерфейса (или нескольких приложений), и находится на уровне обслуживания. А ViewModel уровня пользовательского интерфейса (если мы используем Microsoft.Web.Mvc.DataAnnotations.dll) предназначен просто для копирования данных из DTO с добавлением к ним некоторых «поведенческих» / атрибутов.
[Теперь это обсуждение станет интересным, читайте дальше ...: I]
И не думайте, что атрибуты аннотации данных предназначены только для пользовательского интерфейса. Если вы ограничиваете проверку с помощью System.ComponentModel.DataAnnotations.dll, то ту же ViewModel можно также использовать для проверки внешнего и внутреннего интерфейса (таким образом удаляя UI-residing-ViewModel-copy-of-DTO). Более того, атрибуты также могут использоваться в моделях сущностей. Например: с использованием .tt модели данных Entity Framework могут быть автоматически сгенерированы с атрибутами проверки для выполнения некоторых проверок БД, таких как максимальная длина, перед отправкой на серверную часть. Это экономит круговые пути от пользовательского интерфейса к бэкэнду для проверки. Это также позволяет серверной части повторно проверять по соображениям безопасности. Таким образом, модель - это самодостаточный валидатор, и вы можете легко ее передавать. Еще одно преимущество заключается в том, что если проверка бэкэнда изменяется в БД, тогда .tt (считывает специфику БД и создает атрибут для класса сущности) автоматически подбирает это. Это также может привести к сбою модульных тестов проверки пользовательского интерфейса, что является большим плюсом (так что мы можем исправить это и проинформировать все пользовательские интерфейсы / потребителей вместо того, чтобы случайно забыть и потерпеть неудачу). Да, обсуждение продвигается к хорошему дизайну фреймворка. Как видите, все это связано: многоуровневая проверка, стратегия модульного тестирования, стратегия кеширования и т. Д.
Хотя не имеет прямого отношения к вопросу. Упомянутый здесь «ViewModel Façade» должен смотреть ссылку на канал 9 тоже стоит изучить. Он начинается ровно в 11 минут 49 секунд ролика. Потому что это будет следующий шаг / мысль после того, как будет решен ваш текущий вопрос, данный выше: «Как организовать ViewModels?»
И, наконец, многие из этих проблем модели и логики можно решить с помощью REST. Потому что каждый клиент может обладать интеллектом, чтобы запрашивать данные и получать только те данные, которые ему нужны. И он сохраняет модель в пользовательском интерфейсе, нет модели / логики уровня сервера / сервиса. Единственное дублирование будет в автоматических тестах, которые необходимо выполнить каждому клиенту. Также, если есть изменения в данных, некоторые клиенты терпят неудачу, если они не адаптируются к изменениям. Тогда возникает вопрос, удаляете ли вы уровень обслуживания полностью (и модели, которые они несут) или подталкиваете уровень обслуживания к своему проекту пользовательского интерфейса (поэтому проблема с моделью все еще сохраняется), который вызывает REST API. Но с точки зрения ответственности уровня обслуживания они одинаковы.
Также в вашем примере «_repository.ListContacts ()» возвращает ViewModel из репозитория. Это не зрелый способ. Репозитории должны предоставлять модели сущностей или модели БД. Это преобразуется в модели представления, и именно эта модель представления возвращается уровнем сервиса.
person
Blue Clouds
schedule
04.07.2012