Зачем DDD: сложность живёт в предметной области
Почему код со временем расходится с бизнесом и разработка вязнет в «большом коме грязи», что такое предметная область, модель и DDD, из каких двух половин он состоит, когда окупается и когда лишний — и как устроена программа на сквозном примере онлайн-школы.
Зачем это нужно
Заголовок раздела «Зачем это нужно»Представьте онлайн-школу в первый месяц жизни. Есть таблица курсов, кнопка «Записаться» и форма оплаты. Код помещается
в один файл, и любой разработчик понимает его за вечер. Через два года у той же школы появились потоки с датой старта
и ограниченным числом мест, лист ожидания, возвраты при отмене, рассрочка, сертификаты и десяток рассылок. Методист
говорит: «Если студент не оплатил запись за двое суток, место надо отдать первому из листа ожидания». Разработчик
кивает, открывает код и видит таблицу orders, поле st со значениями 0, 1 и 2 и три функции, которые по-разному
считают свободные места. Задача «на час» занимает неделю, а после выкатки поддержка находит новый баг.
Ничего катастрофического никто не делал. Каждая правка была разумной, но правила бизнеса оказались размазаны по коду,
а слова в коде перестали совпадать со словами людей, которые этот бизнес ведут. Дорогим стал перевод: из «студент
записан на поток и ждёт оплаты» в st == 0 и обратно, в каждом разговоре и в каждом ревью.
Предметно-ориентированное проектированиепредметно-ориентированное проектирование (DDD)EN Domain-Driven DesignПодход Эрика Эванса (книга 2003 года): проектировать сложную систему вокруг модели предметной области, выработанной вместе с экспертами, говорить на едином языке и сосредоточить силы на основном поддомене. (Domain-Driven Design, DDD) — это набор идей и приёмов о том, как не допустить этого расхождения: строить программу вокруг модели предметной области, вырабатывать её вместе с экспертами и называть вещи в коде так же, как их называет бизнес. Этот урок открывает программу: разберёмся, откуда берётся сложность, что такое DDD и когда он нужен, познакомимся со сквозным примером — онлайн-школой — и посмотрим на карту всех четырёх модулей.
Почему код расходится с бизнесом
Заголовок раздела «Почему код расходится с бизнесом»Две сложности
Заголовок раздела «Две сложности»Фред Брукс в эссе «Серебряной пули нет» (1986) разделил сложность программ на два вида. Существенная сложностьсущественная сложностьEN essential complexityСложность, присущая самой задаче (правила бизнеса), — её нельзя убрать, только выразить ясно. Противоположность — привнесённая (accidental) сложность от инструментов и неудачных решений. Различение — у Фреда Брукса («Серебряной пули нет», 1986). присуща самой задаче: правило «при отмене за 7 суток и более до старта — полный возврат» существует, даже если программы нет вовсе. Привнесённая (accidental) сложность появляется от инструментов и решений: неудачная схема базы, магические числа, копии одной логики в трёх местах.
Существенную сложность убрать нельзя, её можно только выразить ясно. Привнесённую можно и нужно уменьшать. Беда начинается, когда они перемешаны: чтобы понять бизнес-правило, приходится продираться через технические детали, а чтобы поменять технику, приходится угадывать, какие правила сломаются. Подзаголовок книги Эрика Эванса говорит именно об этом: «Tackling Complexity in the Heart of Software» — справляться со сложностью в самом сердце программы.
Испорченный телефон
Заголовок раздела «Испорченный телефон»Знания о бизнесе живут в головах экспертов предметной областиэксперт предметной областиEN domain expertЧеловек, который глубоко знает бизнес-процессы и их правила: методист, менеджер набора, бухгалтер, опытный сотрудник поддержки. Необязательно начальник.: методистов, менеджеров набора, бухгалтеров, опытных сотрудников поддержки. До кода они доходят цепочкой пересказов:
| Кто | Как он это называет |
|---|---|
| Методист | «Студент записался на поток, но не оплатил — через двое суток запись сгорает, место уходит следующему» |
| Аналитик в задаче | «Удалять неоплаченные заказы старше 48 часов» |
| Разработчик в коде | DELETE FROM orders WHERE st = 0 AND ts < now() - interval '48 hours' |
| Поддержка через месяц | «Студент говорит, что записывался, а в системе его нет. Куда он делся?» |
На каждом шаге смысл немного искажается. «Запись сгорает» превратилась в «удалить заказ» — и пропала история: никто не может ответить, был ли студент записан. «Место уходит следующему» потерялось вовсе. Разработчик не виноват: ему передали не модель, а пересказ пересказа.
«Большой ком грязи»
Заголовок раздела ««Большой ком грязи»»Если так развивать систему годами, получается то, что Брайан Фут и Джозеф Йодер в статье 1997 года назвали «большим комом грязи»«большой ком грязи»EN Big Ball of MudСистема без различимой структуры: всё зависит от всего, правила размазаны и продублированы, любое изменение страшно. Название — из статьи Брайана Фута и Джозефа Йодера (1997). (Big Ball of Mud): систему без различимой структуры, где всё зависит от всего, правила продублированы, а заплатки держатся на честном слове. Авторы замечают, что это самая распространённая архитектура на свете: её никто не выбирает, она вырастает сама из череды разумных по отдельности решений «сделаем быстро, потом поправим».
Признаки кома грязи узнаются быстро:
- одно правило реализовано в нескольких местах, и копии понемногу расходятся;
- имена в коде ничего не говорят эксперту:
process,data,flag,st,Manager; - чтобы поменять одну вещь, надо понимать всю систему;
- новые люди входят в проект месяцами, старые боятся трогать «ту самую функцию»;
- скорость команды падает: каждая новая возможность дороже предыдущей.
Последний пункт — главный для бизнеса. Вначале ком грязи кажется быстрым путём, но кривая скорости у него идёт вниз: через год-два почти всё время уходит на то, чтобы не сломать существующее. В практике урока вы увидите, как ровно одно правило про возврат, записанное в двух местах, тихо даёт студентам разные деньги.
Предметная область, модель и DDD
Заголовок раздела «Предметная область, модель и DDD»Предметная область
Заголовок раздела «Предметная область»Предметная областьпредметная область (домен)EN domainОбласть деятельности, задачи которой решает программа: для онлайн-школы — набор студентов на потоки, обучение, оплата, сертификаты. Знания о ней — у экспертов, а не в коде., или домен (domain), — это область деятельности, задачи которой решает программа. Для онлайн-школы это набор студентов на потоки, обучение, оплата, выдача сертификатов. Для банка — счета, кредиты, платежи. Домен существует независимо от программы: школа может вести набор в таблице на бумаге, правила от этого не исчезнут.
Домен почти никогда не бывает однородным. В школе набор и бухгалтерия живут по разным правилам, у них разные эксперты и даже разные слова. Поэтому домен делят на части — поддомены; им посвящён урок DDD.1.3.
Модель — это упрощённое представление, в котором оставлено только нужное для задачи. Хороший пример — схема метро. Она искажает расстояния и форму линий, на ней нет улиц и домов, но для вопроса «как доехать с пересадкой» она лучше точной карты города. Модель не бывает «верной вообще» — она бывает полезной для конкретной задачи.
Модель предметной областимодель предметной областиEN domain modelУпрощённое и осознанно отобранное представление знаний о предметной области, нужное для конкретной задачи. В DDD модель живёт одновременно в словах команды, в документах и в коде. — такое же отобранное знание о бизнесе: какие в нём есть
понятия (курс, поток, запись на поток), как они связаны и какие правила соблюдаются. В DDD важно, что модель — не
картинка в документации и не схема базы данных. Она живёт одновременно в трёх местах: в словах, которыми команда
говорит о системе, в документах и в коде. Если в разговоре «запись на поток», а в коде order, — моделей уже две.
Модель не записывают под диктовку. Эванс называет этот процесс переработкой знанийпереработка знанийEN knowledge crunchingТермин Эванса: совместная работа разработчиков и экспертов, в которой из разговоров, примеров и черновых моделей выжимают то, что важно для задачи, и отбрасывают лишнее.: разработчики и эксперты вместе разбирают случаи, пробуют черновые модели, спорят о словах и отбрасывают лишнее, пока не получат то, что действительно объясняет правила. Хорошая модель часто удивляет самих экспертов: они впервые видят свои правила записанными без противоречий.
Что такое DDD
Заголовок раздела «Что такое DDD»Эрик Эванс описал подход в книге «Domain-Driven Design: Tackling Complexity in the Heart of Software» (2003); её называют «синей книгой» по цвету обложки. На русском она вышла в 2010 году под названием «Предметно-ориентированное проектирование (DDD). Структуризация сложных программных систем». В кратком справочнике (Domain-Driven Design Reference, 2015) Эванс сводит DDD к трём тезисам:
- Сосредоточиться на основной предметной области — той части, ради которой система существует и которая отличает бизнес от конкурентов.
- Исследовать модели в совместной творческой работе экспертов предметной области и разработчиков.
- Говорить на едином языкеединый языкEN ubiquitous languageОбщий язык экспертов и разработчиков, построенный на модели, который используют везде: в разговорах, документах, именах классов и методов, событиях и тестах. Изменение языка — это изменение модели и кода. Встречаются переводы «вездесущий» и «повсеместный язык». внутри явно ограниченного контекста — одни и те же слова в разговорах, документах и коде, с понятными границами, где эти слова действуют.
Авторы книги «Architecture Patterns with Python» (её называют «Cosmic Python»; это хорошее продолжение программы для питонистов) формулируют суть ещё короче: самое важное в программе — полезная модель задачи. Если модель верна, программа приносит пользу и открывает новые возможности. Если неверна — она становится препятствием, которое приходится обходить.
Обратите внимание: в трёх тезисах нет ни слова о классах, базах данных или микросервисах. DDD — прежде всего способ думать и договариваться, а уже потом — набор шаблонов кода.
Две половины DDD
Заголовок раздела «Две половины DDD»Эванс разделил книгу на части, и сообщество со временем свело их к двум половинам подхода.
Стратегическое проектированиестратегическое проектированиеEN strategic designПоловина DDD о крупных решениях: на какие части делится предметная область, где проходят границы моделей, что здесь главное и как части связаны (поддомены, ограниченные контексты, карта контекстов). отвечает на крупные вопросы: на какие части делится предметная область, какая из них главная, где проходят границы моделей и как части связаны между собой. Это решения уровня всей системы и всех команд.
Тактическое проектированиетактическое проектированиеEN tactical designПоловина DDD о коде внутри одной модели: сущности, объекты-значения, агрегаты, доменные события, сервисы, фабрики и репозитории. отвечает на вопрос, как выразить модель в коде внутри одной такой границы: какие объекты имеют идентичность, какие являются просто значениями, какие правила защищает агрегат, какие события он публикует.
| Стратегическое | Тактическое | |
|---|---|---|
| Масштаб | вся система, несколько команд | одна модель, один модуль |
| Главные вопросы | что главное? где границы? кто от кого зависит? | как выразить правила в коде, чтобы их нельзя было нарушить? |
| Инструменты | поддомены, ограниченные контексты, карта контекстов, Event Storming | сущности, объекты-значения, агрегаты, доменные события, сервисы, репозитории |
| Ошибка обходится | очень дорого: неверные границы живут годами | дешевле: код внутри границы можно переписать |
| В программе | модули DDD.1 и DDD.2 | модули DDD.3 и DDD.4 |
Частая ошибка новичков — начать с тактики: обложить код репозиториями и агрегатами, не договорившись ни о языке, ни о границах. Вон Вернон в «Реализации методов предметно-ориентированного проектирования» называет такое применение «DDD-Lite»: шаблоны есть, а модели, выработанной с экспертами, нет. Получается тот же ком грязи, только с модными именами классов. Поэтому программа идёт от стратегии к тактике — так же советуют и составители маршрута изучения DDD в SAP: новичкам лучше начинать со стратегического проектирования.
Когда DDD окупается, а когда это лишнее
Заголовок раздела «Когда DDD окупается, а когда это лишнее»DDD стоит денег: время экспертов на разговоры, больше классов и понятий в коде, время на обучение команды. Окупается он не везде.
| Признак проекта | DDD окупается | DDD скорее лишний |
|---|---|---|
| Правила | много нетривиальных правил, исключений, сроков, статусов | данные сохраняются и показываются почти без правил |
| Изменчивость | правила часто меняются вслед за бизнесом | требования стабильны |
| Срок жизни | система будет жить и развиваться годами | прототип, одноразовый скрипт, проверка гипотезы на две недели |
| Эксперты | есть люди, которые знают домен и готовы разговаривать | знаний о домене ни у кого нет, или домен тривиален |
| Где сложность | в бизнес-логике | в технике: видеокодек, высокая нагрузка, низкоуровневая оптимизация |
| Команда | несколько команд, частые недопонимания | один-два разработчика, которые сами себе эксперты |
Второй столбец — классические случаи CRUDCRUD (создать, прочитать, изменить, удалить)EN Create, Read, Update, DeleteПриложение или его часть, которое в основном хранит и показывает данные: формы поверх таблиц, почти без бизнес-правил. Для такого кода тяжёлое DDD не нужно. (Create, Read, Update, Delete): «формы поверх таблиц». Админка справочника городов, страница «О нас», внутренний учёт ноутбуков — здесь агрегаты и доменные события только замедлят работу. Для прототипа DDD тоже вреден: пока неизвестно, нужен ли продукт вообще, вкладываться в тщательную модель рано.
Важная оговорка из материалов DDD Crew: DDD — не «всё или ничего». Можно применить только часть идей. Единый язык и разговоры с экспертами полезны почти в любом проекте и почти ничего не стоят. Разделение на поддомены помогает решить, куда тратить силы. А полный тактический арсенал имеет смысл только там, где сосредоточена существенная сложность, — в основном поддомене. Даже внутри одной системы часть кода может быть аккуратным CRUD, а часть — богатой моделью; в уроке DDD.1.3 вы научитесь проводить эту границу.
Сквозной пример: онлайн-школа
Заголовок раздела «Сквозной пример: онлайн-школа»Вся программа DDD — и программа SDD тоже — строится на одном примере, который развивается от урока к уроку. Это онлайн-школа, которая продаёт курсы и учит студентов потоками.
Как устроен бизнес. У школы есть курсы и программы из нескольких курсов. Курс проходит потоками: у каждого потока есть дата старта и вместимость — сколько студентов в нём помещается (например, из-за числа наставников). Студент записывается на поток, получает счёт и оплачивает его через внешнюю платёжную систему. После оплаты запись подтверждается, студент учится: занятия, задания, прогресс. Тот, кто выполнил условия, получает сертификат. Если мест нет, студент встаёт в лист ожидания.
Школа естественно делится на шесть частей:
| Часть | Чем занимается |
|---|---|
| Каталог | курсы и программы: описания, цены, расписание потоков для витрины |
| Набор | потоки, записи на потоки, лист ожидания, отмены и возвраты |
| Оплата | счета и платежи через внешнюю платёжную систему |
| Обучение | занятия, задания, прогресс студентов |
| Сертификация | выдача сертификатов |
| Уведомления | письма и пуши студентам |
flowchart LR K["Каталог<br/>курсы и программы"] --> N["Набор<br/>потоки, записи,<br/>лист ожидания"] N -->|"счёт"| P["Оплата<br/>внешняя платёжная система"] P -->|"ПлатёжПолучен"| N N -->|"ЗаписьПодтверждена"| L["Обучение<br/>занятия, задания, прогресс"] L -->|"условия выполнены"| C["Сертификация"] N -.-> U["Уведомления<br/>письма и пуши"] C -.->|"СертификатВыдан"| U
Самая насыщенная правилами часть — Набор. Вот его правила в учебном примере; числа (48 часов, 7 суток, 24 часа) — условия примера, а не отраслевой стандарт:
- записей со статусами «ожидает оплаты» и «подтверждена» не больше вместимости потока;
- студент не может записаться на один поток дважды;
- запись закрывается в момент старта потока;
- неоплаченная запись отменяется через 48 часов;
- при отмене за 7 суток и более до старта — полный возврат, позже — без возврата;
- освободившееся место предлагается первому в листе ожидания (по очереди, кто раньше встал), и у него 24 часа на подтверждение.
Уже здесь видно, почему это не CRUD: правила зависят от времени, от статусов, друг от друга. Отмена записи освобождает место, место предлагается из листа ожидания, у предложения есть срок, по истечении срока место уходит дальше. Ровно такие правила и расползаются по коду, если их не собрать в модель.
Важные факты в жизни школы мы будем записывать как события в прошедшем времени: СтудентЗаписан (StudentEnrolled), ЗаписьПодтверждена (EnrollmentConfirmed), ЗаписьОтменена (EnrollmentCancelled), МестоОсвободилось (SeatReleased), ПлатёжПолучен (PaymentReceived), СертификатВыдан (CertificateIssued). Что такое доменное событие и зачем оно нужно, разберём в модулях DDD.2 и DDD.3; пока достаточно заметить, что события звучат на языке бизнеса.
Карта программы
Заголовок раздела «Карта программы»Программа рассчитана примерно на 40 часов и состоит из четырёх модулей. Каждый урок продвигает онлайн-школу на шаг: от слов и границ — к коду на Python, покрытому тестами.
flowchart LR M1["DDD.1<br/>Предметная область<br/>и единый язык"] --> M2["DDD.2<br/>Стратегическое<br/>проектирование"] M2 --> M3["DDD.3<br/>Тактическое<br/>проектирование"] --> M4["DDD.4<br/>DDD на практике"] M3 --> H1["ДЗ ddd-hw01-domain-model"] M4 --> H2["ДЗ ddd-hw02-integration"] M2 -.->|"дальше можно<br/>параллельно"| S["Программа SDD"] M4 -.->|"модель как вход<br/>для спецификаций"| S
| Модуль | Часов | Что в нём | Что появится в онлайн-школе |
|---|---|---|---|
| DDD.1 Предметная область и единый язык | 8 | зачем DDD; единый язык и глоссарий; поддомены, ядро и решения «делать или купить» | глоссарий домена, классификация шести частей, описание ядра на страницу |
| DDD.2 Стратегическое проектирование | 10 | ограниченные контексты; карта контекстов и шаблоны отношений; Event Storming | границы контекстов, карта их связей, предохранительный слой для платёжной системы, «стена событий» записи и оплаты |
| DDD.3 Тактическое проектирование | 12 | сущности и объекты-значения; агрегаты и инварианты; доменные события, сервисы, фабрики; репозитории и архитектура | объекты Money и Period, агрегат «Поток» с правилами записи, сценарий «записаться на поток», репозиторий в памяти |
| DDD.4 DDD на практике | 10 | CQRS и event sourcing; интеграция контекстов; DDD в существующей системе; DDD и системы с ИИ | поток как свёртка событий, цепочка «оплата прошла → запись подтверждена → сертификат выдан», план внедрения |
В программе две домашние работы с автотестами и уровнями Simple, Medium, Strong и Boss — как в основном курсе:
- ddd-hw01-domain-model — в конце модуля DDD.3: модель предметной области онлайн-школы на Python из тактических шаблонов этого модуля, проверяемая автотестами;
- ddd-hw02-integration — в конце модуля DDD.4: интеграция контекстов школы через события.
Как устроены домашние работы и команда проверки python homework/check.py, вы знаете по
уроку 0.1.3. Подробные условия будут в последних уроках
модулей DDD.3 и DDD.4.
Что нужно знать заранее
Заголовок раздела «Что нужно знать заранее»Программа рассчитана на тех, кто прошёл ступень 0 основного курса. Конкретно понадобятся:
- Python и классы —
__init__, методы,@property,__eq__и особенно@dataclassиз урока 0.2.3. Если@dataclassи сравнение объектов через==вызывают сомнения, перечитайте конец этого урока: объекты-значения в модуле DDD.3 строятся именно на них; - модули и исключения — урок 0.2.4: модель будет разложена по модулям, а нарушение правила — это исключение с понятным сообщением на русском;
- тесты на pytest и домашние работы — урок 0.1.3;
- Git и терминал — урок 0.1.1.
Желательно пройти урок 11.1.2 «Чужой код»: рефакторинг под защитой тестов пригодится в уроке о DDD в существующей системе. Паттерны проектирования и архитектуру знать не нужно — всё объясняется с нуля, на примерах и коде.
Связь с программой SDD
Заголовок раздела «Связь с программой SDD»Вторая программа — SDD, разработка через спецификации с ИИ-агентами. Её идея: сначала хорошенько продумать задачу и записать её в набор спецификаций, а потом отдать их ИИ-агенту для кода, который превратит их в рабочий код. Программы дополняют друг друга. SDD отвечает на вопрос, как передать замысел агенту и проверить результат. DDD отвечает на вопрос, что именно записать: какие в системе понятия, как они называются, какие правила нельзя нарушать и где проходят границы.
Пример программы SDD — тот же: спецификация записи на потоки онлайн-школы. Требования в ней формулируются словами глоссария из урока DDD.1.2, а правила Набора становятся критериями приёмки. Поэтому программа SDD советует пройти модули DDD.1–DDD.2 до неё. Дальше программы можно идти параллельно, а урок DDD.4.4 «DDD и системы с ИИ» строит мост между ними.
Практика
Заголовок раздела «Практика»Посмотрим, как ровно одно правило Набора превращается в тихий баг. Вот код, каким он часто бывает через два года жизни проекта: словари, сокращения, магические числа. Отмену из личного кабинета написал один разработчик, отмену через поддержку — другой, полгода спустя.
from datetime import datetime
# «База данных» школы через два года жизни проекта: словари и сокращенияdb = { "groups": {7: {"start": datetime(2026, 11, 2, 10, 0), "max": 2, "price": 3_000_000}}, "orders": [],}
def add_order(usr, grp): """Записать пользователя в группу (так это называлось в первой версии).""" g = db["groups"][grp] busy = [o for o in db["orders"] if o["grp"] == grp and o["st"] in (0, 1)] # 0 — не оплачен, 1 — оплачен if len(busy) >= g["max"]: return None order = {"usr": usr, "grp": grp, "st": 0} db["orders"].append(order) return order
def cancel_from_site(order, now): """Отмена из личного кабинета. Писал первый разработчик.""" g = db["groups"][order["grp"]] order["st"] = 2 days = (g["start"] - now).days # целых суток до старта return g["price"] if days >= 7 else 0
def cancel_by_support(order, now): """Отмена через поддержку. Через полгода писал другой разработчик.""" g = db["groups"][order["grp"]] order["st"] = 2 hours = (g["start"] - now).total_seconds() / 3600 return g["price"] if hours > 7 * 24 else 0 # «больше недели» — как он понял задачу
a = add_order("anna", 7)b = add_order("boris", 7)now = datetime(2026, 10, 26, 10, 0) # ровно 7 суток до стартаprint("Отмена ровно за 7 суток до старта потока:")print(f" через сайт: возврат {cancel_from_site(a, now) / 100:.2f} руб.")print(f" через поддержку: возврат {cancel_by_support(b, now) / 100:.2f} руб.")Отмена ровно за 7 суток до старта потока: через сайт: возврат 30000.00 руб. через поддержку: возврат 0.00 руб.Два студента отменили запись в одну и ту же минуту и получили разные деньги. Код не упал, тесты (если они есть)
прошли — у каждой функции свой «правильный» ответ. Виноваты не разработчики: правило «за 7 суток и более» нигде не
записано одним куском, а слово «неделя» каждый понял по-своему. Заодно посмотрите на имена: orders, usr, grp,
st == 2. Эксперт школы не сможет прочитать этот код и сказать, верен ли он.
Теперь то же правило, записанное один раз и словами предметной области:
from datetime import datetime, timedelta
# Правило Набора записано один раз — словами предметной области.# 7 суток — условие учебного примера, а не закон природы.FULL_REFUND_PERIOD = timedelta(days=7)
def refund_on_cancellation(price_kopecks, cohort_starts_at, cancelled_at): """Сколько вернуть студенту при отмене записи на поток (в копейках).
Правило: отмена за 7 суток и более до старта потока — полный возврат, позже — без возврата. """ if cohort_starts_at - cancelled_at >= FULL_REFUND_PERIOD: return price_kopecks return 0
def describe(left): """Интервал по-русски: «6 сут. 23 ч 59 мин».""" return f"{left.days} сут. {left.seconds // 3600} ч {left.seconds % 3600 // 60} мин"
starts_at = datetime(2026, 11, 2, 10, 0) # старт потокаprice = 3_000_000 # 30 000 руб. в копейкахfor cancelled_at in [datetime(2026, 10, 20, 9, 0), # задолго до старта datetime(2026, 10, 26, 10, 0), # ровно за 7 суток datetime(2026, 10, 26, 10, 1), # на минуту позже datetime(2026, 11, 1, 18, 0)]: # накануне старта refund = refund_on_cancellation(price, starts_at, cancelled_at) print(f"до старта {describe(starts_at - cancelled_at):>18} → возврат {refund / 100:>9.2f} руб.")до старта 13 сут. 1 ч 0 мин → возврат 30000.00 руб.до старта 7 сут. 0 ч 0 мин → возврат 30000.00 руб.до старта 6 сут. 23 ч 59 мин → возврат 0.00 руб.до старта 0 сут. 16 ч 0 мин → возврат 0.00 руб.Что изменилось:
- правило живёт в одном месте, и обе отмены — с сайта и через поддержку — должны вызывать эту функцию;
- граница «ровно 7 суток» решена явно (
>=), и её легко показать эксперту на четырёх примерах выше; - имена взяты из языка школы: поток (cohort), отмена (cancellation), возврат (refund), старт потока; деньги — в копейках, как договорились в глоссарии;
- докстринг пересказывает правило словами, которые эксперт узнает.
Это ещё не DDD — это первый шаг: одно правило, одно место, слова бизнеса. В модуле DDD.3 правило переедет в модель: появятся объект-значение «Деньги» (Money) вместо голых копеек и агрегат «Поток», который сам следит за своими правилами. Но направление движения видно уже сейчас.
Упражнение на 15 минут. Вспомните проект, в котором вы участвовали или который хорошо знаете как пользователь: доставку еды, запись к врачу, интернет-магазин. Выпишите пять правил этого бизнеса с числами («заказ можно отменить, пока курьер не выехал», «приём переносится не позже чем за 24 часа»). Для каждого ответьте: живёт ли оно в одном месте? Кто в компании может подтвердить, что оно верно? По таблице из раздела «Когда DDD окупается» решите, нужен ли этому проекту DDD целиком, частично или вовсе не нужен.
Проверь себя
Заголовок раздела «Проверь себя»- Сложность бывает существенной (правила бизнеса) и привнесённой (инструменты и решения). Код расходится с бизнесом, когда правила размазаны, а слова в коде не совпадают со словами экспертов. Итог — «большой ком грязи» и падающая скорость команды.
- Предметная область — то, чем занимается бизнес. Модель — отобранное под задачу знание о ней. В DDD модель живёт одновременно в словах, документах и коде и вырабатывается вместе с экспертами.
- DDD (Эрик Эванс, 2003) сводится к трём тезисам: сосредоточиться на основном поддомене, исследовать модели вместе с экспертами, говорить на едином языке в явных границах. У подхода две половины: стратегическое проектирование (части, границы, связи) и тактическое (как выразить модель в коде).
- DDD окупается при сложных, меняющихся правилах в долгоживущей системе и лишний в простом CRUD и прототипе. Его можно применять частично: единый язык полезен почти всегда, полный тактический арсенал — только в ядре.
- Сквозной пример программы — онлайн-школа из шести частей с самыми насыщенными правилами в Наборе. Программа: четыре модуля, около 40 часов, две домашние работы; модель предметной области из DDD становится входом для спецификаций в программе SDD.
Дальше: урок DDD.1.2 — единый язык. Заведём глоссарий онлайн-школы, которым будет пользоваться вся программа, научимся вырабатывать язык с экспертами на примерах и переименуем «технический» код так, чтобы его мог прочитать методист.