Демонстрационное backend-приложение на Kotlin
с применением Domain-Driven Design, Clean Architecture и Детройтской школы тестирования.
Приложение представляет собой REST API для многопользовательской пошаговой игры.
- Технологический стек
- Применяемые подходы и принципы
- Предметная область
- Архитектура
- Сборка ограниченных контекстов
- Тесты
- Качество кода и архитектуры
- Референсные проекты
- Дальнейшие планы
- Kotlin
- Gradle
- Spring (Web, Data Jdbc, Cloud Stream, Feign)
- Postgres
- Kafka
- Docker, Docker Compose
- Testcontainers
- Detekt, JaCoCo
- ArchUnit
- Domain-Driven Design
- Clean Architecture
- Детройтская (классическая) школа тестирования
- Low Coupling & High Cohesion
- SOLID
- ООП
- ФП
Предметной областью является небольшая пошаговая настольная игра.
В одной партии могут принимать участие от 2 игроков.
Игра происходит на поле, разделенном на клетки (примерно 50х50 клеток).
Суть игры в том, чтобы захватить как можно больше клеток на поле.
Перед началом партии игроки собираются вместе и выбирают параметры партии
(размер поля, свои цвета для обозначения захваченных клеток и тд.).
Каждый игрок совершает ход по очереди. Ход состоит из двух фаз.
Первая фаза - бросок кубиков. Игрок делает бросок двумя кубиками.
Выпавшие значения определяют размер области на поле, которую игрок может захватить.
Вторая фаза - процесс захвата.
Игрок определяет область клеток на карте и производит захват.
Затем передается следующему игроку.
Игра продолжается до тех пор, пока на поле остаются области, доступные для захвата.
Ссылка на доску в Miro: https://miro.com/app/board/uXjVKcoerYQ=/
В предметной области выявлено 2 поддомена:
- Лобби, где игроки собираются вместе и настраивают будущую партию перед игрой
- Игра, где происходит непосредственный игровой процесс на клеточном поле
Приложение организовано в виде монорепозитория.
Поделено на два микросервиса (ограниченных контекста) и общий модуль (паттерн Shared Kernel).
Каждый микросервис имеет REST API.
Между микросервисами построено событийно-ориентированное взаимодействие посредством Kafka.
Применяемые стратегические паттерны:
- Bounded contexts
- Shared Kernel
Применяемые тактические паттерны:
- Aggregates
- Value Objects
- Domain Events
Каждый микросервис построен по принципам Чистой Архитектуры:
- Трёхслойная структура: адаптеры, юзкейсы, модель предметной области
- Правило зависимостей: верхнеуровневые слои не зависят от низкоуровненых
- Модель предметной области инкапсулирована и не зависит от инфраструктуры
- lobby - ограниченный контекст, в котором игроки собираются до начала партии и настраивают игру
- game - ограниченный контекст, где происходит сам игровой процесс
- kernel - общее ядро для двух ограниченных контекстов
- tests - сквозные тесты
- domain - явно выделенная модель предметной области, построенная по принципам тактического DDD
- restapi - интерфейсы с REST API
- app - включает конфигурацию, юзкейсы, входные и выходные адаптеры
Исходник диаграммы находится в diagram.puml
Важные решения зафиксированы в ADR.md
# команды даны на примере ограниченного контекста game
# собрать модуль
gradle :game:app:build
# выполнить тесты
gradle :game:app:test
# проверить стилистику кода
gradle :game:detekt
# собрать docker-образ модуля
gradle :game:app:bootBuildImage
- Реализованы в соответствии с детройтской (классической) школой тестирования
- Покрывают модель предметной области
- Моки используются только для недетерминированных или инфраструктурных операций
- Реализованы в соответствии с детройтской (классической) школой тестирования
- Каждый интеграционный тест полностью покрывает один сценарий (включает REST API, юзкейс, домен, БД, Kafka)
- Написаны без использования моков
- Postgres и Kafka поднимаются с помощью Testcontainers
- Проверяют совместную работу двух ограниченных контекстов (lobby и game)
- Включают в себя один BDD-сценарий
- Выполняются с помощью docker-compose с поднятием контейнеров для двух ограниченных контекстов, двух баз данных Postgres и одного экземпляра Kafka
# выполнить сквозные тесты
# это включает в себя сборку с docker-образами модулей lobby и game
gradle :tests:test
- Расположены в пакете fitness в каждом микросервисе
- Реализованы с помощью ArchUnit
- Запускаются так же, как и обычные тесты
- За тестовым покрытием следит JaCoCo
- Стилистику кода контролирует Detekt
- Соблюдение подходов Software Design и архитектуры обеспечивает ArchUnit
Источником вдохновения и примерами для реализации данного репозитория послужили следующие проекты:
- демонстрационное приложение от StringConcat (Kotlin): https://github.com/stringconcat/ddd_practice
- демонстрационное приложение "eShop" от Microsoft (C#): https://github.com/dotnet/eShop
- репозиторий для книги "Get Your Hands Dirty on Clean Architecture" by Tom Hombergs (Java): https://github.com/thombergs/buckpal
- Внедрить CQRS
- Внедрить Event Sourcing
- Реализовать микросервис "Редактор игровых полей"
- Внедрить Spec-Driven Development
