Чому я повинен ізолювати свої сутності домену від мого рівня презентації?


85

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

Вони використовують сутності домену, де завгодно, на рівнях презентації та інтерфейсу. Коли я сперечаюся з ними про те, що вони повинні використовувати моделі відображення або DTO, щоб ізолювати рівень Домену від рівня інтерфейсу, вони заперечують, що не бачать цінність бізнесу в тому, щоб робити щось подібне, тому що тепер у вас є об'єкт інтерфейсу, який потрібно підтримувати а також оригінальний об'єкт домену.

Тому я шукаю деякі конкретні причини, якими я можу це підтвердити. Зокрема:

  1. Чому б нам не використовувати об'єкти домену в нашому презентаційному рівні?
    (якщо відповідь очевидна, "роз'єднання", поясніть, будь ласка, чому це важливо в цьому контексті)
  2. Чи слід використовувати додаткові об'єкти або конструкції для ізоляції об'єктів домену від інтерфейсу?

це питання має бути у вікі.
Сайєд Тайяб Алі,

@ m4bwav - Це має бути вікі, оскільки вона сформульована таким чином, щоб викликати дискусію, а не одну правильну відповідь.
Роб Аллен

1
@ m4bwav: Я думаю, що ваше запитання вийшло більше як частина думки, ніж як справжнє питання ... Я намагався це виправити (можливо, ви хочете змінити його далі), але майте на увазі, що без належного догляду це може здатися бути тролінгом.
Shog9

5
Гаразд, резервне копіювання, я задаю законне запитання, як це когось образить? На кого я націлююся?
Марк Роджерс

@ m4bwav: ти націлений на свого солом'яного чоловіка. "Велика кількість людей", з якими ви обговорюєте це у своєму питанні.
Shog9

Відповіді:


48

Причиною є просто впровадження та дрейф. Так, ваш рівень презентації повинен знати про ваші бізнес-об’єкти, щоб мати можливість їх правильно представляти. Так, спочатку здається, що між реалізацією двох типів об’єктів є багато перекриттів. Проблема полягає в тому, що з плином часу все додається з обох сторін. Зміни презентації та потреби рівня презентації еволюціонують, включаючи речі, які повністю не залежать від вашого ділового рівня (наприклад, колір). Тим часом об’єкти вашого домену змінюються з часом, і якщо у вас немає належного роз’єднання з інтерфейсом, ви ризикуєте зіпсувати свій шар інтерфейсу, вносячи, здавалося б, доброякісні зміни у свої бізнес-об’єкти.

Особисто я вважаю, що найкращий спосіб підійти до речей - це суворо дотримувана парадигма інтерфейсу; тобто рівень вашого бізнес-об’єкта надає інтерфейс, який є єдиним способом спілкування; ніяких деталей реалізації (тобто об’єктів домену) щодо інтерфейсу не виставляється. Так, це означає, що вам потрібно реалізувати об’єкти домену в двох місцях; на рівні інтерфейсу та на рівні BO. Але така реалізація, хоча спочатку може здатися додатковою роботою, допомагає забезпечити розв’язування, що дозволить заощадити ТОНИ роботи в певний момент у майбутньому.


2
Що ви маєте на увазі під "реалізацією об'єктів домену в двох місцях?"
jlembke

10
Мені це просто здається безглуздим. Чому зайва робота зараз, МОЖЕ заощадити роботу в майбутньому? 9 разів із 10 вам ніколи не потрібно буде вносити зміни, які б заощадили "ТОНИ" роботи.
звуковий сигнал

13
@LuckyLindy: 99 разів із 100 (насправді більше), пристібання ременя безпеки не потрібно, щоб не отримати травму. Однак в одному випадку, коли мені це дійсно потрібно, це (швидше за все) не дозволить мені загинути чи отримати серйозні травми. Унція профілактики коштує фунт лікування. Я підозрюю, що ваша думка щодо цього зміниться після того, як у вас буде більше досвіду.
Paul Sonier

19

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

Ну замість того, щоб завантажувати CompanyObject, який міг би мати посилання на підписки або хто знає що ще, я міг би надіслати DTO з іменем та ідентифікатором. Це хороше використання IMHO.

