что такое доменный объект
Domain Object (рус. «Доменный объект») — один из наиболее популярных подходов к использованию тестовых данных непосредственно в логике скриптов. На данный момент является одним из самых популярных и распространенных approach’ей, благодаря своей простоте, понятности и логичности.
Применим во всех видах автоматизации функционального тестирования (End-to-End, API, Integration), в независимости от проверяемой платформы, будь то Web, Mobile, или Desktop.
ВАЖНО: не стоит путать Domain Object с Data Transfer Object (DTO). Это абсолютно разные подходы, которые применяются в разных сферах.
Из другого названия подхода — «Business Object» — становится понятно, что это некая абстракция, представляющая собой модель и описание объекта, который важен именно для понимания и функционирования бизнес-логики приложения. Он не способен выполнять никаких функций, кроме «переноса» полей и их значений одного конкретного business-unit’а.
Как это выглядит
В качестве примера, возьмем любое приложение, где предусмотрено создание аккаунта пользователя. Именно пользователь и становится нашим доменным объектом. Практически во всех случаях, у юзера должны быть логин и пароль:
Особенно внимательные заметят, что все внутренние поля являются private. Задавать и считывать значения напрямую из полей объекта считается плохой практикой. Вместо этого принято использовать всем хорошо известные геттеры и сеттеры:
Теперь, мы получили доступ к полям, и можем задавать и считывать их значения. Но в данном примере у нас используется только два поля. А что произойдет, если этих полей будет пятнадцать? Верно, класс User разрастется до невиданных размеров, благодаря бесконечной копипасте getter’ов и setter’ов. Как же мы будем с этим справляться?
Магия Lombok
Здесь нам на помощь приходит Project Lombok — популярная библиотека, которая позволяет сократить код в несколько раз, избежать copy/paste-страданий, и значительно уменьшить количество времени на написание Data Object-классов. Несколько полезных ссылок:
Просто, быстро, удобно. Таким образом, наш код становится гораздо читабельнее, классы — лаконичнее, а разработка — быстрее.
Применяем в тесте
Хороший тест — это тест, в котором четко разделены тестовые данные, тестовая логика, и ее реализация.
Попробуем залогинить нашего пользователя. Создаем класс с тестовыми данными, и «наполняем» ими нового User’а:
Описываем модель Login-страницы:
Осталось только реализовать тестовый класс:
Подведем итоги
В финале мы получаем аккуратную архитектуру проекта, с четким разделением логики, данных, и реализации. Lombok помогает избавиться от дублирования кода, Domain Object замечательно вписывается в философию Page Object, а поддержка кода становится сплошным удовольствием.
Должны же быть минусы?
Что такое Доменный объект и Предметная область, простым языком?
Доменный объект должен содержать всю бизнес-логику для работы с данным объектом.
Так же интересует, что означает «Уровень объектов предметной области» и «Уровень модели предметной области». О которых говорится в Вики
Предметная область — множество всех сущностей и их отношений в рамках контекста.
Например:
В рамках магазина это покупатели, продавцы, товары, цены, скидки, поставщики, процесс продажи, прихода на склад, возврата и т.п.
В рамках дискорда это пользователи, серверы, комнаты, группы, права на доступ, процессы присоединения к серверу, входа в комнату, оплаты nitro, написания текстового сообщения и т.п.
В целом, это всё, что понимает твой менеджер и ничего, что он не понимает. В предметную область не входит, например, то, где именно ты хранишь данные — в mysql, в файлах, получаешь и сохраняешь их по API или хранишь их в redis’е. Но входит абстрактная сущность «хранилище». Она же — интерфейс репозитория. Репозиторий — это паттерн, который скрывает реализацию конкретного хранилища и который оперирует объектами доменной модели — элементами предметной области, как будто они хранятся у тебя в оперативной памяти. Например, у репозитория могут быть методы и т.п. Реализация репозитория определяет, куда именно сохранится этот user или откуда он скачается. В одну таблицу или в несколько. Нормализованные ли будут данные лежать в РСУБД или денормализованные. Именно здесь можно реализовать запись в master, а чтение с реплик. Или энкодинг в msgpack и передачу его по API куда-то. Или по gRPC. Потому что предметная область не должна перегружаться деталями реализации хранилищ.
Про доменную модель:
Словарь (он же хэш, он же ассоциативный массив) — это не доменная модель (хотя в некоторых функциональных языках может быть). Объект ORM — это тоже не доменная модель, хотя много где пытается ей быть. Доменная модель не зависит от конкретных фреймворков, баз данных, оптимизаций этих баз и прочих навязанных технической составляющей сущностей. Чаще всего это обычный класс на языке, на котором пишется код (или struct в случае Golang).
Доменные модели бывают богатыми и анемичными (но не бескровными). Оба подхода применяются и, имхо, не является антипаттерном ни один из них. Лично я использую анемичные модели, а всю бизнес-логику храню в службах.
Еще несколько уточнений.
1. Какие запросы должны присутствовать в репозитории. Самые простые CRUD для работы с объектом. Или так же более специфические. К примеру, выборка колонок, простой список постов (заголовки и дата) или полный список, со всеми данными.
Если описать все возможные потребности программы в один интерфейс он станет очень «жирным». Куда лучше вынести такую логику, в Сервис? Или создать отдельный интерфейс и реализацию, только для чтения. Сюда же можно отнести получение отношений сущности. Так же вынести в Сервис который будет работать с разными репозиториями?
2. Насколько я понял, так же в интерфейсе репозитория нужно сразу описывать тип возвращаемых и принимаемых данных (доменный объект). Репозиторий не должен работать с «сырыми данными».
Как должна работать система в моем понимании.
1. Interface Segregation Principle. Нет ничего страшного в том, чтобы для одной сущности было больше одного репозитория. Запросы могут быть далеко не CRUD. Репозиторий — это хоть и коллекция, которая симулирует наличие всех бизнес-объектов в ОЗУ, но не стоит забывать, что это в первую очередь коллекция, а не просто словарь или список. У неё тоже может быть логика. В том числе, а аргументах методов можно указывать limit/offset, список полей, которые нужны от сущности. Хотя, последнее я бы делал очень осторожно, и, возможно, сделал бы отдельные методы или даже репозитории для тонких read-моделей. И только в случае, когда это действительно нужно. Скажем, если у вас тысячи запросов в секунду на чтение и кэша почему-то нет или его нельзя поставить.
2. Не понял и не хочу, если честно, понимать схемы:) Но как минимум, мне непонятно, почему сервис не использует интерфейс.
Доменный объект
Доменные объекты — это объекты в объектно-ориентированных компьютерных программах, выражающие сущности из модели предметной области, относящейся к программе, и реализующие бизнес-логику программы. Например, программа, управляющая заказами, может содержать такие доменные объекты, как «заказ», «позиция заказа», «счёт-фактура».
Доменные объекты инкапсулируют всю необходимую для программы информацию об объекте предметной области. Так, например, реальный сотрудник может иметь фамилию, имя, отчество, пол, возраст (модель предметной области), но, если в программе используются только фамилия и имя, то именно они будут включены в качестве атрибутов доменного объекта (уровень объектов предметной области).
Содержание
Использование термина
Термин доменный объект (англ. domain object ) буквально переводится на русский язык как «объект предметной области», однако этот термин русскоязычными программистами используется только в контексте создания программного обеспечения (в то время как в бизнес-моделировании может использваться термин бизнес-объект (англ. business object )). Термин объект предметной области является наиболее общим.
См. также
Ссылки
Литература
Полезное
Смотреть что такое «Доменный объект» в других словарях:
Инстанциирование — Объект некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов)[1]. Как правило, при рассмотрении объектов выделяется то, что… … Википедия
Инстанцирование — Объект некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов)[1]. Как правило, при рассмотрении объектов выделяется то, что… … Википедия
Экземпляр (программирование) — Объект некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов)[1]. Как правило, при рассмотрении объектов выделяется то, что… … Википедия
Экземпляр класса — Объект некоторая сущность в виртуальном пространстве, обладающая определённым состоянием и поведением, имеет заданные значения свойств (атрибутов) и операций над ними (методов)[1]. Как правило, при рассмотрении объектов выделяется то, что… … Википедия
Объектно-ориентированное программирование — Эта статья во многом или полностью опирается на неавторитетные источники. Информация из таких источников не соответствует требованию проверяемости представленной информации, и такие ссылки не показывают значимость темы статьи. Статью можно… … Википедия
ООАП — Объектно ориентированное программирование (ООП) парадигма программирования, в которой основными концепциями являются понятия объектов и классов (либо, в менее известном варианте языков с прототипированием прототипов). Класс это тип, описывающий… … Википедия
Объектно-ориентированный подход — Объектно ориентированное программирование (ООП) парадигма программирования, в которой основными концепциями являются понятия объектов и классов (либо, в менее известном варианте языков с прототипированием прототипов). Класс это тип, описывающий… … Википедия
ORM — также может означать: англ. Object Role Model, рус. Модель ролей объекта методика концептуального проектирования информационных систем, включающая собственную графическую нотацию. Содержание 1 Задача … Википедия
Домен — (фр. domaine) область; единица структуры: В Викисловаре есть статья «домен» … Википедия
Бизнес-логика — в разработке информационных систем совокупность правил, принципов, зависимостей поведения объектов предметной области (области человеческой деятельности, которую система поддерживает). Иначе можно сказать, что бизнес логика это реализация правил… … Википедия
Что такое Доменный объект и Предметная область, простым языком?
Доменный объект должен содержать всю бизнес-логику для работы с данным объектом.
Так же интересует, что означает «Уровень объектов предметной области» и «Уровень модели предметной области». О которых говорится в Вики
Предметная область — множество всех сущностей и их отношений в рамках контекста.
Например:
В рамках магазина это покупатели, продавцы, товары, цены, скидки, поставщики, процесс продажи, прихода на склад, возврата и т.п.
В рамках дискорда это пользователи, серверы, комнаты, группы, права на доступ, процессы присоединения к серверу, входа в комнату, оплаты nitro, написания текстового сообщения и т.п.
В целом, это всё, что понимает твой менеджер и ничего, что он не понимает. В предметную область не входит, например, то, где именно ты хранишь данные — в mysql, в файлах, получаешь и сохраняешь их по API или хранишь их в redis’е. Но входит абстрактная сущность «хранилище». Она же — интерфейс репозитория. Репозиторий — это паттерн, который скрывает реализацию конкретного хранилища и который оперирует объектами доменной модели — элементами предметной области, как будто они хранятся у тебя в оперативной памяти. Например, у репозитория могут быть методы и т.п. Реализация репозитория определяет, куда именно сохранится этот user или откуда он скачается. В одну таблицу или в несколько. Нормализованные ли будут данные лежать в РСУБД или денормализованные. Именно здесь можно реализовать запись в master, а чтение с реплик. Или энкодинг в msgpack и передачу его по API куда-то. Или по gRPC. Потому что предметная область не должна перегружаться деталями реализации хранилищ.
Про доменную модель:
Словарь (он же хэш, он же ассоциативный массив) — это не доменная модель (хотя в некоторых функциональных языках может быть). Объект ORM — это тоже не доменная модель, хотя много где пытается ей быть. Доменная модель не зависит от конкретных фреймворков, баз данных, оптимизаций этих баз и прочих навязанных технической составляющей сущностей. Чаще всего это обычный класс на языке, на котором пишется код (или struct в случае Golang).
Доменные модели бывают богатыми и анемичными (но не бескровными). Оба подхода применяются и, имхо, не является антипаттерном ни один из них. Лично я использую анемичные модели, а всю бизнес-логику храню в службах.
Еще несколько уточнений.
1. Какие запросы должны присутствовать в репозитории. Самые простые CRUD для работы с объектом. Или так же более специфические. К примеру, выборка колонок, простой список постов (заголовки и дата) или полный список, со всеми данными.
Если описать все возможные потребности программы в один интерфейс он станет очень «жирным». Куда лучше вынести такую логику, в Сервис? Или создать отдельный интерфейс и реализацию, только для чтения. Сюда же можно отнести получение отношений сущности. Так же вынести в Сервис который будет работать с разными репозиториями?
2. Насколько я понял, так же в интерфейсе репозитория нужно сразу описывать тип возвращаемых и принимаемых данных (доменный объект). Репозиторий не должен работать с «сырыми данными».
Как должна работать система в моем понимании.
1. Interface Segregation Principle. Нет ничего страшного в том, чтобы для одной сущности было больше одного репозитория. Запросы могут быть далеко не CRUD. Репозиторий — это хоть и коллекция, которая симулирует наличие всех бизнес-объектов в ОЗУ, но не стоит забывать, что это в первую очередь коллекция, а не просто словарь или список. У неё тоже может быть логика. В том числе, а аргументах методов можно указывать limit/offset, список полей, которые нужны от сущности. Хотя, последнее я бы делал очень осторожно, и, возможно, сделал бы отдельные методы или даже репозитории для тонких read-моделей. И только в случае, когда это действительно нужно. Скажем, если у вас тысячи запросов в секунду на чтение и кэша почему-то нет или его нельзя поставить.
2. Не понял и не хочу, если честно, понимать схемы:) Но как минимум, мне непонятно, почему сервис не использует интерфейс.
Ценности DDD
Основоположником DDD (Domain Driven Design, предметно-ориентированное проектирование) является Эрик Эванс, который в довольно далеком 2003 году подарил миру свою знаменитую книгу о предметно-ориентированном проектировании. Безусловно, не все, что описано в книге придумал автор с нуля. Многие идеи и практики существовали и до него, но у Эванса получилось все это систематизировать и правильно расставить акцента. Давайте попробуем разобраться, что же именно предлагает Эванс.
На мой субъективный взгляд DDD стоит на трех основных столпах (и это если что не три буквы Д):
Доменная модель
Transaction Script и Domain Model
If all your logic is in services, you’ve robbed yourself blind.
В качестве альтернативы выступает понятие доменной модели. Доменная модель создается, как некое подобие реального мира. Например, если мы разрабатываем ПО для ресторанов и доставки блюд, то наверняка в такой модели нам встретятся такие объекты как: ресторан, блюдо, курьер и может быть, что-то еще при более детальном рассмотрение предметной области.
В отличие от Transaction Script, где логика содержится в сервисах, а данные в сущностях, в доменной модели и логика и данные размещены в доменных объектах. Согласно идеям объектного-программирования такие объекты инкапсулируют свое внутреннее состояние, а для работы с ним предоставляют вполне определенный внешний интерфейс. Например, у объекта корзины может быть метод добавления товара. Тут можно возразить и сказать, что у нашей сущности вполне может быть сеттер для добавления товара.
Да, все это верно. Но не стоит забывать, что в идеале класс корзины должен соблюдать ряд бизнес-инвариантов. Например, после добавления товара в корзину, итоговая стоимость корзины должна увеличится на сумму добавленных товаров. В подходе Transaction Script данная логика размещается в сервисе. Но при таком раскладе соблюдение инвариантов не обеспечивается ничем, кроме хороших тестов и внимательности программиста. Существует не нулевая вероятность, что в каком-то другом сервисе проявится ошибка и он изменит данные корзины неверным образом. В случае же с доменной моделью, за корректность изменения данных (за соблюдение инвариантов) отвечает только один объект сама корзина (может быть еще ее «внутренние классы», но опять же об этом мы не знаем, за счет соблюдения подхода сокрытия информации). Таким образом мы формируем абстракцию корзины, с которой должны взаимодействовать другие классы модели, через ее определенный интерфейс, а не влияя напрямую на ее внутреннее состояние. Также автоматически начинают соблюдаться еще и такие принципы, как SRP (принцип единственной ответственности), low coupling и high cohesion (слабая внешняя связанность и высокое внутреннее зацепление).
Эванс ставит во главу угла именно доменную модель. Доменная модель в первую очередь позволяет сосредоточится на бизнес-задаче и отвлечься от технических вопросов, связанных с сохранением данных, передачей информации в веб и прочим. Это своего рода еще один уровень абстракции, самый высокий уровень, в котором, по сути присутствуют только бизнес-понятия. Эванс говорит, что код доменного уровня программист может изучать даже вместе со специалистом предметной области. И при небольших комментариях разработчика доменный эксперт вполне должен понимать исследуемый код, т.к. в нем, в хорошей модели, должны фигурировать знакомые ему бизнес-понятия и выполняться знакомые бизнес-операции. Тем самым мы приходим к такому понятию как Единый язык, который в DDD занимает одно из самых значимых мест.
Единый язык
Единый язык — это некий набор терминов, относящихся к разрабатываемой доменной модели, который использует команда разработки в общение между собой. Важно заметить, что в состав команды входят не только разработчики, но и бизнес-эксперты. Единый язык — это не язык программистов, так же это и не язык бизнес-аналитиков. Единый язык — это своего рода некое смешение, которое возникает в результате совместной работы этих двух категорий специалистов. Это позволяет, как программистам при общении с доменными экспертами более погрузиться в предметную область, так и специалистам предметной области понять, что же все же пытаются создать разработчики (Безусловно, доменные эксперты должны иметь поверхностное представление об объектно-ориентированном моделировании, они не должны впадать в ступор только лишь при упоминании таких слов, как класс и объект). При этом доменные эксперты могут дать обратную связь разработчикам даже до момента написания первой строчки кода. Во время анализа способов использования системы (use cases) разрабатываемой системы, обсуждение, которых должно вестись с активным применением терминов из словаря Единого языка.
DDD — это про общение между людьми, одна из его задач — сломать имеющийся «языковой барьер» между бизнесом и разработкой.
В конечном счете единый язык переносится в доменную модель, а затем реализуются в коде. DDD продвигает идею общения на одном языке между программистами и доменными экспертами и вовлеченности в работу друг друга. Это особенно важно в сложных предметных областях, где на первом месте стоит однозначное взаимопонимание и точность переноса бизнес-требований в код.
Размышляя на тему DDD и хорошо проработанной доменной модели у меня всегда возникает ассоциация с небезызвестным высказыванием:
Сначала ты работаешь на репутацию, а потом она работает на тебя.
Хорошую доменную модель не легко построить, но в какой-то момент окажется, что дальнейшие изменения вносятся, как по маслу. Модель развивается логичным образом, сложность внесения изменений предсказуема, а результат управляем. И в этот момент модель начинает работать уже на тебя.
Ограниченный контекст
Тут уже все несколько посложнее. Есть понятие предметная область, она же и есть домен (domain). Это та сфера деятельности, в которой работает наш бизнес. Например, тот же самый e-commerce, доставка еды из ресторанов, бухгалтерская сфера или что-то иное. В любом случае это весьма обширная сфера и при разработке ПО нет смысла моделировать всю эту огромную область.
Практически всегда в нашей предметной области есть подобласти (subdomain). Подобласти это своего рода отдельно взятые «боли» бизнеса, т.е. это бизнес-проблема, бизнес-задача, которую требуется решить в нашем случае за счет автоматизации. Например, нам может требоваться автоматизация для формирования заказов, для производства товаров, для их доставки. Все это разные подзадачи из одной и той же предметной области. Можно переформулировать иначе. На предприятии могут быть разные подразделения: производство, доставка и служба продаж принимающая заказы и наша цель состоит в разработке ПО для данных подразделений предприятия.
Разное использование понятий в зависимости от контекста
Примечательно то, что в этих подобластях могут встречаться понятия названия, которых совпадают, но в зависимости от подобласти каждое из понятий может использоваться по-разному.
Например, заказ для отдела продаж содержит информацию о покупателе, набор заказанных товаров. Он может предоставлять такие методы, как изменение статуса или выполнение возврата. Для службы доставки столь подробная информация не требуется, курьеру понадобится знать вес и габариты заказа, но вовсе не обязательно знать, что внутри. В свою очередь, если заказ передается на производство, то там не требуется информация о клиенте и о ценах. Для производства важно, то что требуется сделать, т.е. только сами товарные позиции. Также у понятия заказа в разных подразделениях может быть абсолютно различный жизненный цикл. Понятие заказ для разных подразделений отличается не только разными данными, но и различным поведением. Мы видим, что казалось бы одно и то же понятие может использоваться по-разному. Можно прийти к выводу, что такие понятия должны и моделироваться по-разному. В виде различных классов, размещенных в различных моделях.
Также если продолжить анализ задач наших подразделений, то непременно всплывут и такие понятия, которые никак не пересекаются и не накладываются друг на друга. Например, в службе приема заказов, может появиться понятие корзины покупателя, которое отсутствует как в производстве так и в доставке. В службе производства вполне может быть понятие материала или некого ресурса. А в службе доставки может существовать такое понятие как интервал доставки, которого также нет ни в одном из других подразделений.
Давайте зайдем с другой стороны. К нам пришел клиент, мы начинаем анализировать предметную область, накидываем черновые диаграммы классов и диаграммы взаимодействий. И на этом этапе уже вполне может быть возможно увидеть потенциальные границы субдоменов.
При этом некоторые классы, например, тот же заказ оказывается на проведенной границе. Такие пограничные классы мы можем рассмотреть с позиций их функций в контексте подобластей, к которым они относятся. В ходе анализа может выясниться, что для одной подобласти эти классы выполняю одну роль, а для другой другую. Это опять же наталкивает на мысль, что подобные понятия следует моделировать по-разному. Когда данные пересекают границу подобластей, должно происходить отображение одного граничного объекта на другой, из второй подобласти.
Области задач и области решений
Вон Вернон рассматривает субдомены, как области бизнес-задач, а ограниченные контексты, как области решений.
Ограниченный контекст — подмножество более большой доменной модели. Можно сказать, что ограниченный контекст строится, как отдельная уменьшенная доменная модель с использованием терминов единого языка, характерных для выбранной подобласти.
Ограниченный контекст представляется как реализация узкоспециализированной модели, которая не пытается охватить все и сразу и в которой нет противоречий. Единый язык в данном случае является тем инструментом, который помогает этого достичь.
В идеале должно быть однозначное соответствие между субдоменами и ограниченными контекстами. Но может быть и иначе, например, у нас может быть единое монолитное приложение без четких внутренних границ, которое пытается автоматизировать задачи сразу всего предприятия. Такое приложение можно рассматривать как один большой ограниченный контекст. Это приводит к формированию слишком большой модели, которая со временем может обрастать запутанной логикой, непонятными взаимосвязями и такую модель становится сложно понимать, развивать и поддерживать.
Ограниченный контекст — это то, что призвано улучшить доменную модель, сосредоточившись на лишь на одной подобласти. Это инструмент призванный ограничить размер модели.
Ограниченный контекст как способ декомпозиции системы
Идея ограниченного контекста это своего рода желание декомпозировать большую систему на более простые компоненты, с которыми понятней и более удобно работать. Также можно сказать, что данная идея реализует все те же принципы проектирования SRP, low coupling и high cohesion, но только на более высоком уровне. Об этом также говорит принцип CCP (Common Closure Principle), который похож на SRP, но только для классов, изменяющимся по одной и той же причине и следовательно должны находится вместе, например, в одном пакете. Также эта идея отлично согласуется с другими подходами, например, с микро сервисной архитектурой и с гибкими командами в Agile.
Закон Конвея
Организации проектируют системы, которые копируют структуру коммуникаций в этой организации
Даже когда я приводил пример с подразделениями организации, то невольно рассматривалась декомпозиция системы по бизнес-возможностям предприятия, которые уже структурированы определенным образом. Что на мой взгляд перекликается с законом Конвея.
Декомпозицию на основе объектно-ориентированного анализа можно рассматривать как альтернативный подход, который более точно моделирует исследуемую предметную область. Такое моделирование может даже выявить неэффективную (слишком запутанную, с сильным связыванием) структуру подразделений в нашем бизнесе.
Например, Обратный маневр Конвея рекомендует развивать команду и структуру организации для продвижения желаемой архитектуры.
Агрегаты
Если ранее по большей мере речь шла о так называемых стратегических шаблонах DDD, то сейчас хочется сказать пару слов в самом интересном на мой взгляд тактическом шаблоне, об Агрегате.
Приходилось ли вам в коде видеть что-то подобное?
Данный код представляет своего рода довольно глубокий обход графа объектов нашей предметной модели. В нашей модели имеются несколько объектов-сущностей: Payment, Order, Account, Client И Address. И все эти объекты имеют некоторые связи друг с другом. B это довольно знакомая и распространенная ситуация. И само собой такая тесная связь между объектами вызывает и большую связанность самого кода. И это даже не говоря о том, что такая связь может быть не всегда обязательной и тем самым, подобный невнимательный обход объектов может вызывать исключение NullPointerException.
Подход DDD предлагает разбить большой граф объектов всего приложения на слабосвязанные агрегаты, которые представляют собой совокупность тесно связанных объектов. Агрегаты не используют ссылочное связывание объектов. Вместо этого модель осуществляет взаимодействие агрегатов по идентификаторам. Внутри агрегата объекты могут связываться друг с другом по ссылке. Агрегат инкапсулирует все свои внутренние объекты и предоставляет интерфейс для работы с ним. Модель должна использовать только этот интерфейс, но не взаимодействовать с внутренними объектами агрегата напрямую.
Агрегат как граница транзакционной согласованности
Когда говорят про агрегаты не редко упоминают транзакционную согласованность этих агрегированных объектов. Например, в качестве агрегата, можно рассмотреть корзину товаров. Корзина помимо своих основных свойств таких, как подытог, скидка и итоговая сумма содержит такие объекты как CartItem. Данный объект представляет элемент корзины и может содержать такие свойства, как добавленный товар и его количество, а также может вычислять подытог, как произведение количества на стоимость товара. Агрегат корзина (как и любой доменный объект) обеспечивает необходимые бизнес-инварианты (например, пересчет стоимости при добавление еще одного товара). Также очевидно, что при сохранении корзины должны одновременно сохраняться и ее элементы в рамках одной транзакции, что удовлетворяет транзакционной согласованности.
По этому при проектировании агрегата всегда можно задаться вопросом:
А должны ли эти объекты сохраняться вместе?
Агрегаты и границы ограниченных контекстов
Агрегаты — это тот инструмент, который помогает разделить модель на слабосвязанные ограниченные контексты.
На мой взгляд, самое интересное в агрегатах это то, что они дают право на ошибку при определении границ ограниченных контекстов. Ведь эти границы нигде не прописаны жестко и вполне могут изменяться с развитием модели и более глубоким пониманием исследуемой области. Может возникнуть потребность разбить имеющийся большой ограниченный контент на несколько поменьше, или наоборот объединить слишком конкретизированные контексты вместе или быть даже сместить границу и выполнить перенос одного или нескольких агрегатов в соседний контекст. Все эти манипуляции становятся намного проще из-за слабой связанности агрегатов.
Агрегаты и событийно-ориентированный архитектура
DDD уменьшает связанность за счет использования Агрегатов. Но агрегаты, как и любые объекты должны взаимодействовать друг с другом. В DDD это взаимодействие осуществляется за счет публикации событий. В ходе жизненного цикла и изменение своего состояния агрегат может генерировать различные события, которые могут быть приняты и обработаны в другой части модели. Событийно-ориентированный подход также помогает снизить связность системы. Использование событий также можно рассматривать, как способ приведения распределенной системы к конечному согласованному состоянию.