Являются ли сущности на стороне клиента анти-шаблоном?

Раньше я пользовался сервисом RIA, сейчас тестирую Breeze Sharp.

RIA и Breeze создают впечатление, что то, что вы видите на сервере/среднем уровне, совпадает с тем, что вы видите на клиенте. Чтобы поддержать это, термин Entity используется как на клиенте, так и на сервере. Это действительно Сущность или это действительно Модель Представления или Модель на клиенте?

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

Почему мы не можем рассматривать то, с чем имеем дело на клиенте, как модели представления, а не сущности?


person wonderful world    schedule 06.06.2014    source источник


Ответы (2)


Вы можете называть класс сущности на стороне клиента как угодно :-)

А если серьезно, давайте рассмотрим типичное обоснование утверждения, что это анти-шаблон.

Клиент не является уровнем представления

Я хочу быть очень ясным по этому поводу. Breeze разработан для многофункциональных клиентских веб-приложений. Клиент Breeze не является уровнем представления; он имеет уровень представления. Он также имеет собственную бизнес-модель и уровни доступа к данным.

Термины сущность и DTO означают разные вещи для разных людей. Мне нравится определение DDD Эвана для сущности и определение Фаулера для DTO в PoEAA.

Сущности клиента Breeze квалифицируются как сущности Эванса: Объекты, которые имеют четкую идентичность, которая проходит через время и различные представления. Вы также слышите, как они называются «эталонными объектами» [Fowler]. Сущности Breeze — это не просто сумки с имуществом; у них также есть бизнес-логика, и вы можете расширить их своими собственными.

Объекты Breeze не являются презентационными моделями. Они не зависят от какого-либо конкретного представления пользовательского интерфейса и обычно не реализуют проблемы представления.

Они разработаны таким образом, что их можно напрямую привязать к визуальным элементам управления. Это решение Breeze по проектированию производительности... решение о том, как мы реализуем объекты. Некоторым людям — людям, считающим, что свойства сущностей — это анти-шаблон, — это не понравится. Эванс молчит на этот вопрос. Фаулер это какает. Если это вас оскорбляет, вам может не понравиться Бриз. Двигайтесь вперед.

Отправить объекты или DTO?

Я собираюсь утверждать, что это ложная дихотомия.

Люди часто говорят, что отправлять объекты по сети — это антишаблон. Всегда отправлять DTO. За этим плохо сформулированным указом есть веская причина. Когда класс сущностей клиента и сервера идентичны, вы связываете реализацию сервера с реализацией клиента. Если модель изменяется на сервере, она должна измениться и на клиенте, и наоборот, даже если изменение относится только к одному из уровней. Это может помешать вам независимо развивать серверный и клиентский код. Мы можем принять такое соединение из соображений целесообразности (а целесообразность имеет значение!), но никто не хочет этого.

Класс сущности клиент Breeze не обязательно должен быть таким же, ни по форме, ни по бизнес-логике, как класс сущности сервер. Когда вы делаете запрос в Breeze, вы помещаете данные объекта в сеть и преобразуете их в клиентские объекты; при сохранении вы помещаете клиентский объект data в сеть и преобразуете его на сервере в серверные объекты. DTO могут быть вовлечены в любом направлении. Важным фактом является то, что классы могут быть разными.

Концептуально они, конечно, связаны. У вас будет чертовски много времени на преобразование данных между двумя представлениями, если значение сущности Customer сильно расходится с двух сторон. Это верно как с явными DTO, так и без них.

Давайте также признаем, что легче преобразовывать данные в обоих направлениях, когда классы на самом деле одни и те же. Вы платите налог за сопоставление, когда они отличаются, и вы можете потерять возможность составлять запросы Breeze LINQ на клиенте. Вы можете заплатить налог, если хотите. Бризу все равно.

Я склоняюсь к тому, чтобы начать с одинаковых классов с обеих сторон и менять их по мере необходимости. Это хорошо сработало для большого процента классов RIA Services и DevForce. Самое главное, мне никогда не было сложно провести рефакторинг для разделения классов, когда в этом возникала необходимость.

‹rant› Беспокойные преувеличивают риски совместного использования определений классов и преуменьшают стоимость сопоставления слоев, преимущества которых редко реализуются на практике в течение всего срока службы приложения.‹/rant› >

