wandres.dev
MIGRAR A TCA · una app existente

El orden de migración: qué primero, cómo medir y cuándo parar

Elegir mal la primera pantalla es la causa más frecuente de que una adopción de TCA se cancele en el segundo mes, y casi siempre se elige mal por las razones que parecen más nobles: empezar por lo más crítico o por lo más difícil. Esta lección fija los criterios de selección y sus contrarios, sustituye las métricas de progreso que engañan por cuatro que informan, e introduce el argumento de perímetro y área que explica por qué se migra por flujos y no por pantallas sueltas. Termina con lo que casi ninguna guía dice: cuáles son los tres puntos de parada legítimos y por qué una migración parcial permanente puede ser el resultado correcto.

⏱ 19 min

Las dos lecciones anteriores resolvieron el cómo. Queda el qué y el cuándo, que es donde se deciden de verdad las migraciones, porque son decisiones que se toman una vez, delante de gente que controla el calendario, y con información incompleta. La primera pantalla que elijas determinará qué aprende el equipo, qué conclusión saca la organización sobre si esto funciona y cuánta paciencia queda para la segunda. El modo de medir determinará si a los tres meses puedes demostrar avance o solo afirmarlo. Y saber dónde está el punto de parada legítimo es lo que distingue una migración terminada de una abandonada, aunque las dos se detengan en el mismo sitio.

🎯 Al terminar esta lección sabrás
  • Aplicar cuatro criterios de selección de la primera pantalla, y reconocer las tres elecciones que hunden un piloto.
  • Sustituir las métricas de superficie por indicadores que midan capacidad real y no volumen de código.
  • Razonar el orden con el argumento de perímetro y área para migrar flujos completos en lugar de pantallas sueltas.
  • Identificar los tres puntos de parada legítimos y dejar la frontera en un estado sostenible.

Elegir la primera pantalla

Los criterios son cuatro y se aplican en conjunto: la pantalla debe ser hoja según la definición del primer capítulo de este nivel; debe tener suficiente lógica de estado para que la arquitectura demuestre algo, es decir, más de un estado de carga y alguna regla de negocio, pero no tanta como para llevar un mes; debe cambiar con frecuencia, porque el beneficio de una migración se cobra cada vez que alguien vuelve a tocar el código; y debe tener un historial de defectos de estado inconsistente, porque entonces el rendimiento de la migración se puede enseñar en la lista de incidencias y no solo argumentar.

Aplicar los cuatro a la vez suele dejar dos o tres candidatas, y para elegir entre ellas basta puntuar cada criterio y sumar. La tabla no es una ceremonia burocrática: obliga a escribir el motivo, y escribirlo es lo que impide que se acabe eligiendo la pantalla que le apetecía a alguien.

Candidata Es hoja Lógica de estado Frecuencia de cambio Historial de fallos
Detalle de pedido Media, tres estados de carga Alta Dos incidentes de doble envío
Ajustes de notificaciones Baja, banderas sueltas Baja Ninguno
Inicio de sesión Casi Alta Media Varios, pero de sesión
Ficha de ayuda Nula Nula Ninguno

En ese cuadro la elección es el detalle de pedido y no hay discusión: es la única que puntúa en las cuatro columnas. Los ajustes y la ficha de ayuda saldrían bien y no demostrarían nada; el inicio de sesión demostraría demasiado y de la peor manera.

Los antipatrones son más instructivos que los criterios. El primero es empezar por el inicio de sesión, que a mucha gente le parece natural por estar al principio: es la pantalla más acoplada a la sesión, la que más singletons toca y la que rompe la app entera si sale mal. El segundo es empezar por la pantalla más compleja con el razonamiento de que si la arquitectura sobrevive ahí sobrevive en cualquier sitio; sobrevivirá, pero tardará seis semanas durante las cuales nadie verá resultados y la pregunta de si esto merece la pena se hará sola. El tercero, más sutil, es elegir una pantalla que nadie toca nunca: saldrá bien, no servirá para nada y el beneficio será exactamente cero porque nadie volverá a leer ese código.