Тепер візьмемо інший приклад. У мене є об'єкт, який представляє оцінку, ця оцінка може складатись із робочої сили, обладнання тощо, вона може мати багато розрахунків, які визначає користувач, які беруть усі ці елементи та підсумовують їх (кожна оцінка може бути різною для різних типів розрахунків). Чому я повинен моделювати цей об'єкт двічі? Чому я не можу просто зробити так, щоб мій інтерфейс перелічував обчислення та відображав їх?

Як правило, я не використовую DTO для ізоляції шару домену від мого інтерфейсу. Я використовую їх, щоб ізолювати мій рівень домену від межі, яка знаходиться поза моїм контролем. Думка, що хтось міститиме навігаційну інформацію у своєму бізнес-об’єкті, смішна, не забруднюйте об’єкт вашого бізнесу.

Ідея, що хтось поставить перевірку у свій бізнес-об’єкт? Ну, я кажу, що це добре. Ваш інтерфейс користувача не повинен відповідати виключно для перевірки ваших бізнес-об'єктів. Ваш рівень бізнесу ПОВИНЕН зробити власну перевірку.

Чому б ви розміщували код генерації інтерфейсу користувача в об'єкті бізнесу? У моєму випадку у мене є окремі об'єкти, які генерують код інтерфейсу окремо від інтерфейсу. У мене є спеціальні об'єкти, які перетворюють мої бізнес-об'єкти на Xml, ідея про те, що вам потрібно розділити свої шари, щоб запобігти подібному забрудненню, для мене настільки чужа, бо навіщо вам навіть розміщувати код генерації HTML у бізнес-об'єкті ...

Редагувати Як я думаю трохи більше, є випадки, коли інформація про інтерфейс може належати до рівня домену. І це може затьмарити те, що ви називаєте доменним рівнем, але я працював над додатком із декількома клієнтами, який мав дуже різну поведінку як зовнішнього вигляду інтерфейсу, так і функціонального робочого процесу. Залежно від різних факторів. У цьому випадку у нас була модель домену, яка представляла орендарів та їх конфігурацію. Їхня конфігурація включала інформацію про інтерфейс користувача (наприклад, мітки для загальних полів).

Якщо мені довелося проектувати свої об’єкти, щоб зробити їх стійкими, чи повинен я також дублювати об’єкти? Майте на увазі, якщо ви хочете додати нове поле, тепер у вас є два місця для його додавання. Можливо, це піднімає ще одне запитання, чи використовуєте ви DDD, чи всі об'єкти домену зберігаються? Я знаю, що на моєму прикладі вони були.


Хіба не мітки, що відрізняються для різних орендарів, не позначають різну всюдисущу мову для кожного орендаря? Я думаю, що повинна існувати концепція метамоделі, де домен ділиться між орендарями з шаром перекладу для їх інтерпретації метамоделі.
Келл

16

Ви робите це з тієї самої причини, через яку не дозволяєте SQL знаходитись на сторінках ASP / JSP.

Якщо ви зберігаєте лише один об’єкт домену для використання в презентації І доменному рівні, то цей об’єкт незабаром стає монолітним. Він починає включати код перевірки інтерфейсу користувача, навігаційний код інтерфейсу користувача та код генерації інтерфейсу користувача. Потім ви незабаром додасте всі методи бізнес-рівня на додачу до цього. Тепер ваш бізнес-рівень та користувальницький інтерфейс змішані, і всі вони псуються на рівні сутності домену.

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


13

Я не погоджуюсь.

Я думаю, що найкращий спосіб - це почати з об’єктів домену у вашому презентаційному шарі, поки не буде сенсом робити інакше.

Всупереч поширеній думці, "доменні об'єкти" та "об'єкти цінності" можуть щасливо співіснувати на рівні презентації. І це найкращий спосіб зробити це - ви отримуєте переваги обох світів, зменшуєте дублювання (і шаблонний код) з об’єктами домену; та адаптація та концептуальне спрощення використання об’єктів вартості для запитів.


Дякую за ваш внесок, я бачу, звідки ви беретесь. Хоча я не кажу, що це не ще один з нескінченних способів створити успішний проект, схоже, це суперечить стилю "Управління доменом", який стосується великих і складних проектів, які важче підтримувати в довгостроковій перспективі.
Марк Роджерс

Ні, це неправильно, і саме тому стільки сайтів в кінцевому підсумку вразливі до введення sql.
Ремі

7