Когда использовать презентационные модели

Вы написали:

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

По моему опыту, это верно только в том случае, если вы предполагаете, что ваш клиент просто вставляет объекты на экран. Но я уже оговорил, что клиент — это приложение, а не уровень представления.

Я также утверждаю, что вам нужна модель домена на клиенте по той же причине, что и на сервере: чтобы рассуждать о домене. Вы делаете это независимо от презентации. Я предполагаю, что ваши объекты будут появляться на нескольких экранах в зависимости от разных правил представления. Это одна и та же модель, представленная многими способами. Мы называем это обходом данных.

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

FWIW, у меня всегда есть модель представления (также известная как ViewModel) в моих приложениях для организации действий представления. Так что я не спрашиваю себя PM или модель?. Вместо этого я выбираю либо, чтобы данные привязывали визуальные элементы управления непосредственно к объектам модели, которые я предоставляю через API виртуальной машины или вместо этого привязываю их к промежуточной модели представления элементов (также известной как Item ViewModel) который оборачивает некоторые объекты. Каким путем я пойду, зависит от приложения. На практике я начинаю с прямой привязки к сущностям и рефакторинга к Item ViewModel, когда это необходимо.

В любом случае я создам нужные мне PM (VM) на клиенте. Если мне нужна Item ViewModel, я также создаю ее на клиенте. Я не прошу свой сервер подготовить DTO для отображения моего клиента. Для меня это анти-шаблон, потому что он связывает сервер с клиентом.

Как? Если разработчику нужно изменить экран на клиенте, ему, возможно, придется подождать, пока кто-нибудь предоставит конечную точку поддерживающего сервера и DTO. Теперь нам нужно согласовать графики выпуска сервера и клиента, даже несмотря на то, что толчком к изменению было требование клиента, а не требование сервера.

Сервисное загрязнение

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

В конце концов мы забываем, кто использует какой метод и для чего. Никто не осмеливается изменить существующий метод, опасаясь взлома неизвестного клиента. Итак, разработчик копирует что-то, что выглядит правильно, делает это немного по-другому и называет это как-то иначе. Эта модель загрязнения сервисного API должна быть знакома всем, кто работал с корпоративными приложениями.

Делать исключения

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

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

Надеюсь это поможет.

person Ward    schedule 09.06.2014
comment
Спасибо Уорд за ответ. - person wonderful world; 13.06.2014

Я не знаю, нравится ли мне идея иметь другую модель предметной области на клиенте. Это приведет к легендарной проблеме, над которой мы все боролись годами, — передаче бизнес-логики клиенту. Я имею в виду внешний интерфейс, такой как Windows Forms, приложение XAML или HTML5, при условии, что приложение подключено к серверу. Разве это не удобно, если сущности существуют только на уровне домена на сервере и защищены службой приложений?

Насколько я понял из учебников по DDD, когда модель представляет собой сущность, у нее есть поведение и данные. Модель представления касается только представления объектов предметной области, которые находятся на сервере. Для этих моделей есть валидация. Это может быть просто, так как электронная почта требуется для проверки бизнес-правил. Когда клиент имеет дело со сложными проверками бизнес-правил, он может использовать те же правила, которые были реализованы на уровне предметной области. Преимущество таких фреймворков, как RIA, заключается в том, что эти бизнес-правила доступны клиенту, что позволяет избежать дублирования. Это также заставит одни и те же сущности передаваться клиенту.

Я поддерживаю идею о том, что модели клиента и сервера должны расти отдельно — модель на клиенте и объекты домена на сервере. Затраченные затраты включают перевод моделей, сервис приложений для блотинга, циклические обращения для проверки сложности бизнес-правил. Вы упомянули о некоторых из них в своем ответе.

person wonderful world    schedule 13.06.2014
comment
Привет. В этих учебниках не рассматривается, что означает DDD для многофункционального распределенного клиентского приложения, в котором многоуровневая модель представления/предметной области повторяется, хотя и не обязательно с точно такими же правилами. Нет проблем с тем, что ваши модели сервера и клиента растут отдельно, при этом совместно используется логика (если не код) по мере необходимости. - person Ward; 27.06.2014