Monorepositorio con Swift: organización del código en la práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Monorepositorio con Swift: organización del código en la práctica



En el desarrollo moderno de iOS y macOS, la elección de una estrategia de gestión de código es uno de los factores clave que afectan la escalabilidad, la velocidad de entrega y la calidad del producto. Tradicionalmente, los desarrolladores usaban multirepositorios (polyrepo), donde cada módulo o servicio vive en un repositorio Git separado. Sin embargo, con el crecimiento de proyectos y equipos, surge cada vez más la pregunta: ¿cómo organizar el código para que se mantenga íntegro, reutilizable y fácil de mantener? La respuesta es — monorepositorio (monorepo) con Swift. En este artículo, analizaremos qué es un monorepositorio, por qué es adecuado para proyectos Swift y cómo organizarlo en la práctica con Swift Package Manager (SPM).



¿Qué es un monorepositorio y por qué es necesario en Swift?



Un monorepositorio es un enfoque en el que todo el código del proyecto (o de varios proyectos relacionados) se almacena en un solo repositorio. A diferencia de polyrepo, donde cada componente está aislado, monorepo unifica bibliotecas, aplicaciones, pruebas, configuraciones y documentación bajo un único control de versiones.



Para los desarrolladores de Swift, el monorepositorio es especialmente relevante por varias razones:

  • Versión única de dependencias: Evitas la desincronización de versiones de bibliotecas entre diferentes aplicaciones.
  • Simplificación de la refactorización: Los cambios en un módulo común son visibles de inmediato para todos los consumidores dentro del repositorio.
  • Integración rápida: Las nuevas funcionalidades se pueden probar y lanzar en una sola pull request.
  • Compatibilidad con SPM: Swift Package Manager es ideal para monorepositorios, ya que admite paquetes locales y rutas relativas.


Estructura de un monorepositorio para un proyecto Swift



Consideremos un ejemplo práctico. Supongamos que tenemos una aplicación para iOS (en SwiftUI) y macOS (en AppKit), que utilizan módulos comunes: capa de red, lógica de autenticación y componentes de UI. Organicemos el monorepositorio de la siguiente manera:



MyMonorepo/├── Package.swift├── Sources/│   ├── AppiOS/│   │   └── main.swift│   ├── AppMacOS/│   │   └── main.swift│   ├── CoreNetworking/│   │   ├── Sources/│   │   │   └── HTTPClient.swift│   │   └── Tests/│   ├── CoreAuth/│   │   ├── Sources/│   │   │   └── AuthService.swift│   │   └── Tests/│   └── UIComponents/│       ├── Sources/│       │   └── CustomButton.swift│       └── Tests/├── Tests/│   ├── AppiOSTests/│   └── AppMacOSTests/├── .gitignore└── README.md


El archivo clave es Package.swift. Describe todos los módulos y sus dependencias. Un ejemplo de dicho archivo:



// swift-tools-version:5.9import PackageDescription

let package = Package( name: "MyMonorepo", platforms: [ .iOS(.v17), .macOS(.v14) ], products: [ .executable(name: "AppiOS", targets: ["AppiOS"]), .executable(name: "AppMacOS", targets: ["AppMacOS"]), .library(name: "CoreNetworking", targets: ["CoreNetworking"]), .library(name: "CoreAuth", targets: ["CoreAuth"]), .library(name: "UIComponents", targets: ["UIComponents"]) ], dependencies: [ // Dependencias externas, si son necesarias // .package(url: "https://github.com/...", from: "1.0.0") ], targets: [ .executableTarget( name: "AppiOS", dependencies: ["CoreNetworking", "CoreAuth", "UIComponents"], path: "Sources/AppiOS" ), .executableTarget( name: "AppMacOS", dependencies: ["CoreNetworking", "CoreAuth", "UIComponents"], path: "Sources/AppMacOS" ), .target( name: "CoreNetworking", dependencies: [], path: "Sources/CoreNetworking/Sources" ), .target( name: "CoreAuth",

Blogs

Book Recommendations