Відповідь залежить від масштабу вашої заявки.


Проста програма CRUD (Створення, читання, оновлення, видалення)

Для основних сирих програм ви не маєте жодних функціональних можливостей. Додавання DTO поверх об'єктів було б марною тратою часу. Це збільшить складність без збільшення масштабованості.

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


Помірно складний додаток Non-CRUD

У цьому розмірі програми у вас буде мало сутностей, які мають справжній життєвий цикл та певну ділову логіку, пов’язану з ними.

Додавання DTO у цьому випадку є гарною ідеєю з кількох причин:

  • Презентаційний рівень може бачити лише підмножину полів, які має сутність. Ви інкапсулюєте сутності
  • Немає зв'язку між серверною базою та фронтентом
  • Якщо у вас є бізнес-методи всередині сутностей, але не в DTO, тоді додавання DTO означає, що зовнішній код не може зруйнувати стан вашої сутності.

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


Складний корпоративний додаток

Одному суб’єкту може знадобитися кілька способів представлення. Кожному з них знадобиться різний набір полів. У цьому випадку ви стикаєтесь з тими ж проблемами, що і в попередньому прикладі, плюс потрібно контролювати кількість полів, видимих ​​для кожного клієнта. Окремий DTO для кожного клієнта допоможе вам вибрати те, що повинно бути видимим.

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


4

Ми використовуємо одну і ту ж модель на сервері та в інтерфейсі користувача. І це біль. Ми мусимо його реконструювати колись.

Проблеми в основному тому, що модель домену потрібно розрізати на менші частини, щоб мати можливість серіалізувати її, не маючи посилань на всю базу даних. Це ускладнює використання на сервері. Важливі посилання відсутні. Деякі типи також не можна серіалізувати і не можуть бути надіслані клієнту. Наприклад, "Тип" або будь-який загальний клас. Вони не повинні бути загальними, а Type потрібно передавати як рядок. Це генерує додаткові властивості для серіалізації, вони є зайвими і заплутаними.

Інша проблема полягає в тому, що сутності в інтерфейсі не дуже підходять. Ми використовуємо прив'язку даних, і багато сутностей мають безліч зайвих властивостей лише для цілей інтерфейсу користувача. Крім того, в суттєвій моделі є багато "BrowsableAttribute" та інші. Це справді погано.

Зрештою, я думаю, що справа лише в тому, який шлях простіший. Можуть існувати проекти, де це просто чудово працює і де немає необхідності писати іншу модель DTO.


2
Якщо ви збираєтеся використовувати прив'язку даних, запустіть запит linq і прив'яжіть до анонімного типу. Це дозволяє вам вирівняти і змінити ірархію. Ви також можете дуже добре реалізувати фільтрування та сортування.
JoshBerke

@Josh: Дякую за пораду. Це може частково спрацювати. Я сам не програміст графічного інтерфейсу і не надто беру участь у концепціях графічного інтерфейсу. Проблема буде у випадках, коли даними маніпулюють і надсилають назад на сервер.
Стефан Штайнеггер,

3

Йдеться про залежності здебільшого. Основна функціональна структура організації має свої функціональні вимоги, і користувальницький інтерфейс повинен дозволяти людям змінювати та переглядати ядро; але саме ядро ​​не повинно вимагати розміщення інтерфейсу користувача. (Якщо це має статися, це, як правило, свідчить про те, що ядро ​​не призначене для власності.)

Моя система бухгалтерського обліку має структуру та зміст (і дані), які повинні моделювати діяльність моєї компанії. Ця структура реальна і існує незалежно від того, яке програмне забезпечення для бухгалтерії я використовую. (Неминуче даний програмний пакет містить структуру та вміст сам по собі, але частиною проблеми є мінімізація цих накладних витрат.)

В основному у людини є робота. DDD повинен відповідати потоку та змісту завдання. DDD полягає в тому, щоб чітко визначити всі завдання, які потрібно виконувати, повністю та незалежно. Тоді користувальницький інтерфейс, сподіваємось, сприяє виконанню роботи якомога прозоріше, якомога продуктивніше.

Інтерфейси - це входи та подання, що надаються для правильно змодельованого та незмінного функціонального ядра.


3

Чорт, клянусь, що це наполегливість.

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


2