Hay un cuarto que no es de selección sino de ejecución y que estropea incluso una elección buena: migrar una pantalla mientras se le añade funcionalidad nueva. Se hace por eficiencia aparente, ya que la pantalla está abierta de todos modos, y tiene un coste que solo se ve al final: cuando algo falla, nadie puede decir si falla por la arquitectura o por la funcionalidad, y la conclusión que la organización saque del piloto será ruido. La migración de la primera pantalla debe ser, hasta donde sea posible, un cambio de comportamiento cero, verificable comparando la pantalla anterior con la nueva.

💡
La primera pantalla es un experimento, y su métrica es el tiempo hasta publicar

No la elijas por importancia sino por capacidad de producir evidencia rápido. Si el primer incremento no está publicado en dos o tres semanas, el problema no es de esfuerzo: es que la pantalla elegida era demasiado grande o estaba demasiado acoplada, y conviene retirarse a una más pequeña antes de que el piloto consuma su crédito político.

Medir sin engañarse

Las métricas que se usan por defecto son las peores posibles. El porcentaje de archivos migrados premia mover archivos pequeños; las líneas de código en TCA suben cuando alguien escribe un reducer verboso; y el número de pantallas migradas trata igual a la ficha de ayuda que al carrito. Ninguna de las tres mide lo que la migración pretende comprar, que es capacidad: poder afirmar en un test lo que hace la app, poder reproducir un fallo desde un valor, poder abrir cualquier pantalla desde un enlace.

Indicador Qué mide de verdad Señal esperada
Pantallas cuyo estado es un valor inspeccionable Capacidad de reproducir y restaurar Sube de forma sostenida
Cobertura de lógica testeada sin interfaz Verificabilidad real del dominio Sube más rápido que las pantallas
Defectos de la categoría estado inconsistente El rendimiento que se prometió Baja por trimestre
Puentes activos entre los dos mundos Coste de la convivencia Sube, hace pico y baja

Conviene concretar qué significa capacidad, porque es lo único que se está comprando. Significa que un fallo llegado de producción se reproduce escribiendo un valor y afirmando una acción, sin dispositivo, sin cuenta de prueba y sin secuencia de toques.

func testCarritoNoDuplicaAlReintentar() async {
  let store = TestStore(initialState: Carrito.State(lineas: [.muestra], reintentando: true)) {
    Carrito()
  } withDependencies: {
    $0.pedidos.confirmar = { _ in .muestra }
  }
  await store.send(.confirmarPulsado)
  await store.receive(\.confirmacionRecibida) { $0.reintentando = false }
}

Ese test es la unidad de medida honesta: cada pantalla migrada debe poder producir uno equivalente, y una pantalla que no lo consigue no está migrada aunque su archivo diga @Reducer. El cuarto indicador es el más informativo y el que nadie mide. El número de puentes es un indicador adelantado: mientras crece, la migración avanza en anchura; cuando deja de crecer y no empieza a bajar, la migración se ha estancado en un frente demasiado ancho y conviene consolidar antes que abrir más zonas. Un recuento de puentes que solo sube durante dos trimestres es la firma inequívoca de una migración que se está convirtiendo en coexistencia permanente sin que nadie lo haya decidido.

Queda una precaución sobre lo que se promete al medir. El tercer indicador, los defectos de estado inconsistente, es el más convincente ante quien decide y también el más lento: tarda dos o tres trimestres en moverse, porque hace falta que las pantallas migradas acumulen uso real. Prometerlo para el primer mes es garantizar una decepción. Lo que sí se puede enseñar pronto son los dos primeros, que responden a preguntas concretas y verificables: cuántas pantallas se pueden abrir hoy directamente en cualquier estado, y cuánta lógica se verifica sin arrancar la interfaz. Empieza informando de esos y deja el tercero para cuando tenga datos que lo respalden.

Perímetro y área

Aquí está el principio que ordena todo lo demás y que casi nunca se enuncia. El beneficio de la migración es proporcional al área migrada: cuántas pantallas y cuánta lógica viven ya bajo las reglas nuevas. El coste de la convivencia es proporcional al perímetro: cuántos puntos de contacto hay entre los dos mundos, porque cada puente es código que hay que escribir, mantener, testear y borrar después.

Conviene hacer la cuenta con números para que deje de ser una metáfora. Supón un puente entre cien y ciento cincuenta líneas entre la vista envoltorio, la traducción de modelos y sus tests, más el coste continuo de que cada revisión de código en esa zona obligue a sostener dos modelos mentales a la vez.

