Почему я должен изолировать объекты домена от своего уровня представления?

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

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

Итак, я ищу некоторые конкретные причины, которые я могу использовать, чтобы поддержать это. В частности:

  • Почему мы не должны использовать объекты домена в нашем слое представления?
    (если ответ является очевидным, "развязка", то, пожалуйста, объясните, почему это важно в этом контексте).
  • Должны ли мы использовать дополнительные объекты или конструкции для выделения наших доменных объектов из интерфейса?

Ответ 1

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

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

Ответ 2

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

Вместо того, чтобы загружать объект CompanyObject, который может иметь ссылки на подписки или кто знает, что еще, я мог бы отправить обратно DTO с именем и идентификатором. Это хорошее использование ИМХО.

Теперь возьмем другой пример. У меня есть объект, который представляет собой оценку, эта оценка может быть составлена ​​из-за труда, оборудования и т.д., У него может быть множество вычислений, которые определяются пользователем, которые берут все эти элементы и суммируют их (каждая оценка может отличаться от разных типов вычислений). Почему мне нужно дважды моделировать этот объект? Почему я не могу просто перечислить свой UI по вычислениям и отобразить их?

Обычно я не использую DTO, чтобы изолировать свой доменный слой от моего пользовательского интерфейса. Я использую их, чтобы изолировать свой доменный уровень от границы, находящейся вне моего контроля. Идея о том, что кто-то помещает навигационную информацию в свой бизнес-объект, смехотворна, не загрязняет ваш бизнес-объект.

Идея, что кто-то будет проверять в своем бизнес-объекте? Хорошо, я говорю, что это хорошо. Ваш пользовательский интерфейс не должен иметь единственной ответственности за проверку ваших бизнес-объектов. Уровень вашего бизнеса ДОЛЖЕН выполнять свою собственную проверку.

Почему вы добавляете код генерации пользовательского интерфейса в объект busienss? В моем случае у меня есть отдельные объекты, которые генерируют пользовательский интерфейс seperatley из пользовательского интерфейса. У меня есть спертые объекты, которые превращают мои бизнес-объекты в Xml, идея, что вы должны разделять свои слои, чтобы предотвратить такой тип заражения, настолько чуждо мне, потому что вы бы даже поместили код генерации HTML в бизнес-объект...

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

Если бы мне пришлось проектировать мои объекты, чтобы сделать их устойчивыми, должен ли я также дублировать объекты? Имейте в виду, если вы хотите добавить новое поле, у вас есть два места для его добавления. Возможно, это вызывает другой вопрос, если вы используете DDD, все объекты домена объектов сущностей? Я знаю, что в моем примере они были.

Ответ 3

Вы делаете это по той же причине, по которой вы храните SQL из своих страниц ASP/JSP.

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

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

Ответ 4

Я не согласен.

Я думаю, что лучший способ начать - это начать с объектов домена в вашем слое презентации, пока он не сделает попытку сделать другое.

Вопреки распространенному мнению, "объекты домена" и "объекты ценности" могут успешно сосуществовать на уровне презентации. И это лучший способ сделать это - вы получаете преимущество обоих миров, уменьшенное дублирование (и шаблонный код) с объектами домена; и пошив и концептуальное упрощение использования объектов ценности в запросах.

Ответ 5

Мы используем ту же модель на сервере и на ui. И это боль. Мы должны реорганизовать его когда-нибудь.

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

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

В конце концов, я думаю, что это просто вопрос, по какому пути проще. Там могут быть проекты, где он просто отлично работает и где нет необходимости писать другую модель DTO.

Ответ 6

Это касается зависимостей по большей части. Основная функциональная структура организации имеет свои функциональные требования, и пользовательский интерфейс должен позволять людям изменять и просматривать ядро; но ядро ​​не должно требоваться для размещения пользовательского интерфейса. (Если это должно произойти, это обычно указывает на то, что ядро ​​не является собственностью.)

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

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

Интерфейсы касаются входов и представлений, предоставленных для правильно смоделированного и инвариантного функционального ядра.

Ответ 7

Черт возьми, я клянусь, что это настойчивость.

