Introducción al monorepositorio con Kotlin
El desarrollo moderno de aplicaciones complejas a menudo se enfrenta al problema de la gestión del código. La elección entre monorepositorio y multirepositorio es una de las decisiones arquitectónicas clave. En este artículo, analizaremos cómo organizar un monorepositorio con Kotlin, utilizando las mejores prácticas y herramientas modernas.
Un monorepositorio (monorepo) es un enfoque en el que todos los proyectos, bibliotecas y servicios se almacenan en un solo repositorio. Para los desarrolladores de Kotlin, esto es especialmente relevante gracias al potente sistema de compilación Gradle y la posibilidad de usar código compartido entre diferentes módulos.
Ventajas del monorepositorio para proyectos Kotlin
Antes de pasar a la organización, consideremos las ventajas clave del monorepositorio para Kotlin:
- Versión única de dependencias — todos los módulos usan una misma versión de Kotlin, bibliotecas y plugins, lo que elimina conflictos de versiones.
- Refactorización simplificada — los cambios en una biblioteca común se verifican automáticamente en todos los módulos dependientes.
- Configuración centralizada — configuraciones comunes de Gradle, linters y CI/CD se configuran una sola vez.
- Commits atómicos — cambios relacionados en diferentes módulos se pueden realizar en un solo commit.
- Reutilización de código — utilidades comunes, DTOs y lógica de negocio están fácilmente disponibles para todos los proyectos.
Estructura del monorepositorio con Kotlin y Gradle
Consideremos la estructura óptima de directorios para un monorepositorio Kotlin usando Gradle Multi-Module:
my-monorepo/├── build.gradle.kts # Archivo build raíz├── settings.gradle.kts # Configuración de módulos├── gradle.properties # Propiedades comunes├── gradle/│ └── libs.versions.toml # Version Catalog├── modules/│ ├── common/ # Utilidades y modelos comunes│ ├── domain/ # Lógica de negocio│ ├── data/ # Capa de datos (API, BD)│ ├── service-a/ # Microservicio A│ ├── service-b/ # Microservicio B│ └── shared-test/ # Utilidades de prueba comunes├── apps/│ ├── backend/ # Aplicación principal│ └── cli-tool/ # Herramienta CLI└── config/ ├── checkstyle/ # Configuración de linters └── docker/ # Dockerfile para serviciosConfiguración de settings.gradle.kts
El archivo settings.gradle.kts define todos los módulos del proyecto:
rootProject.name = "my-monorepo"
// Incluimos todos los módulosinclude( ":modules:common", ":modules:domain", ":modules:data", ":modules:service-a", ":modules:service-b", ":apps:backend", ":apps:cli-tool")
// Plugin para gestión de versionespluginManagement { repositories { gradlePluginPortal() mavenCentral() }}Uso de Version Catalog (libs.versions.toml)
Para la gestión centralizada de dependencias usamos gradle/libs.versions.toml:
[versions]kotlin = "1.9.22"coroutines = "1.7.3"ktor = "2.3.7"exposed = "0.44.1"
[libraries]kotlin-stdlib = { module = "org.jetbrains.kotlin:kotlin-stdlib", version.ref = "kotlin" }kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "coroutines" }ktor-server-core = { module = "io.ktor:ktor-server-core", version.ref = "ktor" }exposed-core = { module = "org.jetbrains.exposed:exposed-core", version.ref = "exposed" }
[plugins]kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }Ejemplo de build.gradle.kts para el módulo common
plugins { alias(libs.plugins.kotlin.jvm)}
depend