De ahí se sigue una recomendación operativa que contradice el instinto. Migrar cinco pantallas sueltas repartidas por la app produce cinco perímetros y cinco áreas mínimas: coste máximo, beneficio mínimo. Migrar un flujo completo de cinco pantallas produce un solo perímetro, en el punto donde el flujo se cuelga de la app, y un área cinco veces mayor con todas sus transiciones internas ya modeladas como datos. Es la misma relación entre superficie y volumen que hace que las cosas grandes pierdan proporcionalmente menos calor, y explica por qué las migraciones que avanzan por flujos aceleran mientras las que avanzan por pantallas se atascan.

El mismo argumento dicta cómo se reparte el esfuerzo en el tiempo. Una migración financiada como proyecto aparte compite cada trimestre con el producto y pierde siempre; una financiada como una fracción fija y modesta de cada iteración —del quince al veinte por ciento, sostenido— avanza sin necesidad de defenderse, porque deja de ser una iniciativa y pasa a ser una forma de trabajar. La regla práctica que mejor funciona es que toda pantalla del mundo viejo que haya que abrir para cambiar algo relevante se evalúe como candidata a migrarse en ese mismo momento, siempre que pertenezca al flujo que está abierto y no a otro.

⚠️
El frente ancho es la forma elegante de no terminar nada

Tener siete pantallas a medio migrar en cinco zonas distintas se siente productivo y es lo contrario: multiplica los puentes, obliga a mantener dos modelos mentales en cada revisión de código y no permite retirar ni una sola pieza del mundo viejo. Cierra un flujo entero antes de abrir el siguiente, aunque el siguiente parezca más urgente.

Cuándo parar

Hay tres puntos de parada legítimos, y conviene tenerlos identificados de antemano para no confundir terminar con rendirse. El primero es la zona estable y aburrida: pantallas que llevan dos años sin cambiar, sin defectos y sin planes. Migrarlas cuesta lo mismo que las otras y no rinde nada, porque el beneficio se cobra al volver a tocar el código y nadie va a volver. El segundo es la zona puramente presentacional: pantallas sin estado propio, sin efectos y sin reglas, donde TCA solo añade ceremonia. El tercero es el cambio de condiciones: si el equipo, el producto o el horizonte de la app dejan de ser los que justificaban la decisión, seguir migrando por coherencia es una falacia de coste hundido con nombre de disciplina.

Conviene distinguir estos tres de una cuarta situación que se les parece y que no es una parada sino un aviso: la migración que se detiene porque el siguiente paso es demasiado grande. Eso no significa que haya que dejarlo, significa que el paso está mal cortado y hay que buscar una transferencia de titularidad intermedia que lo parta en dos. La diferencia entre parar y atascarse es que en el primer caso queda claro qué no se va a hacer, y en el segundo solo queda claro que hoy no se ha hecho.

Parar tiene una condición, y es la que convierte una migración parcial en un resultado y no en un abandono: la frontera que queda debe ser corta, explícita y estar documentada. Una app con dos zonas bien delimitadas y tres puentes claros es un sistema perfectamente sano que mucha gente mantiene durante años. Una app con veinte pantallas mezcladas y puentes improvisados es otra cosa, y no importa si el porcentaje migrado es mayor.

La comprobación de que una parada es sostenible cabe en cuatro preguntas, y hay que responderlas antes de anunciar que se ha terminado. ¿Puede alguien nuevo saber en qué mundo está una pantalla sin abrir el archivo, por ejemplo por su ubicación en el árbol de módulos? ¿Está cada puente en un sitio previsible, con nombre reconocible y con un test que lo cubre? ¿Está escrito, en algún documento que la gente lea, qué dato pertenece a qué mundo? ¿Existe una regla clara sobre en qué arquitectura se escriben las pantallas nuevas? Si las cuatro respuestas son afirmativas, la migración parcial es una decisión de arquitectura. Si alguna es negativa, no se ha parado: se ha soltado.

📝
Escribe el veredicto y ponle fecha de revisión