В любом случае, это еще один пример того же: закон Парнаса гласит, что модуль должен хранить секрет, а секрет - это требование, которое может измениться. (У Боба Мартина есть правило, что другая версия этого.) В такой системе презентация может изменяться независимо от домена. Например, компания, которая поддерживает цены в евро и использует французский язык в офисах компании, но хочет представить цены в долларах с текстом на мандаринском. Домен тот же; презентация может измениться. Таким образом, чтобы свести к минимуму хрупкость системы, то есть количество вещей, которые необходимо изменить для реализации изменения требований, вы отделяете проблемы.

Ответ 8

Ваша презентация может ссылаться на ваш доменный уровень, но не должно быть привязки непосредственно от вашего ui к вашим объектам домена. Объекты домена не предназначены для использования пользовательского интерфейса, поскольку они часто, если они правильно разработаны, основаны на поведении, а не на представлении данных. Должен быть слой отображения между пользовательским интерфейсом и доменом. MVVM, или MVP, является хорошим примером для этого. Если вы попытаетесь напрямую привязать свой интерфейс к домену, вы, вероятно, создадите много головной боли для себя. У них есть две разные цели.

Ответ 9

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

Теперь предположим, что речевой движок для системы телефонного звонка работает на совершенно другом компьютере (например, Mac) с компьютера, на котором запущен веб-сайт (возможно, Windows).

Конечно, легко попасть в ловушку: "В моей компании мы заботимся только об английском, запустим наш сайт на LAMP (Linux, Apache, MySQL и PHP), и каждый использует ту же версию Firefox". Но как насчет через 5 или 10 лет?

Ответ 11

С помощью такого инструмента, как Value Injecter и концепция "Mappers" в слое презентации при работе с представлениями, это много более легко понять каждый фрагмент кода. Если у вас есть немного кода, вы не увидите преимуществ сразу, но когда ваш проект будет расти все больше и больше, вы будете очень счастливы, работая с представлениями, чтобы не входить в логику сервисов, репозитории, чтобы понять модель представления. View Model - еще один охранник в огромном мире антикоррупционного слоя и стоит своего веса в золоте в долгосрочном проекте.

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

Ответ 12

Вот реальный пример того, почему я считаю хорошей практикой отделить объекты домена от представления.

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

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

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

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

Ответ 13

Ответ зависит от масштаба вашего приложения.


Простое приложение CRUD (создание, чтение, обновление, удаление)

Для базовых приложений crud у вас нет никаких функций. Добавление DTO поверх сущностей будет пустой тратой времени. Это увеличит сложность без увеличения масштабируемости.

введите описание изображения здесь


Умеренно сложное приложение без CRUD

В таком размере приложения у вас будет несколько объектов, у которых есть истинный lifeclycle и некоторая бизнес-логика, связанная с ними.

Добавление DTO в этом случае является хорошей идеей по двум причинам:

  • Уровень представления может видеть только подмножество полей, которые имеет объект. Вы инкапсулируете объекты
  • Нет связи между бэкэнд и фронт.
  • Если у вас есть бизнес-методы внутри сущностей, но не в DTO, то добавление DTO означает, что внешний код не может разрушить состояние вашей сущности.

введите описание изображения здесь


Сложное корпоративное приложение

Единому объекту может потребоваться несколько способов представления. Каждому из них потребуется другой набор полей. В этом случае вы сталкиваетесь с теми же проблемами, что и в предыдущем примере, и вам нужно контролировать количество полей, видимых для каждого клиента. Наличие отдельного DTO для каждого клиента поможет вам выбрать, что должно быть видимым.

введите описание изображения здесь

Ответ 14

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

Проекты с поддержкой домена работают лучше всего при использовании в сочетании с ортогональным набором функциональных инфраструктур домена (таких как ORM, GUI, Workflow и т.д.). Всегда помните, что только во внешних смежных слоях необходимо выявить предметную семантику. Обычно это интерфейсный интерфейс (GUI) и постоянный сервер (RDBM, ORM). Любые эффективно спроектированные промежуточные слои могут и должны быть инвариантными к домену.