Почти любое мобильное приложение общается с бэкендом, а значит живёт по контракту — чаще всего в виде OpenAPI схемы, которую удобно смотреть в Swagger.

Пока проект маленький, изменения в API можно отслеживать вручную. Но по мере роста схемы и команды ручная проверка становится дорогой и начинает регулярно ломаться.
Автогенерация из OpenAPI решает проблему, но в многомодульном Android-проекте всплывают нюансы: где хранить код, как не тянуть лишнее, как вписать сгенерённый код в архитектуру.
Привет! Меня зовут Дима Максимов, я Android-разработчик в Дринкит. В этом цикле статей из 2 частей я расскажу о том, как настроить генерацию из Swagger в Kotlin-код, и о том, как обуздать автогенерацию в условиях многомодульного проекта.
Сгенерировать код из Swagger просто в том случае, если:
С другой стороны - есть наш проект Дринкит. И тут мы сталкиваемся с несколькими сложностями одновременно:
root
├── infra
│ ├── lib_1
│ └── ...
└── contexts
├── common
│ ├── cart
│ │ ├── domain-api
│ │ └── domain-impl
│ └── ...
├── cart
│ ├── domain-api
│ ├── domain-impl
│ └── presentation
├── product
│ ├── domain-api
│ ├── domain-impl
│ └── presentation
└── ...
И в каждом модуле примерно такая структура:
cart
├── cart-api
│ ├── build.gradle
│ └── src/main/kotlin/ru/drinkit/common/cart
│ ├── Cart.kt
│ ├── ConsumeCartRepository.kt
│ └── ... other cart related domain classes
└── cart-impl
├── build.gradle
└── src/main/kotlin/ru/drinkit/common/cart
├── ConsumeCartRepositoryImpl.kt
├── api
│ └── CartApi.kt
└── dto
├── CartDto.kt
└── ... other cart related DTOs
То есть в конкретном модули лежат DTO модели и сетевой интерфейс только конкретного домена. Для корзины — про корзину, для карточки продукта — про карточку.
И для соблюдения нашей архитектуры, необходимо найти способ генерировать код из Swagger в модули -impl
Например, в блоке со структурой проекта можно заметить два одинаковых модуля cart: в common и в contexts. И это не ошибка!