Domain-Driven Design Vocabulary: 30 DDD Terms Explained (англійською)
Обмежений контекст, агрегат, сутність, об’ єкт значення, подія домену і тактичний словник DDD для архітекторів програмного забезпечення.
Дизайн, керований доменом (англ. Domain-Driven Design) — часто скорочується до DDD — це підхід до розробки програмного забезпечення, який ставить бізнес-домен в центр кожного технічного рішення. Введена Еріком Евансом у його книзі 2003 року Domain-Driven Design: Tackling Complexity in the Heart of Software, вона стала стандартною точкою відліку для архітекторів і старших розробників, які працюють над складними системами. Словник є точним і навмисним: кожен термін називає концепцію, яка допомагає командам моделювати реальність більш точно в коді. Якщо ви працюєте з мікросервісами, системами, що керуються подією, або будь- яким помірно складним сервером, ви зустрінетеся з цією мовою на зустрічах з розробниками, під час перегляду архітектури і перегляду коду. Цей посібник охоплює основні терміни DDD — що вони означають, і як справжні розробники використовують їх у розмові.
Основні стратегічні завдання
Стратегічне DDD стосується розуміння бізнес-ландшафту перед написанням однієї рядка коду. Ці терміни допомагають командам розрізати систему на значущі частини.
** Домен ** — сфера знань і діяльності, навколо якої обертається логіка програми. У практичному сенсі, це проблемний простір, який ваше програмне забезпечення намагається розв’ язати. Доменом логістичної компанії є вантажний рух; доменом банку є фінансові операції.
“Ми повинні зрозуміти область, перш ніж ми почнемо моделювати. Давайте проведемо день з командою операцій» «Це правило перевірки живе в доменні шарі, а не в шарі застосування»
** Піддомен ** — окрема частина загального домену. DDD розпізнає три типи:
- ** Core subdomain ** — конкурентний диференціатор; частина, де компанія отримує унікальну перевагу. Тут ви вкладаєте найбільше інженерних зусиль.
- ** Підтримка піддоменів ** — необхідний, але не відрізняється; часто побудований вдома, але з меншими інвестиціями.
- ** Загальний піддомен ** — вирішує проблеми, з якими стикається багато компаній; зазвичай обробляється готовими рішеннями (доставка електронної пошти, обробка платежу, автентифікація).
«Ціна є нашим основним піддоменом — ми будуємо його самі з повною моделлю DDD. Розрахунки є загальними; ми просто використовуємо Stripe» “Не переробляйте модуль звітів. Це підтримуючий субдомен»
** Обмежений контекст ** — чітко визначена межа, в межах якої певна модель є послідовною і чинною. У межах обмеженого контексту, кожен термін має одне точне значення. Одне і те ж слово може означати щось інше в сусідньому обмеженому контексті. Це одна з найважливіших концепцій у всій DDD.
“Слово “замовник” означає різні речі в контексті продажів і контексті доставки. Нам потрібно зберігати ці моделі окремо» «Перед тим, як ми додамо це поле, давайте перевіримо, який обмежений контекст володіє цією концепцією»
** Універсальна мова** — спільний словник, розроблений спільно розробниками і експертами з даної області, який використовується у коді, документації і розмовах. Метою є виключення перекладу між тим, що говорить бізнес і що робить код.
«Давайте оновимо всюдисущий лексикон мови — бізнес тепер називає це «зобов’язанням», а не «контрактом»». Якщо доменний експерт каже «shipment», а код каже «delivery», то у нас є мова проблема
** Карта контексту ** — діаграма або документ, у якому показано зв’ язки між обмеженими контекстами: як дані перетікають між ними, хто є попереднім, а хто — наступним, і які шаблони інтеграції використовуються.
“Чи можете ви оновити контекстну карту? Ми додали новий обмежений контекст для повідомлень» «Контекстна карта показує, що Замовлення знаходиться вище за виконання — саме тому зміна пошкодила речі»
Тактичні будівельні блоки
Тактична DDD надає вам словник для об’ єктів у обмеженому контексті. Ці шаблони описують, як моделювати область у коді.
** Сутність ** — об’ єкт, який має окрему ідентичність, яка зберігається протягом часу, навіть якщо його атрибути змінюються. User з ідентифікатором є суб’єктом; навіть якщо користувач змінює свою адресу електронної пошти, він все ще є тим самим користувачем.
«Користувач є безумовно суб’єктом — він має ідентифікатор і його стан змінюється протягом його життєвого циклу» “Не порівнюйте об’єкти за цінністю. Порівняйте їх за ідентичністю»
** Об’ єкт значення ** — об’ єкт, який повністю визначено його атрибутами і не має власної концептуальної ідентичності. Два об’ єкти значення з однаковими даними є взаємозамінними. Поширені приклади: сума грошей, поштова адреса, код кольору.
«Гроші повинні бути об’єктом цінності — незмінним, порівняним за цінністю, з валютою і кількістю» “Адреса не має ідентифікатора, тому що це об’єкт значення. Якщо адреса зміниться, ми її замінимо»
** Агрегатний ** — кластер об’ єктів і об’ єктів значення, які розглядаються як єдина одиниця для змін даних. Кожне агрегування має межу і накладає власні внутрішні правила послідовності. Ви намагаєтеся отримати агрегований результат як ціле.
«Агрегат замовлення включає заголовок замовлення і всі його рядкові елементи.» Якщо вам потрібно змінити рядок, ви проходите через агрегат Замовлення — ніколи не безпосередньо
** Корінь агрегату ** — єдиний об’ єкт у верхній частині агрегату, який керує всіма доступами до об’ єктів, що містяться у ньому. Зовнішній код може містити лише посилання на кореневий агрегат, а не на внутрішні сутності.
“OrderItem знаходиться всередині агрегату Order. Ви не можете отримати OrderItem безпосередньо — ви завантажуєте Order і переходите з кореня.» «Всі бізнес-правила для цього агрегату впроваджуються коренем агрегату»
** Подія домену ** — щось, що сталося у домені, про що інші частини системи можуть мати потребу знати. Події доменів називаються в минулому часі і представляють факти: OrderPlaced, PaymentFailed, UserRegistered.
«Коли оплата успішна, ми публікуємо подію домену
PaymentProcessed. Служба виконання послуг слухає за це» «Доменні події незмінні — вони факти, а не команди»
Інфраструктура та послуги
Ці терміни описують, як організовано поведінку і доступ до даних, якщо вони не вписуються чітко всередину сутності або об’ єкта значення.
** Доменна служба ** — служба без стану, яка містить логіку домену, яка не належить жодній одній сутності або об’ єкту значення. Типовим прикладом є калькулятор цін, який включає декілька агрегатів.
«Логіка конвертації валюти не належить жодній одній суб’єкті, тому ми помістили її в службу домену» Якщо ви виявите, що додаєте поведінку до сутності, яка відчуває себе змушеним, це може належати до доменного сервісу
** Служба програм ** — тонкий шар, який організовує об’ єкти домену для виконання певного випадку використання. Служби програм обробляють транзакції, авторизують запити і координують між службами домену і сховищами. Вони не містять логіки домену.
“Служба програми викликає сховище для завантаження агрегату, викликає метод домену, а потім зберігає його назад. Це все, що він робить» “Не вставляйте бизнес-правила в службу приложений. Ця логіка належить до домену»
** Шаблон сховища ** — абстракція, яка надає доступ до агрегатів, схожий на доступ до збірки, приховуючи деталі щодо того, як дані зберігаються і отримуються. Код домену взаємодіє з інтерфейсом сховища; рівень інфраструктури забезпечує реалізацію.
“Інтерфейс
OrderRepositoryзнаходиться в доменній ланці. Реалізація Postgres знаходиться в шарі інфраструктури» “Ми обміняємося даними. Оскільки ми використовували шаблон сховища, код домену залишається незмінним»
** Шлях захисту від пошкодження ** — це шар перекладу, який розташовано між двома обмеженими контекстами (або між вашою системою і застарілою системою), щоб запобігти перенесенню припущень однієї моделі на іншу. Він перетворює вхідні дані на мову вашої власної моделі.
«Ми побудували антикорупційний шар між нашим новим контекстом Замовлень і спадковим ERP. Ми перекладаємо їхню концепцію «роботи» в наш «заказ» «Без антикорупційного шару, кожна зміна в верхньому рівні служби руйнує нашу модель»
Спільне відкриття
** Подія Storming ** — метод спільного семінару, у якому експерти з домену і розробники використовують листівки для відображення подій домену, команд, агрегатів і правил у бізнес- процесі. Це один з найшвидших способів розробити спільне розуміння складної області.
«Перед тим, як ми почнемо моделювання, давайте проведемо сеанс штурму подій з командою продукту» «Події, що штурмували, допомогли нам відкрити три обмежені контексти, про які ми навіть не думали»
Як використовувати ці терміни в розмові
Зрозуміти термін - це одне; використовувати його природно в технічній дискусії - це інше. Ось реалістичні сценарії, де з’ являється словник DDD.
Архітектурний огляд: “Ми розбиємо моноліт на обмежені контексти. Основний піддомен — динамічне цінообразування — отримує багату модель домену з агрегатами і подіями домену. Сервіс сповіщення є загальним піддоменом; ми зробимо це простим»
** Перегляд коду: ** “Цей метод на сутності User запитує агрегат Order безпосередньо. Це перевищує межі агрегації. Служба застосунків повинна завантажувати кожен агрегат окремо і координувати їх»
** Дискусія про дизайн: ** “Ми потребуємо антикорупційного шару тут. Провайдер платежу використовує «трансакцію» таким чином, що це вступає в конфлікт з нашим власним об’єктом значення Transaction. Давайте перекладаємо на кордоні, перш ніж це забруднить нашу модель»
** Інформація про інцидент: ** « Проблема полягала у тому, що дві служби змінили агрегат Shipment, не пройшовши через кореневий агрегат. Ми втратили послідовність. В подальшому всі записи повинні проходити через кореневий файл і опублікувати подію домену»
Таблиця швидких посилань
| Term | Type | One-line definition |
|---|---|---|
| Bounded Context | Strategic | Boundary within which a model is consistent and unambiguous |
| Ubiquitous Language | Strategic | Shared vocabulary used by developers and domain experts alike |
| Aggregate | Tactical | Cluster of objects treated as one unit; persisted together |
| Aggregate Root | Tactical | The single entry point to an aggregate; enforces invariants |
| Entity | Tactical | Object with a persistent identity that changes over time |
| Value Object | Tactical | Immutable object defined entirely by its attributes |
| Domain Event | Tactical | An immutable record of something that happened in the domain |
| Domain Service | Tactical | Stateless service for domain logic that spans multiple objects |
| Repository Pattern | Infrastructure | Abstraction for loading and saving aggregates |
| Anti-Corruption Layer | Integration | Translation layer preventing model contamination at boundaries |
Завдання з освоєння словника DDD не зробить вашу архітектуру автоматично кращою, але воно надасть вам і вашій команді точну мову, необхідну для правильного ведення розмов. Коли всі в кімнаті використовують ті ж самі терміни з тими ж значеннями, рішення про дизайн стають швидшими, чистішими і легше комунікувати. Почати з визначення обмежених контекстів вашої власної системи і основного піддомену, а потім створити універсальну мову з цього.