Организация модульного монолита

Организация модульного монолита

В прошлый раз рассмотрели что такое модульный монолит и откуда возникла сама идея. Сегодня начнем рассматривать как организовать модульный монолит.

❤ Сердце Модульного Монолита: Ясная Структура

Главная цель модульного монолита — это ограничение зависимостей и четкое разделение ответственности. Это достигается за счёт продуманной структуры организации кода.

Заповеди модульного монолита:

  • 🗺 Границы священны: Модуль НЕ ДОЛЖЕН знать о внутренностях другого модуля.
  • 🔒 Инкапсуляция - закон: Внутренняя реализация модуля — его личное дело.
  • 📜 Контракты - наше все: Общение ТОЛЬКО через публичные интерфейсы (API, команды, события).
  • 🧪 Тесты - страховка: Без хороших тестов (особенно интеграционных на стыках модулей) границы размываются. А архитектурные тесты еще лучше (ArchUnit)

Организация кода

Сначала, необходимо выявить модули и их границы. Только нужно использовать подход бизнес-ориентированный (привет DDD). Далее переходим к организации кода. Схематически наше приложение должно выглядеть как на картинке к посту. Если мы используем Java то наши модули могут быть организованы в нескольких вариантах.

Рассмотрим два из них. Предположим. что наше приложение - интернет магазин, у нас есть домены - Users, Products, Orders.

Вариант 1 - разбиваем на модули внутри одного артефакта:

В этом варианте мы разделяем на модули в каталоге с исходными кодами:

. ├── pom.xml └── src └── main ├── java └── org └── kit └── example ├── ModularMonolithApplication.java ├── orders │ ├── api │ ├── controller │ ├── persistent │ └── service ├── products │ ├── api │ ├── controller │ ├── persistent │ └── service └── users ├── api ├── controller ├── persistent └── service

В этом случае необходимо добавить тесты при сборке, чтобы выявить нарушение границ модулей. Для этого отлично подойдет ArchUnit - библиотека для проверки архитектуры приложения - зависимости между пакетами и классами, уровнями и срезами и многое другое.

Вариант 2 - каждый модуль вынесен в отдельный модуль сборки:

Этот вариант более жесткий - здесь мы для каждого модуля создаем свой артефакт. Также можно запретить при сборке использовать в других модулях все, кроме классов, находящихся в пакете api:

. ├── pom.xml ├── orders │ ├── pom.xml │ └── src │ └── main │ └── java │ ├── api │ ├── controller │ ├── persistent │ └── service ├── products │ ├── pom.xml │ └── src │ └── main │ └── java │ ├── api │ ├── controller │ ├── persistent │ └── service ├── src │ └── main │ └── java │ └── org │ └── kit │ └── example │ └── ModularMonolithApplication.java └── users ├── pom.xml └── src └── main └── java ├── api ├── controller ├── persistent └── service

📌 Правила организации модулей

  • Четкое разделение обязанностей: Каждый модуль должен отвечать за выполнение конкретной задачи.
  • Минимизация связей между модулями: Необходимо минимизировать зависимости между разными частями приложения. Чем меньше взаимных ссылок между модулями, тем лучше.
  • Использование абстракций: Создавать интерфейсы и абстрактные классы, позволяющие скрыть внутреннюю реализацию модулей.
  • Инкапсуляция внутренних деталей: Использовать паттерн проектирования Facade, чтобы скрыть внутреннюю реализацию.

Подпишись на мой телеграм-канал

Начать дискуссию