У вашій презентації може бути посилання на рівень вашого домену, але не повинно бути прив’язки безпосередньо з вашого інтерфейсу до об’єктів вашого домену. Об'єкти домену не призначені для користувальницького інтерфейсу, оскільки вони часто, якщо вони правильно розроблені, базуються на поведінці, а не на представлення даних. Між інтерфейсом користувача та доменом повинен бути шар відображення. MVVM, або MVP, є хорошим шаблоном для цього. Якщо ви спробуєте безпосередньо прив’язати свій користувальницький інтерфейс до домену, ви, мабуть, створите собі головний біль. Вони мають дві різні цілі.


1

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

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

Звичайно, легко потрапити в пастку: "У моїй компанії ми дбаємо лише про англійську мову, запускаємо наш веб-сайт на LAMP (Linux, Apache, MySQL та PHP), і всі користуються однією версією Firefox". Але як бути через 5 або 10 років?



1

За допомогою такого інструменту, як « Value Injecter », та концепції «Mappers» на рівні презентації під час роботи з поданнями набагато легше зрозуміти кожен фрагмент коду. Якщо у вас є трохи коду, ви не побачите переваг відразу, але коли ваш проект буде зростати все більше і більше, ви будете дуже раді, працюючи з поданнями, не потрібно входити в логіку сервісів, сховища для розуміння моделі подання. View Model - ще одна охорона у величезному світі з питань боротьби з корупцією, і вона на вагу золота під час довгострокового проекту.

Єдина причина, чому я не бачу переваг використання моделі перегляду, полягає в тому, що ваш проект досить маленький і простий, щоб подання були прив’язані безпосередньо до кожного властивості вашої моделі. Але якщо в майбутньому вимога зміниться і деякі елементи керування у поданнях не будуть прив’язані до моделі, і у вас немає концепції моделі подання, ви почнете додавати патчі в багатьох місцях, і у вас почнеться застарілий код, який ви не оціните. Звичайно, ви можете зробити деякий рефакторинг, щоб перетворити свою модель перегляду в view-viewmodel і слідувати принципу YAGNI, не додаючи код, якщо він вам не потрібен, але для мене самого, це набагато краща практика, якої я повинен дотримуватися, щоб додати презентаційний рівень, що виставляє лише об'єкти моделі перегляду.


1

Ось реальний приклад того, чому я вважаю хорошою практикою відокремлювати сутності домену від подання.

Кілька місяців тому я створив простий інтерфейс, щоб показати значення азоту, фосфору та калію у зразку ґрунту через серію з 3 датчиків. Кожен датчик мав червону, зелену та червону ділянки, тобто у вас могло бути занадто мало або занадто багато кожного компонента, але в середині був безпечний зелений рівень.

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

Це означало, що пізніше мені довелося показати 12 компонентів, я просто зіставив додаткові дані в 12 нових моделей подання калібру, і вони з’явилися на екрані. Це також означало, що я міг легко використовувати контрольний прилад з повторним використанням і дозволити їм відображати інші набори даних.

Якби я з'єднав ці датчики безпосередньо з моїми сутностями домену, я б не мав жодної із зазначених вище гнучкостей, і будь-які подальші модифікації були б головним болем. Я стикався з дуже подібними проблемами при моделюванні календарів в інтерфейсі користувача. Якщо є потреба, щоб зустріч у календарі стала червоною, коли присутні 10+ учасників, тоді бізнес-логіка, яка повинна це зробити, повинна залишатися на бізнес-рівні, і весь календар в інтерфейсі повинен знати, це те, що йому було доручено почервоніти, це не повинно знати, чому.


-1

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

Доменно-керовані конструкції найкраще працюють у поєднанні з ортогональним набором функціональних доменних фреймворків (таких як ORM, GUI, Workflow тощо). Завжди пам’ятайте, що семантику домену потрібно піддавати лише зовнішнім шарам. Зазвичай це інтерфейс (GUI) і постійний сервер (RDBM, ORM). Будь-який ефективно розроблений проміжний шар може і повинен бути інваріантом домену.


пункт 1: не створюйте зайвих абстракцій (наприклад, багаторазових компонентів), якщо ви насправді не будете ділитися ними між різними програмами. пункт 2: Цікаво, як загальні графічні інтерфейси працюють у багатьох різних доменах. Примітка: Ця галузь настільки зламана, що вже навіть не смішно ...
alphazero
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.