Monorepositório com Kotlin: organização de código na prática
No desenvolvimento de software moderno, cada vez mais surge a escolha entre monorepositório (monorepo) e multirrepositório (multirepo). Para projetos em Kotlin, especialmente aqueles que usam Kotlin Multiplatform ou arquitetura de microsserviços, o monorepositório torna-se uma ferramenta poderosa. Neste artigo, vamos analisar como organizar corretamente o código em um monorepositório em Kotlin, considerar exemplos práticos e melhores práticas que ajudarão você a evitar erros típicos.
O que é um monorepositório e por que ele é necessário em Kotlin?
Monorepositório é uma abordagem onde todo o código do projeto (ou de vários projetos relacionados) é armazenado em um único repositório. No contexto do Kotlin, isso pode incluir:
- Bibliotecas comuns — utilitários, modelos de dados, DTOs.
- Módulos de aplicativos — backend (Ktor, Spring), frontend (Kotlin/JS), aplicativos móveis (Kotlin Multiplatform).
- Scripts e configurações — CI/CD, Dockerfile, scripts Gradle.
Principais vantagens do monorepositório para projetos Kotlin:
- Versão única de dependências — todos os módulos usam a mesma versão do Kotlin e bibliotecas, reduzindo o risco de conflitos.
- Refatoração simplificada — a alteração de uma API em um módulo é imediatamente visível em todos os dependentes.
- Configuração mais fácil de CI/CD — um único pipeline para todos os componentes.
- Transparência — toda a base de código está disponível em um só lugar.
No entanto, também existem desvantagens: o tamanho do repositório pode crescer e o tempo de clonagem aumenta. Mas para projetos médios e grandes em Kotlin, o monorepositório muitas vezes acaba sendo a solução ideal.
Estrutura do monorepositório: modelo prático
A organização correta das pastas é a base do sucesso. Vamos considerar uma estrutura típica para um projeto Kotlin usando Gradle:
my-kotlin-monorepo/├── build.gradle.kts # Script de build raiz├── settings.gradle.kts # Configuração dos módulos├── gradle.properties # Parâmetros comuns do Gradle├── gradle/│ └── libs.versions.toml # Version Catalog (recomendado)├── modules/│ ├── common/ # Utilitários e modelos comuns│ │ ├── build.gradle.kts│ │ └── src/│ ├── backend/ # Serviço backend em Ktor│ │ ├── build.gradle.kts│ │ └── src/│ ├── android-app/ # Aplicativo Android│ │ ├── build.gradle.kts│ │ └── src/│ └── web-client/ # Cliente Kotlin/JS│ ├── build.gradle.kts│ └── src/├── scripts/ # Scripts auxiliares│ └── deploy.sh└── docs/ # Documentação └── architecture.mdO arquivo settings.gradle.kts inclui os módulos:
rootProject.name = "my-kotlin-monorepo"
include(":modules:common")include(":modules:backend")include(":modules:android-app")include(":modules:web-client")No build.gradle.kts raiz, você pode definir plugins e dependências comuns:
plugins { kotlin("jvm") version "1.9.22" apply false kotlin("multiplatform") version "1.9.22" apply false id("com.android.application") version "8.2.0" apply false}Gerenciamento de dependências: Version Catalog e Convention Plugins
Em um monorepositório, é crucial evitar a duplicação de versões de dependências. Para isso, em Kotlin, usa-se o Version Catalog (arquivo libs.versions.toml).
Exemplo de gradle/libs.versions.toml:
[versions]kotlin = "1.9.22"ktor = "2.3.7"coroutines = "1.8.0"
[libraries]kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }ktor-server-core = { module = "io.k