<?xml version='1.0' encoding='UTF-8'?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title>Предметно-ориентированное проектирование · Tommy Cheese</title>
    <link>https://tommycheese.github.io/ru/tags/%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/</link>
    <description>Личный блог Tommy Cheese о программной инженерии, искусственном интеллекте и практическом обучении.</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>ru</language>
    <lastBuildDate>Fri, 26 Jul 2024 19:49:45 +0800</lastBuildDate>
    <atom:link href="https://tommycheese.github.io/ru/tags/%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1/index.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>Введение в предметно-ориентированное проектирование</title>
      <link>https://tommycheese.github.io/ru/blogs/ddd%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1%E5%88%9D%E8%AF%86/</link>
      <pubDate>Fri, 26 Jul 2024 19:49:45 +0800</pubDate>
      <guid>https://tommycheese.github.io/ru/blogs/ddd%E9%A2%86%E5%9F%9F%E9%A9%B1%E5%8A%A8%E8%AE%BE%E8%AE%A1%E5%88%9D%E8%AF%86/</guid>
      <description>&lt;h1 id="领域驱动设计概述"&gt;Обзор предметно-ориентированного проектирования&lt;/h1&gt;
&lt;p&gt;Предметно-ориентированное проектирование (DDD, Domain-Driven Design) — подход к проектированию на основе моделей. Он фиксирует знания предметной области в модели и использует её для создания ПО, &lt;strong&gt;которое легче сопровождать&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Проектирование в DDD делится на стратегическое и тактическое. Стратегическое рассматривает предметные области, подобласти и ограниченные контексты; тактическое — сущности, объекты-значения, события предметной области и другие элементы. Их связь показана ниже:&lt;/p&gt;
&lt;p&gt;&lt;img src="https://tommycheese.github.io/blogimages/DDD1.png" alt="img"&gt;&lt;/p&gt;
&lt;h2 id="战略设计阶段相关概念"&gt;Понятия стратегического проектирования&lt;/h2&gt;
&lt;h3 id="领域"&gt;Предметная область&lt;/h3&gt;
&lt;p&gt;Предметная область — это область задач, которые должна решать система. Например, ею может быть управление информацией о товарах.&lt;/p&gt;
&lt;h3 id="子域"&gt;Подобласти&lt;/h3&gt;
&lt;p&gt;По различиям используемого языка предметную область можно разделить на подобласти:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Ключевая подобласть определяет основное конкурентное преимущество продукта. Это наиболее важная, центральная и специфическая часть бизнеса.&lt;/li&gt;
&lt;li&gt;Общая подобласть предоставляет универсальные функции нескольким подобластям. Примеры — общие системы аутентификации и управления правами. Они не ограничены особенностями предприятия и не требуют большой адаптации.&lt;/li&gt;
&lt;li&gt;Вспомогательная подобласть не содержит ни ключевых, ни универсальных функций. Она специфична для предприятия и не является общей; пример — системы справочников с кодами данных.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="限界上下文"&gt;Ограниченный контекст&lt;/h3&gt;
&lt;p&gt;Ограниченный контекст определяет область, внутри которой используется конкретная модель для решения соответствующих задач.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Ограниченный контекст объединяет одну или несколько подобластей&lt;/strong&gt;, &lt;strong&gt;Нужно обеспечить поддержку полного бизнес-процесса одним ограниченным контекстом&lt;/strong&gt;, &lt;strong&gt;и включить в него все предметные области, задействованные в этом процессе&lt;/strong&gt;. Ограниченный контекст служит основанием для выделения микросервисов: каждому контексту соответствует один микросервис.&lt;/p&gt;
&lt;p&gt;Зачем вводить ограниченные контексты? Потому что &lt;strong&gt;контекст&lt;/strong&gt; усложняет написание кода. Рассмотрим пример:&lt;/p&gt;
&lt;p&gt;В подборе персонала «платформа» может обозначать учебное заведение или организацию. В прыжках в воду это вышка, с которой прыгает спортсмен. На железной дороге это посадочная платформа. Представим, что однажды вместе оказались прыгун в воду, HR и проводник, не зная профессий друг друга. И HR спросил спортсмена: «С какой вы платформы?»…&lt;/p&gt;
&lt;p&gt;Видите? Все трое используют слово «платформа», но &lt;strong&gt;без предварительной договорённости&lt;/strong&gt; могут понимать его по-разному. Решение — разделить области прыжков в воду, найма и транспорта и определить термины внутри каждой. Обсуждение в пределах одной области максимально уменьшает неоднозначность. Это и есть договорённость. По той же причине связанные с бизнесом области лучше определить в одном ограниченном контексте: чтобы уменьшить неоднозначность.&lt;/p&gt;
&lt;p&gt;Аналогичная проблема возникает при проектировании ПО. Допустим, большой продукт охватывает прыжки в воду, найм и поездки, но сервисы никак не разделены. В логике прыжков структура platform означает вышку, в найме — организационную платформу, в транспорте — перрон. Когда три направления неизбежно пересекутся, начнётся беда: что делать с экраном, заполненным почти одинаковыми именами переменных с разным смыслом?&lt;/p&gt;
&lt;p&gt;Если точно ограничить смысл термина в предметной области, внутри неё его можно применять свободно. В этом и состоит важная роль ограниченного контекста.&lt;/p&gt;
&lt;h2 id="战术设计阶段相关概念"&gt;Понятия тактического проектирования&lt;/h2&gt;
&lt;h3 id="值对象和实体"&gt;Объекты-значения и сущности&lt;/h3&gt;
&lt;p&gt;Сначала познакомимся с объектами-значениями и сущностями.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Объект-значение определяется значениями своих свойств: два таких объекта с одинаковыми внутренними значениями считаются равными. Следовательно, свойства объекта-значения неизменяемы.&lt;/li&gt;
&lt;li&gt;Сущность — бизнес-объект с уникальным идентификатором, состоянием и жизненным циклом. Её свойства изменяемы. Даже полностью одинаковые свойства не делают две сущности одной и той же: совпасть должны их идентификаторы, например ID.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Различим эти понятия на примере:&lt;/p&gt;
&lt;p&gt;Предположим, у нас есть объект-значение белого цвета Color white{R:255, G:255, B:255} и сущность шины tire{Air:&lt;em&gt;,Size:&lt;/em&gt;}:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Изменяемость: каждое свойство белого цвета неизменно, потому что после его изменения объект уже не обозначает белый цвет. Давление, размер и другие параметры шины могут меняться: она всё равно остаётся шиной.&lt;/li&gt;
&lt;li&gt;Сравнимость: неизменяемость значений определяет правило равенства объектов-значений. Значения двух объектов белого цвета обязательно совпадают, поэтому объекты с одинаковыми внутренними значениями считаются равными. У сущностей из-за изменяемости свойств такого свойства нет.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;У сущностей обычно выделяют четыре формы модели:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Модель без поведения содержит только данные и методы getter/setter. Вся бизнес-логика и прикладная логика размещается в сервисном слое. В Java такой класс называют POJO.&lt;/li&gt;
&lt;li&gt;Анемичная модель включает часть бизнес-логики, но не ту, что зависит от слоя хранения. Логика, зависящая от хранения, находится в сервисном слое.&lt;/li&gt;
&lt;li&gt;Богатая модель содержит всю бизнес-логику, включая зависимую от слоя хранения.&lt;/li&gt;
&lt;li&gt;Перегруженная модель помещает в предметную модель и другую прикладную логику, не относящуюся к бизнес-логике, например авторизацию и транзакции.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Репозиторий Repo&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Repo определяет операции хранения для Entity. Операции должны быть по возможности низкоуровневыми, иметь короткие имена и не быть слишком многочисленными. MyBatis Mapper в Java можно рассматривать как реализацию Repo.&lt;/p&gt;
&lt;h3 id="聚合与聚合根"&gt;Агрегаты и корни агрегатов&lt;/h3&gt;
&lt;p&gt;Агрегат — инкапсуляция большего масштаба. Он объединяет сущности и объекты-значения с общим жизненным циклом, неразделимые с точки зрения бизнеса. Внешние ссылки разрешено предоставлять только корню агрегата. Агрегат также выражает связность. Корни могут вызывать друг друга; их названия обычно являются существительными.&lt;/p&gt;
&lt;p&gt;Корень агрегата обеспечивает инкапсуляцию следующими способами:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Работать со всем агрегатом нужно через его корень; внешний код не должен напрямую обращаться к внутренним элементам. Например, фиолетовый цвет кузова + шины + стальная рама + … = автомобиль. При вождении мы не управляем отдельно шиной, рулём или внешностью. Мы действуем через автомобиль как корень агрегата, косвенно управляя остальными сущностями и объектами-значениями.&lt;/li&gt;
&lt;li&gt;Агрегат задаёт &lt;strong&gt;границу&lt;/strong&gt;, внутри которой все компоненты должны быть корректны с точки зрения бизнес-логики.&lt;/li&gt;
&lt;li&gt;Работа с агрегатом должна проходить в одной атомарной транзакции, иначе возможны ошибки. Агрегат — единица операции: извлечение из репозитория, изменение и возврат составляют атомарное действие. Например, если автомобиль включает колёса и стальную, алюминиевую или карбоновую раму, нельзя снять колесо для ремонта и после ремонта не установить его обратно.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="领域事件domain-events"&gt;События предметной области — Domain Events&lt;/h3&gt;
&lt;p&gt;Изменение свойств сущности порождает событие предметной области — происходящее в ней событие, которое эксперты считают значимым и заслуживающим внимания. Обычно оно означает изменение состояния предметного объекта.&lt;strong&gt;События передают сообщения, запускают другие действия и служат важным средством уменьшения зависимостей предметной модели&lt;/strong&gt;. Для их передачи часто используют &lt;strong&gt;очередь сообщений&lt;/strong&gt;, чтобы каждая подписанная подобласть выполнила собственную внутреннюю реакцию.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Шина сообщений — ещё один способ реализации 👋.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Например, изменение давления в сущности шины порождает событие утечки leaked. Оно передаёт сообщение «шина спускает», вызывая другие реакции: изменение работы силовой системы, ощущений на руле и так далее. Названия событий обычно ставят в прошедшее время, показывая, что событие уже произошло и необратимо.&lt;/p&gt;
&lt;h3 id="领域服务domain-service"&gt;Сервис предметной области — Domain Service&lt;/h3&gt;
&lt;p&gt;Некоторые действия предметной области, по-видимому, &lt;strong&gt;не принадлежат никакому объекту&lt;/strong&gt;. Они выражают важное поведение, поэтому их нельзя игнорировать или просто включить в случайную сущность либо объект-значение. Когда такое поведение выделено, рекомендуют объявить его сервисом предметной области.&lt;/p&gt;
&lt;p&gt;Сервис предметной области — не тот же «сервис», что в микросервисах. Сервисы и корни агрегатов отчасти похожи: оба могут работать с несколькими сущностями. Но их идеи и роли различаются. &lt;strong&gt;Корень агрегата объединяет сущности, а сервис синхронизирует состояния нескольких сущностей, например добавляет сущность item в сущность list&lt;/strong&gt; — скажем, доставляет mail в inbox. Поэтому название Service обычно выражается глаголом.&lt;/p&gt;
&lt;h2 id="ddd领域建模设计领域模型"&gt;Моделирование предметной области в DDD&lt;/h2&gt;
&lt;p&gt;Обычная последовательность моделирования:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;На основе требований предварительно выделить подобласти, ограниченные контексты и связи между контекстами.&lt;/li&gt;
&lt;li&gt;Подробно изучить каждый контекст, определить сущности и объекты-значения, а затем выбрать форму модели сущностей: без поведения, анемичную, богатую или перегруженную.&lt;/li&gt;
&lt;li&gt;Связать сущности и объекты-значения в агрегаты, определить их границы и корни.&lt;/li&gt;
&lt;li&gt;Спроектировать repo для корней агрегатов и продумать создание сущностей и объектов-значений.&lt;/li&gt;
&lt;li&gt;Применить модель в проекте, проверить её обоснованность практикой, выявить недостатки и выполнить рефакторинг.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Это двухэтапный подход DDD: сначала стратегическое проектирование, затем тактическое.&lt;/p&gt;
&lt;p&gt;На практике рекомендуются сущности без поведения, с одними setter/getter, или анемичные модели с простой логикой без операций базы данных, например проверкой допустимости свойств.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Это лишь один способ моделирования DDD — сверху вниз. Возможен и подход снизу вверх: сначала определить предметные модели, сущности и объекты-значения, а затем подобласти и ограниченные контексты…&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;(Конец раздела)&lt;/p&gt;
</description>
    <category>Архитектура ПО</category><category>Предметно-ориентированное проектирование</category></item>
    </channel>
</rss>
