В первой статье мы выделили область применения обозначенных практик, для каких проектов их можно применять, а для каких не следует.  В данной статье я хотел бы сделать краткий обзор основных принципов DDD, а также поделиться личным опытом их применения. Более подробно будет рассказано о коммуникационных и структурных подходах с примерами их реализации. В следующих статья распишу возможные комбинации применяемых паттернов проектирования с учетом их имплементации, и в конечном итоге приведу пример конкретной реализации одного небольшого микросервиса. Вспомним данное ранее определение: Эталонной книгой которая описывает практики построения сложных систем является книга Domain Driven Dedign (Big Blue Book) Эрика Эванса. Если вы читали любую обзорную статью по этой теме, вы уже знаете об этом. К моменту применения DDD на практике вам придется ее прочесть. Это не самая легкая книга для восприятия: Если пролистать содержание книги, она покажется вам не совсем структурированной. Но нам поможет карта.
 На карте выделены те практики, которые мы сегодня рассмотрим. Объем рассмотренных в книге практик огромен. Объем практик, которые можно применить за пределами данной книги еще больше. Прежде чем брать на вооружение хотя бы часть их них, обозначьте для себя цели. Приведу в качестве примера свои. Разработка программного обеспечения редко приводит к созданию чего-то нового, как правило, это моделирование чего-то существующего. Мы не можем создать программный продукт, который охватит всю предметную область. Возможно воспроизвести только ту его часть, которая будет воспроизводить необходимый функционал.  Хорошим примером модели будет являться топографическая карта. Она является моделью местности. Карта не содержит лугов полей и рек, она только отражает месторасположение реальных объектов относительно друг друга. Чтобы построить четкую и ясную для всех модель, нужно говорить на одном языке. Об этом нам говорит не только Эрик Эванс, но и здравый смысл. Если программисты будут использовать свои термины, а бизнес свой 'сленг', то первые просто не будут понимать что нужно делать. Бизнес же в этом случае не сможет осознать реальной стоимости разработки той или иной 'фичи'. Сколько раз вам приходилось слышать: "Да это всего лишь добавить кнопку"? Ваша цель, как проектировщика системы, должна быть в том, чтобы добиться от всей команды максимального понимания друг друга. Как же этого добиться? Начните говорить. Если люди начинают общаться в любой тесной группе, у них появляется некий общепринятый набор терминов. В различных компаниях процесс введения общего языка, скорее всего, будет отличаться. Это может быть как волевым решением, так и демократической процедурой. Язык может быть обозначен явно, так и вводиться не явно, в этом случае на нем начинают просто говорить. Хорошим приемом введения общего языка станет общая документация. Пример документации:  Заметим, что в данном примере мы не указали явный словарь, тем не менее мы закрепили понятие , Авторизация, Регистрация. Написание подобной документации не займет у эксперта больше 20 минут.  Для человека, не являющегося экспертом в предметной области, процесс написания документации воспринимается как что-то сложное. Нужно разделять сбор знаний и запись собранных знаний. Документирование != Документирование + Сбор знаний. Представим себе, что мы выступили в роли проектировщика прогрессивного стартапа. Все мы любим остывшую пиццу, ругаться с курьерами и часами заполнять формы на сайте. Поэтому мы придумали замечательный стартап "Четыре черепахи и одна крыса": Давайте вспомним документацию, которую мы описывали в предыдущей главе. Там в нашем едином словаре использовался термин регистрация. Но в данном проекте мы имеем их несколько: Унифицированный язык принадлежит к ограниченному контексту. Домен приведенной выше документации — 'Система авторизации'. Давайте попробуем выделить домены для нашего стартапа. Но прежде чем мы к этому приступим, давайте немного разберемся в терминологии, что такое домен и что такое ограниченный контекст.  Например: Система логистики, Система оплаты, Система авторизации, Система управления заказами. Домен делится на сабдомены, которые описывают меньшие структуры, например: корзина заказов, система построения маршрутов. Каждый домен имеет ограниченную зону ответственности — лимитированную функциональность.  Мне нравится представлять этот термин в виде такой абстракции. Домен — это круг. Ограниченный контекст — это окружность.  Еще в терминологии DDD выделяют ядро.  Итак, домены проекта "Четыре черепахи и одна крыса": Работа с пиццерией (Pizzarias) Контекст: b2b все, что относится к работе с пиццериями Сабдомены: Работа с клиентом (Clients) Контекст: b2c, все что относится к работе с заказчиками пиццы Сабдомены:  Работа с курьерами (Delivery system) Контекст: b2e, все что относится к работе с курьерами Сабдомены:  Система заказов (Order system) Контекст: Ядро. Позволяет координировать все отдельные домены, обеспечивая полный цикл от получения заказа до доставки пиццы пользователю. Не является исполнителем, а исполняет роль дирижера. Сабдомены: Система рассчетов (Billing) Контекст: Содержит в себе все финансовые операции. Обеспечивает взаимодействие с процессинговым центром. Сабдомены: Система статистки (Statistics) Контекст: Сбор и обработка (не выдача) аналитической информации. Сабдомены:  Система менеджмента (Managment panel) Контекст: Выдача аналитической информации. Инструментарий управленческих решений. На основе доменов давайте составим его карту.   Карта показывает связи между доменами. Данная карта очень поверхностна, но и предметная область изучена не достаточно. Это первый набросок, переписывая который вы получите ожидаемый результат.  Самое важное в карте — мы видим связи межу доменами. Такая структура очень хорошо ложится на микросервисную архитектуру: Данный принцип дается в книге Сэма Ньюмана — Создание микросервисов, это вторая книга, которую вам придется прочесть, чтобы приступить к практическому использованию описанных в данной статье подходов. Что имеется в виду: домены должны быть слабо связанны между собой, но тесно сцеплены внутри.  Перевод данных терминов взят из официального русского перевода и, возможно, плохо отражает передаваемый смысл. В оригинале термины звучат как: Low coupling (связанность, зацепление, сцепление, сопряженность), high cohesion (связность, прочность). Хотелось бы поделиться личным опытом — набором осознанных решений. Я не призываю вас использовать эти решения. Но они могут оказаться хорошим выбором, если вы не знаете с чего начать. С получением личного опыта инструментарий будет доработан под ваши нужды. Основные принципы, которыми мы руководствовались: Очень удобно выделять домены как отдельные микросервисы. В DDD-разработке принципом выделения микросервиса в отдельное приложение будет служить ограниченный контекст. Это не отменяет технический принцип разделения сервисов (если это обусловлено необходимостью обеспечения высокой производительности). Но контекстный принцип будет доминирующим и обязательным. Связи между доменами это всегда API. Это может быть RESTful json api, gRPC, AMPQ. Мы не будем в рамках данной статьи сравнивать один протокол с другим и выделять их преимущества и недостатки, у каждого из них есть своя область применения. Но все же, остановимся на общих рекомендациях: Будте гибкими в выборе протокола и жесткими в однотипности его реализации. Выбирайте протокол для каждой пары доменов индивидуально, не старайтесь везде использовать http, возможно, вам где-то понадобится асинхронные очереди и преимущества AMPQ для вас станут очевидными. Не игнорируйте эту возможность потому, что у вас везде RESTful.  С другой стороны, если вы реализуйте RESTful json, используйте один стандарт структуризации данных. Можете взять готовый например jsonapi или openapi. Если по каким-то причинам готовые решения вас не устраивают и вы чувствуете, что можете разработать свой стандарт — опишите и используйте его. Но применяйте его везде, не разводите "зоопарк" стандартов. Если вам нужно общаться с внешней системой, где про ваши стандарты ничего знают, напишите микросервис адаптер.  Как отдельные модули внутри микросервиса. Как это все выглядит? Давайте рассмотрим на примере. Как мы помним, у нас есть домен Работа с курьерами (Delivery system) — у этого домена есть три сабдомена: Представим это все в виде структуры папок: Каждая папка в директории apps/ реализует тот или иной сабдомен, внутри каждого домена есть различные паттерны: entities, forms, services и др. Мы рассмотрим каждый из применяемых паттернов подробно в одной из будущих статей. Каждый такой паттерн реализован в соответствующем пространстве имен (Namespace). Например форма создания завяки на выплату курьеру: Давайте рассмотрим конкретный пример. У нас есть учетная запись курьера: Registrations::Entities::Account. Она относится к сабдомену Registrations — так как мы рассматриваем данный домен не как процесс регистрации, а, скорее, как учетный стол и регистрационную книгу, о чем указанно в нашей документации для бизнеса. У нас есть два Процесса при исполнении которых мы обращаемся к этой учетной записи. Как мы видим эти два процесса относятся к разным сабдоменам — Registration и Wihtdrawal.  В первом обращение ообращение к классу будет реализованно через вызов Entities::Account. А во втором случае через явный вызов Registrations::Entities::Account. Т.е. если мы явно указываем сабдомен, значит класс из другого сабдомена и так мы четко обозначаем связь. Если класс не относится явно ни к одному из сабдоменов, есть смысл выносить его в папку lib/. Как правило, это классы, реализующие паттерн 'ValueObject'. Мы рассмотри этот паттерн подробнее в одной из следующих статей. Процитирую Эрика Эванса: Давайте вспомним пример хорошей модели, который я уже приводил в начале этой статьи — топографическая карта. У нас стоит цель — иметь возможность быстро найти расстояние между двумя населенными пунктами. Мы могли бы воспользоваться справочником-таблицей с указанием двух точек между городами. А можем воспользоваться картой. И там и там мы получим один и тот же результат примерно за одно и то же время. Но карта компактнее, она точнее отображает предметную область, она универсальнее. Карта как модель невероятно выразительна. И если рассматривать ее в рамках данной задачи, то померить расстояние удобнее по карте, чем на самой территории, которую она отражает. Модель, которая отражает предметную область, может превосходить ее в некоторых свойствах. Это действительно потрясает воображение. Реализация модели это всегда творческий процесс с непредсказуемым результатом. Качество вашего кода это не его производительность, и не его сложность, это простота и выразительность. Совершенствуйте его через постоянный рефакторинг, делайте его гибким и отсекайте все лишнее. Разделите слой, который будет отвечать за бизнес логику модели, от слоев, чья необходимость обусловлена технической реализацией. О том, как нам удалось это сделать, будет рассказано в дальнейшем.  Разработчик