Qué es The Composable Architecture
The Composable Architecture (TCA) es la librería de arquitectura de Point-Free para SwiftUI y UIKit: el equivalente de Redux y Elm en el mundo Apple. Esta lección la sitúa como lo que realmente es —una librería con opinión que impone un flujo unidireccional y un estado explícito sobre un SwiftUI que, por defecto, deja el estado disperso en múltiples `@State` sin disciplina— y nombra el problema concreto que resuelve en aplicaciones grandes: dónde vive el estado, cómo se muta y cómo se prueban los efectos. Presenta a sus autores, su linaje intelectual, las cinco piezas que la componen —`State`, `Action`, `Reducer`, `Effect` y `Store`— y el hecho decisivo de que corre en las seis plataformas de Apple con el mismo modelo. El objetivo no es aprender su API todavía, sino entender qué clase de herramienta es y por qué existe.
The Composable Architecture —TCA para los amigos— es la librería de arquitectura que Brandon Williams y Stephen Celis construyeron en Point-Free, y es, sin rodeos, lo que Redux y Elm son para la web trasladado al mundo de Apple. No es una parte de SwiftUI ni una recomendación de Apple: es una librería externa, con opinión fuerte, que impone una forma concreta de organizar el estado de una aplicación. SwiftUI te da vistas reactivas pero no te dice dónde vive el estado ni cómo se muta con orden; TCA responde esas preguntas con un flujo unidireccional, un estado explícito y un único camino para el cambio. Esta lección la ubica en el mapa —quién la hizo, de dónde viene y qué resuelve— antes de tocar una sola línea de su API.
- Situar
TCAcomo la librería de Point-Free para SwiftUI y UIKit, heredera de Redux y Elm. - Nombrar el problema que resuelve: el estado disperso y sin disciplina del SwiftUI por defecto.
- Enumerar las cinco piezas —
State,Action,Reducer,EffectyStore— sin detallarlas aún. - Reconocer que un mismo modelo corre en iOS, macOS, iPadOS, visionOS, tvOS y watchOS.
Una librería con opinión, no un framework de Apple
Conviene empezar por lo que TCA no es, porque ahí está el primer malentendido. No forma parte de SwiftUI, no la publica Apple y no aparece en la documentación oficial. Es un paquete de Swift, distribuido por Point-Free, que se añade con Swift Package Manager y que impone una arquitectura sobre la app. Esa distinción importa: SwiftUI es un motor de renderizado reactivo —te da vistas que se recalculan cuando su estado cambia— pero deliberadamente no opina sobre dónde debe vivir ese estado ni cómo debe mutarse. Puedes escribir una app entera con @State, @Observable y @Environment sin ninguna arquitectura, y funcionará. TCA entra precisamente donde SwiftUI calla: es la disciplina que decide la forma del estado, y por eso se la llama una librería con opinión.
Esa opinión tiene un nombre técnico: flujo unidireccional. En TCA el estado solo cambia por un camino, a través de un Reducer que recibe una acción y produce el siguiente estado. No hay setters dispersos, no hay mutaciones desde media docena de vistas, no hay dos fuentes de verdad que se contradigan. La misma idea que Elm llevó a la programación funcional y que Redux popularizó en JavaScript, ahora expresada en Swift y ajustada a SwiftUI.
El problema: SwiftUI no te dice dónde vive el estado
En una pantalla pequeña, el SwiftUI idiomático es delicioso: un @State local por aquí, un binding por allá, y la vista se actualiza sola. El problema aparece al crecer. Cuando una feature tiene diez estados que dependen entre sí, cuando dos pantallas lejanas deben compartir un dato, cuando un efecto asíncrono debe cancelarse al desaparecer la vista, el modelo por defecto empieza a dispersarse. El estado queda repartido en @State privados de varias vistas, la lógica de negocio se cuela dentro del body, y probar esa lógica exige montar la interfaz entera. No hay un lugar único donde leer qué puede pasar en la feature.
import ComposableArchitecture
import SwiftUI
@Reducer
struct Contador {
@ObservableState
struct State: Equatable {
var cuenta = 0
}
enum Action {
case incremento
case decremento
}
var body: some ReducerOf<Self> {
Reduce { state, action in
switch action {
case .incremento:
state.cuenta += 1
return .none
case .decremento:
state.cuenta -= 1
return .none
}
}
}
}
Ese bloque es una feature completa de TCA en su forma mínima. Fíjate en lo que ya está resuelto: todo el estado vive en un valor —State—; cada cosa que puede pasar es un caso de un enum —Action—; y el único sitio donde el estado se muta es el Reducer. No hay que buscar por la app dónde cambia cuenta: se cambia aquí, y solo aquí. Esa concentración es la respuesta de TCA al desorden.
Las cinco piezas y un mismo modelo en seis plataformas
TCA descompone una feature en cinco piezas con roles estrechos, que los próximos niveles diseccionan una a una: State es todo el estado reunido en un valor; Action enumera cada evento que puede ocurrir; Reducer es la función pura que, dada una acción, produce el siguiente estado; Effect es el trabajo con el mundo exterior —red, disco, relojes— que el reducer devuelve en vez de ejecutar directamente; y Store es el motor en tiempo de ejecución que sostiene el estado y conecta la vista con todo lo demás.
Point-Free, no Apple
La construyen Brandon Williams y Stephen Celis. Es un paquete externo que se añade con SPM, no una pieza de SwiftUI ni una recomendación oficial de Apple.
Redux y Elm en Swift
Adapta el flujo unidireccional y el estado inmutable de Elm y Redux al lenguaje de Apple, con tipos algebraicos y semántica de valor.
Cinco piezas
State, Action, Reducer, Effect y Store. Un vocabulario pequeño y fijo que se repite igual en cada feature de la app.
Seis plataformas, un modelo
El mismo Reducer corre en iOS, macOS, iPadOS, visionOS, tvOS y watchOS. La arquitectura no depende de la plataforma ni del framework de UI.
Ese último punto es más profundo de lo que parece. Como la lógica vive en el Reducer y este no importa nada de SwiftUI ni de UIKit, la misma feature se reutiliza en un Apple Watch, en un Vision Pro o en un Mac sin reescribir su comportamiento; solo cambia la vista que se conecta al Store. La arquitectura es ortogonal a la plataforma, y esa portabilidad es una de las razones por las que los equipos grandes de Apple la adoptan.
flowchart TD ELM[Elm Architecture] --> TCA[The Composable Architecture] REDUX[Redux] --> TCA TCA --> IOS[iOS y iPadOS] TCA --> MAC[macOS] TCA --> VIS[visionOS] TCA --> OTROS[tvOS y watchOS] style TCA fill:#cba6f7,color:#11111b style ELM fill:#89b4fa,color:#11111b style REDUX fill:#89b4fa,color:#11111b style IOS fill:#a6e3a1,color:#11111b style MAC fill:#a6e3a1,color:#11111b style VIS fill:#a6e3a1,color:#11111b style OTROS fill:#a6e3a1,color:#11111b
Es tentador leer TCA como una caja de herramientas que te da más capacidades, y esa lectura la malinterpreta desde la raíz. TCA no te deja hacer nada que SwiftUI a secas no te dejara: no hay pantalla que solo se pueda construir con ella. Lo que aporta no es poder, sino restricción, y la restricción es precisamente el valor. Al obligar a que todo el estado viva en un State, a que todo evento sea un caso de Action y a que toda mutación pase por un Reducer, TCA convierte el comportamiento de una feature en algo que se puede leer en un solo lugar, reproducir paso a paso y probar sin montar la interfaz. Esa es la misma apuesta que hicieron Elm y Redux, y la misma que este track ha defendido nivel tras nivel: en una app pequeña la ceremonia no compensa, porque el desorden todavía cabe en la cabeza; en una app grande, con muchas personas tocándola durante años, la legibilidad global vale más que la comodidad local. Entender TCA es entender ese intercambio antes que su sintaxis. Quien la adopta buscando atajos se frustra con su ceremonia; quien la adopta buscando un único camino para el cambio descubre que la ceremonia era el punto. La pregunta correcta ante TCA nunca es qué me deja hacer, sino qué me impide hacer, porque de esas prohibiciones —y no de sus funciones— nace todo lo que la hace útil.
- Toma una feature real de una app SwiftUI que conozcas y localiza cada
@State,@Bindingy@Observableque participa en ella. Anótalos sin agrupar. - Marca en qué archivos y vistas se muta cada uno de esos estados. Cuenta cuántos sitios distintos pueden cambiar el mismo dato.
- Pregúntate: si tuvieras que escribir en una frase qué puede pasar en esta feature, ¿podrías leerlo en un solo lugar, o tendrías que recorrer varias vistas?
- Reescribe mentalmente esa feature con las cinco piezas de TCA: qué campos formarían el
State, qué casos tendría elAction, qué haría elReducer. - Decide con honestidad si esta feature es lo bastante grande como para que la restricción de TCA compense su ceremonia, y escribe el argumento en dos líneas.