Академический Документы
Профессиональный Документы
Культура Документы
DDD
Domain Driven Design (DDD) — это подход, который позволяет нам преуспеть в
понимании и построении моделей программных продуктов. Он предоставляет нам
инструменты стратегического и тактического моделирования для разработки
высококачественного программного обеспечения, которое соответствует нашим бизнес-
целям.
Что очень важно, DDD не связан с технологиями. Здесь речь идет о развитии знаний о
бизнесе и использовании технологий для моделирования процессов и сбора знаний о
предметной области и переноса их в код.
Стратегическое проектирование
Проектирование на высоком уровне абстракции, без технических нюансов,
осуществляемое всей командой - как менеджерами/заказчиками, так и техническими
специалистами.
Этот коллективный язык терминов называется — единый язык. (Ubiquitous Language). Это
один из основных и самых важных шаблонов DDD. Это не бизнес жаргон, навязанный
разработчикам, а настоящий язык, созданный целостной командой – экспертами в
предметной области, разработчиками, бизнес-аналитиками и всеми, кто вовлечен в
создание системы. Роль в команде не столь существенна, поскольку каждый член
команды использует для описания проекта единый язык.
Единый язык — это базовая концепция борьбы со сложностью. Если предметная область
итак требует изучения, то давайте не будем делать вещи еще сложнее и заставлять
людей разбираться еще и в вашей модели предметной области. Будем называть вещи
одинаково как в спецификации, так и в коде.
Итак, ограниченный контекст – это явная граница, внутри которой существует модель
предметной области, которая отображает единый язык в модель программного
обеспечения.
Язык является единым только в рамках команды, работающей над проектом в едином
ограниченном контексте.
Попытка применить единый язык в рамках всего предприятия или что хуже, среди
нескольких предприятий, закончится провалом.
Для разработчиков такой подход позволяет вносить изменения в код не опасаясь, что где-
то в другом месте что-то сломается (например, менять что-то в кассе и не переживать,
что из-за этого что-то отвалится у курьеров).
Проблема №1
Проблема №2
«Единый язык» на самом деле не является «единым» для всего приложения и живет
только в рамках контекста. И Эванс прямо об этом пишет. К сожалению, в книге сей факт
формируется мягко, скорее как рекомендация, а не правило. Я бы набрал параграф
красным КАПСОМ и поместил в рамку. Попытка создания единой модели предметной
области обречена на провал. Один и тот же термин может значить разные вещи в разных
контекстах. Я могу сходу назвать несколько примеров из разных предметных областей, но
все они требуют специального объяснения, поэтому ограничусь синтетическим примером:
салат рекурсивный — помидоры, огурцы, салат. Ну вы поняли…
Проблема №3
Никому не нужна модель предметной области целиком. Она скорее всего слишком
сложна даже для крутых стратегов и аналитиков. Эти ребята попросят представить им
данные в совершенно ином, понятном им, виде и разрезе. Контексты реализуют принцип
«разделяй и властвуй», что помогает быстрее обучать пользователей и подключать
новых членов в команду разработки.
В качестве бонуса
Тактическое проектирование
Использование технических, структурных паттернов в вашем коде, для отражения
результатов стратегического проектирования непосредственно в коде приложения.
Самое главное заключается в том, что эти объекты отражают язык, на котором вы
разговариваете с другими разработчиками — когда вы говорите «Место»(Location) все
знают, что это значит. Второе преимущество заключается в том, что Value Object может
валидировать значение — подходит оно или нет для того, чтобы создать такой объект.
Третьим преимуществом является то, что вы можете полагаться на тип — вы знаете,
что если такой Value Object был принят в качестве аргумента, он будет всегда в
допустимом состоянии и вам не нужно беспокоиться об этом. И также Value Object может
содержать некоторые специализированные методы, которые имеют смысл только в
контексте этого значения и могут быть расположены в этом объекте (не нужно создавать
странные классы-утилиты).
В качестве примера Value Object-а, который является распространённым для всех веб-
приложений, я создал EmailAddress:
Вышеприведённая реализация:
Одержимость примитивами
Неизменяемость
Очень важно помнить и понимать, что Value Object является неизменяемым. Почему это
такое важное понятие? Задумайтесь о реальности вокруг вас и какие значения вы
используете — число один, красный цвет и так далее. Вы не можете изменить эти
значения — это не имеет смысла, менять красный цвет на зеленый, и продолжать
называть его красным — это больше не красный, и называние зеленого красным будет
путать людей. Таким же образом Value Object в вашем приложении должны быть
неизменными.
Например, у вас есть сущность «Собрание» в вашей Предметной Области, и у этого
Собрания есть некоторая Дата (Value Object). Теперь дата встречи изменилась, но не
сама дата - 22 марта все еще 22 марта. Это собрание, которое требует назначения новой
даты, а не изменения самой даты, поэтому выкиньте старую дату и создайте новую.
Важные граждане
Value Object-ы являются важными гражданами вашей Предметной Области, которые
отражают его концепции. Убедитесь, что вы приложите соответствующее поведение к
таким объектам, которое впоследствии будет делать код более организованным и лучше
передавать реальность, потому что ключевым аспектом и целью объектно-
ориентированного программирования является моделирование реального мира.
Entity (Сущность)
Если какое-то понятие предметной области является уникальным и отличным от всех
других объектов в системе, то для его моделирования используется сущность. Такие
объекты-сущности могут сильно отличаться своей формой за весь цикл существования,
тем не менее их всегда можно однозначно идентифицировать и найти по запросу. Для
этого используются уникальные идентификаторы, создание которых необходимо
продумать в первую очередь при проектировании сущности.
Aggregate (Агрегат)
Агрегатом называется кластер из объектов сущностей или значений. То есть эти
объекты рассматриваются как единое целое с точки зрения изменения данных. У каждого
агрегата есть корень Aggregate Root и граница, внутри которой всегда должны быть
удовлетворены инварианты. Также имеют свойство меняться в рамках одной транзакции
по бизнес-процессу;
Module (Модуль)
Модули внутри модели являются именованными контейнерами для некоторой группы
объектов предметной области, тесно связанных друг с другом. Их цель – ослабление
связей между классами, которые находятся в различных модулях. Так как модули в
подходе DDD – это неформальные или обобщенные разделы, их следует правильно
называть. Выбор их имен является функцией единого языка.
Factory (Фабрика)
Некоторые агрегаты или сущности могут быть достаточно сложными. Сложный объект
не может создавать сам себя посредством конструктора. (В книге Эрика Эванса был
приведен пример: двигатель автомобиля, который собирается либо механиком, либо
роботом, но он никак не должен собираться сам по себе.) Еще хуже, когда передают
создание сложного объекта на клиент. Так, клиент должен знать о внутренней структуре и
взаимосвязях внутри объекта. Это нарушает инкапсуляцию и привязывает клиента к
определенной реализации (таким образом, при изменении объекта придется менять и
реализацию клиента).
Лучше выполнять создание сложных агрегатов или других объектов отдельно. Для этого
используются фабрики. Элементы программы, обязанности которого создавать другие
объекты.
Ныряем глубже
Итак, когда мы познакомились с основными строительными блоками DDD мы можем
представить возможные проблемы и попробовать представить пути их решений.
Конечно, при использовании слабой модели предметной области эти модели данных
будут использоваться из набора объектов службы (обычно называемого слоем
предметной области), который фиксирует всю бизнес-логику или логику предметной
области. Слой предметной области находится вверху модели данных и использует
модель данных так же, как данные.
Слабая модель предметной области — это просто структура процедурного стиля. Слабые
объекты сущности не являются реальными объектами из-за отсутствия поведения
(методов). Они лишь содержат свойства данных, и, таким образом, это не объектно-
ориентированный проект. Помещая все поведение в объекты служб (слой предметной
области), вы, в сущности, получаете плохо структурированный код или сценарии
транзакции, таким образом теряя преимущества, которые предоставляет модель
предметной области.
Как бы там ни было, если вы имеете очень простой ограниченный контекст или
микрослужбу (службу CRUD), слабая модель предметной области в форме объектов
сущности только со свойствами данных может быть достаточно хороша, и, возможно, не
имеет смысла реализовывать более сложные шаблоны DDD. В таком случае это будет
просто модель сохраняемости, так как вы намеренно создали сущность только с данными
для целей CRUD.
................
Модульный монолит