Если вы про это не подумаете, то всё просто разъедется. Например, вы затрете последним апдейтом предыдущие изменения. Попутно мы формируем еще одно событие доменно ориентированный подход в разработке по для паттерна Outbox Pattern. Оно сохранится, чтобы и другие модели Bounded Context тоже могли поменяться. У нас работает код консьюмера, который подписан на какое-то брокер-сообщение — на топик Kafka или на очередь в RabbitMQ. Мы храним не объект и не state нашего объекта целиком, а отдельные события, которые этот state меняют.
С чего стоит начать при внедрении DDD?
Во-вторых, непонятно, где ждать Null Reference Exception. Потому что вы не знаете, заполнил ли предыдущий разработчик модель достаточно хорошо, или где-то остановился и вам надо вчитываться в код, или покрывать тестами, или еще что-то делать. В данной статье я расскажу о практиках, принятых в нашей команде (если кратко — мы используем все подходы и ни один из них не является догмой). Покрутили и рассмотрели DDD с разных сторон вместе с Андреем Ратушным — техническим директором компании Югорские Интернет Решения. Не стоит воспринимать статью за единственно верный подход.
Что такое Domain-Driven Design и как его применять
В этой книге поверхностно рассмотрены все вопросы, техники и паттерны, применяемые в DDD, все примеры сопровождаются кодом, что упрощает понимание. Книга превосходная, однако русский перевод подкачал, поэтому, рекомендую прочитать оригинал. Эта книга – отличный практикум по DDD, содержащий очень широкий пласт идей.
Основные концепции Domain-Driven Design
Сервисы — это функции, которые не привязаны к сущностям или ценностным объектам. Наше приложение разделено на слои, которые не зависят от БД, не зависят от фреймворка, который вы решили использовать. Ниже на картинке мы видим, что у нас есть класс Order с полями Id, OrderDate, BuyerId, Address, OrderItems (где последние три будут являтся Value Object). И справа выделен красным один из них — это атрибут Address со своими полями Street, City и т.д. Главный элемент здесь — это Entity (сущность), имеющая уникальный id. Она описывает индивидуально существующие элементы домена и определяется по id, а не по значению каких-то атрибутов.
- Вся суть DDD — использовать единый язык и работать с экспертами в доменной области, чтобы максимально точно отразить бизнес-цели.
- У него есть очень хорошее описание, включающее в себя описание шаблонов и подходов, заключенных в фреймворке.
- Поэтому мы в одной транзакции пишем в БД не только состояние объекта, но и событие, доменный ивент, которое хотели кинуть в RabbitMQ.
- Например, если Bounded Context в вашей CRM связан с продажами, то со временем его можно разделить на продажи и маркетинг.
Функциональные и нефункциональные требования
Когда у вас понятный агрегат с ясными инвариантами, вы можете обсудить с бизнесом или экспертами конкретную часть из своего фокуса. Строить такие объекты тяжело, и в DDD прижилась идея склеить Event Sourcing и CQRS. В итеративной разработке проект разбивается на несколько логически цельных итераций. В каждой итерации проект проходит цикл «Планирование → Реализация → Проверка → Корректировка».
Применение Domain-Driven Design в разработке
Но узкие предметные области, обладающие сложной спецификой, требуют тщательного продумывания на самом высоком уровне. DDD предлагает создавать модели предметных областей, содержащие сложную бизнес-логику. DDD предоставляет набор практик и инструментов для эффективного моделирования и разработки систем, основываясь на понимании и учете предметной области. Он позволяет создавать гибкие, масштабируемые и легко поддерживаемые приложения. Хотя по концепции предметно-ориентированное проектирование не должно быть ограничено какими-либо представлениями, но на практике используются сильные стороны объектно-ориентированного программирования. Это использование наследования, инкапсуляции, представления в виде методов и классов.
Это методология и набор принципов и практик для проектирования сложных программных систем, сосредоточенных на предметной области бизнеса. Основной принцип работы по DDD — разделение предметной области на ограниченные контексты со своими языками описания. Так, без DDD модель «пользователь» описывает все роли, и поэтому очень разрастается. Она описывает и посетителей сайта (имя пользователя, адрес), и данные авторизации (когда пользователь зашел в систему), и разграничения прав доступа для модераторов. В DDD такая модель разделяется на отдельные модели для каждого ограниченного контекста, чтобы не возникало путаницы.
Так как код мы исправили, то и отображаемое состояние объекта тоже становится правильным. А во-вторых, мы получаем от Event Sourcing легкое исправление ошибок. Например, кто-то ошибся и написал в коде минус вместо плюса.
Bounded context — это разграничение контекстов (это бизнес функционал, который описан BA). В проектировании микросервисов существует такой паттерн, который называется Domain Driven Design (DDD). Однако, как и любой другой инструмент, DDD требует тщательного изучения и применения. Как видим, DDD адаптивен и эффективен в различных архитектурных стилях, предоставляя гибкость и простоту в решении бизнес-задач.
Посетитель, модератор, администратор — это разные типы пользователей, каждый из которых относится к своей области. Мы использовали подход Domain-Driven Design для создания информационной системы «Абитуриент», которая автоматизировала работу приемной комиссии Сибирского федерального университета. В процессе проектирования возникали все новые и новые потребности, архитектура сервиса разрасталась.
Не все заказчики готовы выделить людей в своем штате, которые будут вводить разработчиков в курс дела, оставаться на связи, участвовать в проектировании. Если клиенту нужен сложный, многофункциональный продукт, то придется объяснять ему важность участия. Для решения проблемы могут использоваться модели (model), которые описывают отдельные аспекты предметной области. Пример — сценарии пользовательского поведения на сайте. Человек открывает главную страницу, ему нужно заказать перевозку — он нажимает на кнопку «отправить груз». Рано или поздно мы успеваем между изменениями сохранить.
Это всё сыпется непрерывным потоком в какое-то append-only хранилище. Зачастую это даже не реляционная база данных, а что-то оптимизированное под запись, например, Kafka. Она позволяет писать большое количество событий и очень хорошо с этим справляется. Если у нас Event Sourcing, мы можем легко исправить эту ошибку – достаточно поправить код и развернуть приложение заново. Потому что события у нас правильные, но мы их обрабатывали неправильно.
В подходе Event Sourcing мы вычитываем не баланс, а эвенты. То есть мы подаем какие-то эвенты на вход и реализуем код, который эти эвенты перепроигрывает на голом объекте. Поэтому мы в одной транзакции пишем в БД не только состояние объекта, но и событие, доменный ивент, которое хотели кинуть в RabbitMQ. Если он не доступен, то есть еще дополнительный publisher, промежуточный слой, который смотрит, что неотправленного есть в БД, и отправляет. Или, например, мы не хотим каждый раз читать список задач, пробегая по объектам и спискам.
Гораздо хуже, что код получается запутанным — вы не сможете взять кусочек системы и обособленно его развивать. Трогая какие-нибудь отчеты, вы совершенно неожиданно можете затронуть бэк-офис. Именно в этом ядре концентрируются знания о предметной области, поверх которых потом формируются новые слои со служебной и второстепенной функциональностью. Решение — подход DDD, Domain Driven Design, было предложено Эриком Эвансом в 2003. Но прежде, чем о нем говорить, необходимо немного углубиться в историю развития разработки софта как такового. Есть разные мнения о том, стоит ли создавать собственные типы исключений или использовать стандартные, поставляемые в .NET.
Вариаций много, это все лишь видение автора на тематику вопроса. Я устал от одержимости примитивами и от чрезмерного использования примитивных типов для моделирования функциональной области. Этот проект основан на совместной работе компании Эрика Ивенса “Domain Language” и шведской консалтинговой компании “Citerus”.
Мы их прикапываем, чтобы быстро выводить на вьюшки, но при сохранении планировщика с 10 тысячами задач мы реально сохраним, например, 9999. Такое можно видеть в соцсетях, когда у вас есть три поставленных лайка/notification, а заходишь в notification — и их там нет. Эта неконсистентность возникает, если сохранять объект не в транзакциях. Единый язык включает в себя термины, понятия, и даже фразы для общения в команде. Основные строительные блоки, которые мы видим в Domain-Driven Design — это агрегат, команда и доменное событие.
У бизнеса к полям определенные требования, например целостность, валидность, типизация и т.д. Для проектов, которые не планируют внутри себя какого-то динамического изменения или сложной инфраструктуры, внесения новой бизнес логики и т.д. У нас есть домен (domain), который является бизнес задачей (например “счет на оплату билетов в кино”). Изучение предметной области в данном случае подразумевает не только усвоение терминов, но и осознание того, как функционирует бизнес, какие процессы в нем происходят.
IT курсы онлайн от лучших специалистов в своей отросли https://deveducation.com/ here.