Организация модульного монолита
В прошлый раз рассмотрели что такое модульный монолит и откуда возникла сама идея. Сегодня начнем рассматривать как организовать модульный монолит.
❤ Сердце Модульного Монолита: Ясная Структура
Главная цель модульного монолита — это ограничение зависимостей и четкое разделение ответственности. Это достигается за счёт продуманной структуры организации кода.
Заповеди модульного монолита:
- 🗺 Границы священны: Модуль НЕ ДОЛЖЕН знать о внутренностях другого модуля.
- 🔒 Инкапсуляция - закон: Внутренняя реализация модуля — его личное дело.
- 📜 Контракты - наше все: Общение ТОЛЬКО через публичные интерфейсы (API, команды, события).
- 🧪 Тесты - страховка: Без хороших тестов (особенно интеграционных на стыках модулей) границы размываются. А архитектурные тесты еще лучше (ArchUnit)
Организация кода
Сначала, необходимо выявить модули и их границы. Только нужно использовать подход бизнес-ориентированный (привет DDD). Далее переходим к организации кода. Схематически наше приложение должно выглядеть как на картинке к посту. Если мы используем Java то наши модули могут быть организованы в нескольких вариантах.
Рассмотрим два из них. Предположим. что наше приложение - интернет магазин, у нас есть домены - Users, Products, Orders.
Вариант 1 - разбиваем на модули внутри одного артефакта:
В этом варианте мы разделяем на модули в каталоге с исходными кодами:
В этом случае необходимо добавить тесты при сборке, чтобы выявить нарушение границ модулей. Для этого отлично подойдет ArchUnit - библиотека для проверки архитектуры приложения - зависимости между пакетами и классами, уровнями и срезами и многое другое.
Вариант 2 - каждый модуль вынесен в отдельный модуль сборки:
Этот вариант более жесткий - здесь мы для каждого модуля создаем свой артефакт. Также можно запретить при сборке использовать в других модулях все, кроме классов, находящихся в пакете api:
📌 Правила организации модулей
- Четкое разделение обязанностей: Каждый модуль должен отвечать за выполнение конкретной задачи.
- Минимизация связей между модулями: Необходимо минимизировать зависимости между разными частями приложения. Чем меньше взаимных ссылок между модулями, тем лучше.
- Использование абстракций: Создавать интерфейсы и абстрактные классы, позволяющие скрыть внутреннюю реализацию модулей.
- Инкапсуляция внутренних деталей: Использовать паттерн проектирования Facade, чтобы скрыть внутреннюю реализацию.
Подпишись на мой телеграм-канал