Una parada sin registro se convierte en confusión al cabo de un año, cuando ya nadie recuerda si aquella zona quedó fuera por decisión o por falta de tiempo, y el equipo nuevo la migra a medias por si acaso. Un párrafo que diga qué se migró, qué no, por qué, y cuándo se volverá a evaluar convierte una interrupción en una política.

🎯

Hoja, viva y con historial

Primera pantalla: aislada, con lógica de verdad, que se toca a menudo y que ya ha dado fallos de estado.

📉

Cuenta los puentes

El indicador adelantado. Si sube dos trimestres seguidos, no estás migrando: estás coexistiendo.

🧊

Área contra perímetro

Migra flujos completos. Cinco pantallas sueltas cuestan cinco fronteras y no compran ninguna.

🛑

Parar es un resultado

Legítimo si la frontera queda corta y escrita. Ilegítimo si queda mezclada y por descubrir.

flowchart TD
A[Candidatas hoja] --> B[Tiene logica de estado]
B -- no --> Z[Descartar porque no demuestra nada]
B -- si --> C[Se toca a menudo]
C -- no --> Z2[Descartar porque el beneficio es nulo]
C -- si --> D[Historial de fallos de estado]
D -- no --> F[Buena segunda o tercera]
D -- si --> E[Primera pantalla del piloto]
E --> G[Cerrar el flujo entero antes de abrir otro]
style E fill:#a6e3a1,color:#11111b
style Z fill:#f38ba8,color:#11111b
style Z2 fill:#f38ba8,color:#11111b
Una migración no se planifica por porcentaje de código sino por transferencias de titularidad, y por eso el orden correcto casi siempre parece el orden tímido

La forma habitual de planificar una migración consiste en inventariar las pantallas, estimar cada una y dibujar una recta hasta el cien por cien. Ese plan es reconfortante, encaja en una hoja de cálculo y es sistemáticamente falso, porque supone que las pantallas son independientes y que el coste de cada una es intrínseco. No lo es: el coste de migrar una pantalla depende casi por completo de cuántos datos compartidos escribe y de cuántas pantallas heredadas dependen de que los escriba, es decir, de su posición en la red de titularidades, no de su tamaño. Por eso el inventario ordenado por complejidad aparente predice tan mal, y por eso las pantallas que parecían de dos días consumen tres semanas: no se estaba migrando una pantalla, se estaba intentando trasladar la custodia de la sesión sin haberlo dicho. El plan que sí funciona se escribe en otro vocabulario. Consiste en listar los datos compartidos, decidir en qué orden cambia su dueño, y derivar de ahí qué pantallas se migran cuándo, porque una pantalla solo está lista cuando todos los datos que escribe ya pertenecen al mundo nuevo o han dejado de escribirse desde el viejo. Formulado así, el plan explica sin esfuerzo las intuiciones que las tres lecciones anteriores presentaron como reglas: por qué se empieza por las hojas, que son precisamente las que no escriben nada compartido; por qué la sesión va la última, que es la de mayor grado de entrada; por qué se avanza por flujos, que son los subgrafos donde la titularidad se puede transferir de golpe. Y explica también la parte incómoda: que el progreso no es lineal, que hay mesetas largas mientras se convierte a un escritor en lector, y que la métrica del porcentaje de pantallas migradas puede quedarse quieta durante un mes en el que se hizo el trabajo más importante de todo el proyecto. Quien mide superficie no verá nada ese mes. Quien mide titularidades verá que la app entera acaba de volverse más barata de migrar.

⚔️ Escribe el plan en el vocabulario correcto
  1. Haz el inventario habitual: pantallas ordenadas por complejidad estimada. Guárdalo, es la hipótesis que vas a refutar.
  2. Haz el inventario alternativo: datos compartidos, quién los escribe hoy y cuántas pantallas dependen de ellos. Ordénalo por grado de entrada.
  3. Deriva del segundo inventario el orden de migración y compáralo con el primero. Marca las pantallas que cambian mucho de posición: ahí estaban tus estimaciones equivocadas.
  4. Define los cuatro indicadores de la tabla y toma la medición inicial hoy, incluido el recuento de puentes. Sin línea base no hay progreso demostrable, solo opinión.
  5. Escribe ahora, antes de empezar, cuál sería un punto de parada aceptable y qué frontera dejaría. Si no eres capaz de describirlo, todavía no tienes un plan.