Diseño de software

[Modularización #6] iOS modular más fácil con Tuist

Los equipos que han ampliado sus módulos hasta varias decenas siguiendo esta serie terminan encontrando un nuevo tipo de cansancio.

4 min de lectura
Imagen de portada de [Modularización #6] iOS modular más fácil con Tuist

Los equipos que han ampliado sus módulos hasta varias decenas siguiendo esta serie terminan encontrando un nuevo tipo de cansancio.

Configuración repetitiva por cada módulo, conflictos persistentes en los archivos del proyecto y configuraciones sutilmente distintas entre los miembros del equipo.

Tuist apunta exactamente a este problema. En resumen, elimina los archivos de proyecto de Xcode del repositorio y los genera a partir de código Swift declarativo.

Este artículo resume los problemas que resuelve Tuist, el uso básico de Project.swift y la caché de binarios para equipos grandes. Basado en Tuist 4, julio de 2026.


¿Qué problemas resuelve Tuist?

La clave es trasladar la propiedad de pbxproj de las personas a una herramienta.

En un proyecto iOS típico, project.pbxproj se confirma en el repositorio. Añadir archivos y cambiar la configuración de los destinos modifica este archivo, cuyo formato es difícil de leer; por eso los conflictos de merge son muy difíciles de resolver.

En los proyectos Tuist no se confirma este archivo. En su lugar, se confirma una declaración llamada Project.swift.

Comparación Proyecto habitual Proyecto Tuist
En el repositorio project.pbxproj Project.swift (código Swift)
Archivo del proyecto Gestión manual Generado cada vez con tuist generate
Conflictos de merge Frecuentes en pbxproj Raros con diffs de código Swift
Añadir un módulo Operaciones en la GUI + configuración repetida Una llamada a función

Cuando el archivo del proyecto se convierte en un artefacto generado, deja de ser objetivo de conflictos de merge. Añádelo a .gitignore y listo.


¿Cómo es Project.swift?

Lo más destacado es que las definiciones de módulos son código Swift, así que las configuraciones repetidas pueden agruparse en funciones.

// Project.swift
let project = Project(
    name: "MyApp",
    targets: [
        .target(
            name: "MyApp",
            destinations: .iOS,
            product: .app,
            bundleId: "com.example.myapp",
            sources: ["Sources/**"],
            dependencies: [
                .target(name: "FeatureSearch"),
                .target(name: "CoreNetwork"),
            ]
        ),
    ]
)

Hasta aquí puede parecerse a Package.swift de SPM (Swift Package Manager). La diferencia está en la extensibilidad.

Define en una función auxiliar la estructura estándar de módulos del equipo y añadir un nuevo módulo de funcionalidad se convierte realmente en una línea.

// Estándar del equipo: módulo de funcionalidad = conjunto de + pruebas + aplicación demo
let searchModule = Target.featureModule(name: "Search")
let orderModule = Target.featureModule(name: "Order")
// destinos por módulo; la configuración se unifica en la función auxiliar 3

Con 30 módulos, el enfoque pbxproj obliga a repetir 30 veces la pantalla de configuración; con Tuist, solo hay que añadir un nombre a un array. También desaparece la posibilidad de que las configuraciones difieran entre miembros del equipo.

La visualización del grafo de dependencias está integrada. Un solo comando tuist graph representa las dependencias entre módulos, lo que facilita detectar dependencias circulares o el «módulo sobredimensionado del que todos dependen» advertido en el artículo anterior.

Flujo desde la declaración hasta el proyecto generado
Flujo desde la declaración hasta el proyecto generado

Caché de binarios: el siguiente paso para acelerar la compilación

En el artículo anterior vimos que la modularización reduce el alcance de la recompilación; la caché de Tuist va un paso más allá.

tuist cache compila previamente cada módulo y lo guarda como binario (framework). Al ejecutar tuist generate, los módulos sin cambios se sustituyen por binarios en caché en lugar del código fuente.

  • Si solo estoy desarrollando la funcionalidad de búsqueda: abro el módulo de búsqueda como código fuente y recibo los otros módulos como binarios ya compilados.
  • Incluso una compilación limpia se reduce, en la práctica, a «mi módulo + enlazado».

Con una caché remota, el equipo y CI comparten estos binarios. Mi máquina no recompila un módulo que un compañero ya compiló. Por eso los equipos grandes informan de que el tiempo de una compilación limpia baja de minutos a segundos.


¿Cuándo adoptarlo y cuándo es excesivo?

Tuist es potente, pero adoptarlo también convierte otra herramienta en una dependencia obligatoria del equipo.

Situación Evaluación
Menos de 10 módulos, equipo pequeño Bastan los paquetes locales de SPM
Decenas de módulos, conflictos semanales en pbxproj Gran valor de adopción
El tiempo de compilación de CI y del equipo se convierte en un problema de costes La caché por sí sola justifica la adopción
El equipo no tiene ninguna capacidad para mantener el sistema de compilación Considera la curva de aprendizaje y el coste de seguir las actualizaciones

Si lo adoptas, empieza gestionando con Tuist los módulos nuevos y migra gradualmente los destinos existentes, en lugar de cambiarlo todo de una vez. XcodeGen es una alternativa más ligera que solo genera proyectos; también puedes evaluarla si no necesitas caché.

Así se plantea en una entrevista

P. ¿Por qué introducir una herramienta de generación de proyectos como Tuist?

Porque eliminar pbxproj del repositorio evita conflictos de merge y declarar la configuración del proyecto en código Swift permite estandarizar las plantillas de módulos. Además, la caché de binarios evita recompilar módulos sin cambios, reduciendo el coste de gestión de la modularización y aumentando sus beneficios de velocidad.

P. ¿Cómo reducirías el tiempo de compilación del equipo cuando aumentan los módulos?

Introduce una caché de binarios por módulo para sustituir los módulos sin cambios por artefactos precompilados y compártelos entre el equipo y CI mediante una caché remota. Los desarrolladores abren como código fuente solo el módulo en el que trabajan, por lo que el coste de una compilación limpia depende del alcance de su trabajo.

Mostrar el grafo de dependencias en pantalla agiliza la conversación
Mostrar el grafo de dependencias en pantalla agiliza la conversación

Con esto termina la serie sobre modularización. Empezamos con límites y cohesión, y llegamos a la dirección de dependencias, la estructura por capas, SPM, la velocidad de compilación y, finalmente, Tuist.

Si aplicas estos pasos en orden, obtendrás algo más que «compilaciones más rápidas»: una base de código que ya no da miedo modificar.