Módulo 8: Proyecto — modernizar una rebanada de Mercado

Declarar el done y apagar el legacy

Descripción

El burn-down llegó a cero (L6) y la fitness function está en verde. Parece que terminaste. Pero "parece" es exactamente la palabra que el sexto paso del método —el módulo 7 en su tramo final— existe para eliminar. Este paso hace dos cosas: declara el done con un criterio duro y verificable, y retira el legacy de verdad. Y cierra con la pregunta de fondo de toda la guía: ¿por qué modernizar por rebanadas venció a la reescritura? —respondida no con opiniones, sino con lo que las lecciones midieron—.

El done de una migración no es una sola métrica; es una lista de condiciones que todas deben cumplirse. Porque la migración corta el legacy por varios frentes que terminan en momentos distintos, y el más visible (el tráfico) llega a cero primero mientras otros —menos visibles— quedan atrás. Para el catalog, el done son cinco condiciones, una por cada paso del método: legacy_calls == 0 (el burn-down, L6), fallback == 0 (el strangler, L3), discrepancias == 0 (los datos, L5), legacy_refs == 0 (la fitness, L6), y la characterization en verde (el golden master, L2). Solo cuando las cinco están marcadas, done = True, y la acción que dispara no es "apagar" sino borrar el legacy: el código, el deploy y las tablas. Done significa que la rebanada quedó modernizada de punta a punta y el legacy se puede eliminar sin romper nada, no que dejó de recibir tráfico.

Y como es el último paso del método, este paso también rinde cuentas. La justificación de por qué el camino incremental venció al big-bang no es un discurso: es un número. A lo largo del capstone, el método incremental atrapó problemas antes de producción que el big-bang habría enviado sin verificar —las regresiones de precio que el golden master detectó (L2), las compras por volumen que el fallback reveló sin exponerlas (L3), las discrepancias de datos que el parallel-run encontró antes del switch (L5)—. Vas a contar esos problemas y ver, en una cifra, la diferencia entre modernizar midiendo cada paso y apostar todo a una copia sin verificar.

Conexión con el módulo. Este es el sexto y último paso del método (M7), y consume las salidas de todos los pasos anteriores: cada condición de done es el cero que un paso produjo (el burn-down de L6, el fallback de L3, las discrepancias de L5, las referencias de L6, la characterization de L2). Es el paso que declara la rebanada cerrada y cobra el premio de la migración. Fíjate en la frontera: aquí definimos el criterio de terminación y retiramos la rebanada. La decisión de modernizar —el ADR, la reversibilidad como propiedad de diseño, el registro del porqué— es de architecture-decisions-and-tradeoffs; aquí ejecutamos el cierre técnico, no el registro de la decisión. La lección 8 cierra la guía y te dice hacia dónde seguir.

Una analogía: la recepción de obra con acta y sin andamios

Cuando contratas una remodelación, hay un momento formal llamado recepción de obra: el día en que declaras el trabajo terminado, firmas un acta y haces el último pago. Ese momento no depende de que "se vea terminado" ni de que el maestro diga "ya quedó". Depende de una lista de verificación: ¿la electricidad funciona?, ¿no hay filtraciones?, ¿los acabados están completos?, ¿retiraron los andamios, la basura y las herramientas?, ¿te entregaron las llaves? Solo cuando todas las casillas están marcadas firmas el acta. Si falta una —un cuarto sin pintar, una fuga, los andamios "por si vuelven"— la obra no está recibida, por más que el 95% se vea impecable.

Fíjate en dos detalles de la recepción de obra que son el punto de esta lección. Primero: es una lista, no una sola cosa. No firmas porque "la cocina quedó bonita"; firmas porque todo lo de la lista está hecho. Una obra puede tener la cocina perfecta y una fuga en el baño, y no está terminada. Segundo, y más importante: la recepción exige que se lleven los andamios. Una obra donde todo funciona pero dejaron los andamios "por si hay que volver" no está terminada —está a medias, con la casa ocupada por estructuras que ya no sirven, estorbando y costando la renta del andamio—. La obra termina cuando puedes vivir en la casa y los andamios se fueron.

El done de la migración es esa recepción de obra. La lista son las cinco condiciones: todas marcadas, o no está terminado. Y llevarse los andamios es borrar el legacy —el código, el deploy, las tablas—. Una migración donde el tráfico está en cero pero el legacy sigue desplegado "por si acaso" es la obra con los andamios puestos: parece terminada, pero no lo está, y el andamio cuesta. Done es firmar el acta y ver el camión de los andamios alejarse.

Ejemplo trabajado: el done en verde y la justificación medida

Vamos a ejecutar el paso en dos partes. La parte 1 corre el criterio de done como una checklist de cinco condiciones sobre el catalog, en dos estados: el estado A, "ya casi" —las condiciones visibles en verde, pero queda una referencia al legacy en el código— y el estado B, de verdad terminado —las cinco en verde—. Solo el segundo autoriza borrar y retirar el legacy. La parte 2 produce la justificación medida: cuenta los problemas que el método incremental atrapó antes de producción, que el big-bang habría enviado sin verificar.

# Paso 6 del metodo: declarar el done y apagar el legacy. El done NO es una
# condicion sino VARIAS (todas verificables): llamadas al legacy en 0, fallback en
# 0, discrepancias en 0, referencias al legacy en 0, characterization en verde.
# Solo con todas en verde se BORRA el legacy. Y la justificacion medida: por que
# incremental vencio al rewrite, sobre lo que las lecciones midieron de verdad.

# --- PARTE 1: el criterio de done, con sus 5 condiciones. ---
def done_report(state):
    checks = {
        "legacy_calls == 0":      state["legacy_calls"] == 0,       # burn-down (L6)
        "fallback == 0":          state["fallback"] == 0,           # strangler (L3)
        "discrepancias == 0":     state["discrepancies"] == 0,      # datos (L5)
        "legacy_refs == 0":       state["legacy_refs"] == 0,        # fitness (L6)
        "characterization verde": state["characterization_green"],  # golden master (L2)
    }
    return checks, all(checks.values())


def show(title, state):
    checks, is_done = done_report(state)
    print(title)
    for name, ok in checks.items():
        print(f"    [{'x' if ok else ' '}] {name}")
    if is_done:
        print("    => done = True  ->  BORRAR el legacy (codigo + deploy + tablas)\n")
    else:
        pend = [n for n, ok in checks.items() if not ok]
        print(f"    => done = False ->  faltan: {', '.join(pend)}\n")
    return is_done


print("El done de la rebanada: TODAS las condiciones, no una sola\n")

# Estado A: "ya casi". Las condiciones visibles estan en verde, pero queda 1
# referencia al legacy en el codigo. Parece terminado; NO lo esta.
show("Estado A - 'ya casi' (trafico y datos en 0, pero queda 1 referencia):", {
    "legacy_calls": 0, "fallback": 0, "discrepancies": 0,
    "legacy_refs": 1, "characterization_green": True,
})

# Estado B: de verdad terminado. Las 5 condiciones en verde.
done_B = show("Estado B - de verdad terminado:", {
    "legacy_calls": 0, "fallback": 0, "discrepancies": 0,
    "legacy_refs": 0, "characterization_green": True,
})

legacy_retired = done_B
print(f"  legacy_del_catalog_borrado = {legacy_retired}")
print("  Done no es 'el trafico esta en el nuevo': es las 5 condiciones en verde y")
print("  el legacy BORRADO -codigo, deploy y tablas-, no 'apagado por si acaso'.\n")


# --- PARTE 2: la justificacion medida. Que habria llegado a produccion con el
#     big-bang, y que atrapo el metodo incremental ANTES de produccion. ---
caught = [
    ("L2 caracterizar", "golden master atrapo regresiones de precio",   3),
    ("L3 facade",       "fallback detecto compras sin cubrir (bulk)",   100),
    ("L5 migrar datos", "parallel_run atrapo discrepancias de datos",   2),
]

print("Justificacion medida: incremental vs big-bang (lo que cada leccion midio)")
print(f"  {'paso':<18}{'lo que atrapo ANTES de produccion':<45}{'#':>4}")
print("  " + "-" * 67)
total = 0
for paso, que, n in caught:
    total += n
    print(f"  {paso:<18}{que:<45}{n:>4}")
print("  " + "-" * 67)
print(f"  {'TOTAL problemas atrapados antes de produccion':<63}{total:>4}")
print("\n  El big-bang (apagar Mercado y copiar todo) habria enviado los 105 a")
print("  produccion sin verificar, con el negocio apagado y sin vuelta atras.")
print("  El incremental los atrapo por rebanada, con Mercado vivo, cada paso")
print("  reversible y medido. Por eso incremental vencio al rewrite: no por fe,")
print("  sino por 105 problemas atrapados antes de que tocaran a un cliente.")

Qué esperar. Al correr el archivo, la salida es exactamente esta:

El done de la rebanada: TODAS las condiciones, no una sola

Estado A - 'ya casi' (trafico y datos en 0, pero queda 1 referencia):
    [x] legacy_calls == 0
    [x] fallback == 0
    [x] discrepancias == 0
    [ ] legacy_refs == 0
    [x] characterization verde
    => done = False ->  faltan: legacy_refs == 0

Estado B - de verdad terminado:
    [x] legacy_calls == 0
    [x] fallback == 0
    [x] discrepancias == 0
    [x] legacy_refs == 0
    [x] characterization verde
    => done = True  ->  BORRAR el legacy (codigo + deploy + tablas)

  legacy_del_catalog_borrado = True
  Done no es 'el trafico esta en el nuevo': es las 5 condiciones en verde y
  el legacy BORRADO -codigo, deploy y tablas-, no 'apagado por si acaso'.

Justificacion medida: incremental vs big-bang (lo que cada leccion midio)
  paso              lo que atrapo ANTES de produccion               #
  -------------------------------------------------------------------
  L2 caracterizar   golden master atrapo regresiones de precio      3
  L3 facade         fallback detecto compras sin cubrir (bulk)    100
  L5 migrar datos   parallel_run atrapo discrepancias de datos      2
  -------------------------------------------------------------------
  TOTAL problemas atrapados antes de produccion                   105

  El big-bang (apagar Mercado y copiar todo) habria enviado los 105 a
  produccion sin verificar, con el negocio apagado y sin vuelta atras.
  El incremental los atrapo por rebanada, con Mercado vivo, cada paso
  reversible y medido. Por eso incremental vencio al rewrite: no por fe,
  sino por 105 problemas atrapados antes de que tocaran a un cliente.

Lee las dos partes, porque juntas cierran el método: la primera declara la rebanada terminada, la segunda dice por qué el camino que tomamos fue el correcto.

El estado A: "ya casi", el más peligroso. Mira sus casillas: legacy_calls == 0 marcada, fallback == 0 marcada, discrepancias == 0 marcada, characterization verde marcada. Cuatro de cinco, y las más visibles —el tráfico está en el nuevo, no hay compras cayendo al legacy, los datos cuadran, la caracterización pasa—. Un equipo que solo mirara esas cuatro diría "terminamos". Pero una casilla sigue sin marcar: legacy_refs == 0 (queda 1 referencia en el código nuevo que aún llama al legacy). El veredicto: done = False, falta legacy_refs == 0. La migración parece terminada por donde la mires primero, pero no lo está: si borraras el legacy ahora, romperías el modern, que todavía depende de esa referencia. Es la obra con la cocina perfecta y una fuga en el baño.

El estado B: la recepción de obra completa. Las cinco casillas marcadas. done = True. Y fíjate en la acción que dispara: no "apagar el legacy", sino BORRAR el legacy (código + deploy + tablas). Ahora sí se puede eliminar el módulo legacy del catalog entero —el código del repositorio, el servicio desplegado, las tablas que ya nadie usa— sin romper nada, porque nada depende ya de él. El legacy_del_catalog_borrado = True lo sella: la rebanada quedó modernizada de punta a punta y los andamios se fueron. Done no es "el tráfico está en el nuevo"; es las cinco condiciones en verde y el legacy borrado —no "apagado por si acaso"—.

La justificación medida. La parte 2 responde la pregunta de fondo de la guía con una cifra. A lo largo del capstone, el método incremental atrapó 105 problemas antes de que tocaran a un cliente: las 3 regresiones de precio que el golden master detectó cuando una reimplementación "limpia" cambió los números (L2), las 100 compras por volumen que el fallback reveló que el modern no cubría —sin exponer a un solo usuario a un error de precio— (L3), y las 2 discrepancias de datos que el parallel-run encontró antes del read-switch (L5). El big-bang —apagar Mercado un fin de semana y copiar todo— habría enviado los 105 a producción sin verificar, con el negocio apagado durante la ventana y sin vuelta atrás si algo salía mal. El incremental los atrapó por rebanada, con Mercado vivo, cada paso reversible y medido. Por eso incremental venció al rewrite: no por fe ni por gusto, sino por 105 problemas atrapados antes de que llegaran a un cliente.

Profundización: por qué done es una lista y por qué done es borrar

Dos ideas de este paso merecen desarrollarse, porque son las que más se resisten en la práctica.

Por qué una lista, no una métrica. La migración corta el legacy por varios frentes a la vez, y esos frentes no terminan al mismo tiempo. El tráfico se desvía (frente del strangler, L3); el fallback se cierra cuando el modern cubre todos los casos (L6); las discrepancias de datos se reconcilian (frente de los datos, L5); las referencias en el código se eliminan (frente de la fitness, L6); la caracterización se mantiene en verde (frente del golden master, L2). Cada frente llega a cero en un momento distinto, y es común que el tráfico llegue primero (es lo más visible y lo que el negocio empuja) mientras una referencia de código o el fallback se quedan atrás. Si defines done por el frente más visible, declaras terminado con frentes abiertos —y esos frentes abiertos son lo que impide borrar el legacy—. La lista te obliga a verificar todos los frentes. Done es la conjunción (all(...)), no la casilla más llamativa.

   Frente              Condicion               De         Llega a 0...
   ─────────────────   ─────────────────────   ────────   ─────────────────────
   trafico             legacy_calls == 0       L6         primero (visible)
   completitud modern  fallback == 0           L3/L6      con el bulk (tramo terco)
   datos               discrepancias == 0      L5         tras reconciliar
   codigo              legacy_refs == 0         L6         al final (ultima dependencia)
   comportamiento      characterization verde  L2         se mantiene todo el tiempo
                                               ┌──────────────────────────────┐
   done = AND de las cinco  ──────────────────>┤ solo entonces: BORRAR        │
                                               └──────────────────────────────┘

Por qué borrar y no apagar. "Apagar por si acaso" suena prudente y es, en realidad, la puerta de entrada a la migración eterna. Dejar el legacy desplegado pero desconectado tiene tres costos reales que no desaparecen por estar "apagado": el costo de operación (sigue consumiendo servidores, licencias, mantenimiento —pagas por un sistema que no atiende a nadie—), el costo cognitivo (cada desarrollador nuevo lo encuentra en el código, no sabe que está muerto, y pierde tiempo entendiéndolo o lo modifica creyéndolo vivo), y el costo de riesgo (el código muerto sin mantenimiento se pudre —dependencias sin actualizar, vulnerabilidades sin parchar— y es una trampa: alguien podría reactivarlo por error y reintroducir los bugs que la migración dejó atrás). Borrar elimina los tres; apagar no elimina ninguno. Y el miedo que motiva el "por si acaso" —"¿y si lo necesitamos?"— tiene respuesta técnica: el código no se pierde al borrarlo, el historial de git lo conserva. Borrar el legacy del sistema vivo no es tirarlo a la basura; es sacarlo de donde estorba, con una copia guardada por si el caso improbable ocurre. Done es borrar porque solo borrar cobra el premio de la migración —encoger el sistema, dejar de mantener dos—.

Una última precisión: el done se define al principio, no al final. La checklist de las cinco condiciones se escribe el día uno de la migración, en el plan, para que todos sepan hacia qué línea de meta corren. Definir el done al final —cuando ya estás "casi"— es demasiado tarde: para entonces cada quien tiene su idea de "terminado", y la tentación de declarar victoria en el frente más visible es máxima. El done escrito por adelantado es un contrato con el futuro: "no diremos que terminamos hasta que estas cinco casillas estén marcadas y el legacy borrado".

Errores comunes

Declarar "migrado" con la vieja ruta aún prendida. Qué pasa: el tráfico llega a cero, el equipo declara la migración terminada, y el legacy se queda desplegado "por si acaso". Por qué pasa: legacy_calls == 0 es la casilla más visible y la que el negocio empuja, y borrar el legacy es trabajo extra sin recompensa visible inmediata. Cómo detectarlo: la migración se declaró "hecha" pero el legacy sigue en producción, sale en los dashboards, y consume recursos meses después. Cómo corregirlo: done no es "tráfico en cero", es las cinco condiciones cumplidas y el legacy borrado. El tráfico en cero es necesario pero no suficiente —quedan el fallback, las discrepancias, las referencias—. La migración termina cuando el legacy está borrado, no cuando dejó de recibir requests. Poner "borrado" en la definición de done desde el día uno evita esta declaración prematura.

Definir done por la métrica más visible en vez de por la lista completa. Qué pasa: el equipo mira solo el burn-down de tráfico y, al verlo en cero, da por terminada la migración, sin verificar el fallback, las discrepancias ni las referencias. Por qué pasa: el tráfico es lo más visible y fácil de medir; los otros frentes son menos visibles. Cómo detectarlo: la migración se declara done con frentes abiertos —el fallback aún mayor que cero, una referencia al legacy que quedó—; al intentar borrar el legacy, algo se rompe. Cómo corregirlo: done es la conjunción de las cinco condiciones (all(...)), no la casilla más llamativa. Cada frente de la migración tiene su propia condición y llega a cero en un momento distinto; la lista te obliga a verificar todos. Si al intentar borrar el legacy algo se rompe, es la prueba de que done estaba mal definido —faltaba una casilla—.

Confundir "las técnicas funcionaron" con "la rebanada está modernizada". Qué pasa: el equipo ejecutó los seis pasos, cada uno "salió bien", y declara la modernización terminada —pero el legacy sigue prendido, o el fallback sigue mayor que cero, o una referencia quedó—. Por qué pasa: seis técnicas ejecutadas se siente como seis logros, y "terminado" suena a "hice todo lo de la lista". Cómo detectarlo: pregunta "¿se borró el legacy del catalog?". Si la respuesta es "no, sigue ahí por si acaso" o "el tráfico ya está en el nuevo pero el viejo sigue", la rebanada no está modernizada. Cómo corregirlo: el capstone termina en un número, no en una lista de actividades: done = True con el legacy borrado. Ejecutar las técnicas es el medio; el fin es la rebanada cerrada y el legacy retirado. El criterio de done de esta lección es lo que distingue una cosa de la otra.

Ejercicios

Ejercicio 1 — ¿Done o no? Para cada estado del catalog, di si está done y qué falta: (a) las cinco condiciones en verde; (b) legacy_calls=0, fallback=0, discrepancias=0, legacy_refs=0, characterization roja; (c) legacy_calls=0, fallback=5, discrepancias=0, legacy_refs=0, characterization verde; (d) legacy_calls=0, fallback=0, discrepancias=2, legacy_refs=1, characterization verde.

Ver solución
  • (a) DONE. Las cinco condiciones en verde: se puede borrar el legacy. Es el estado B del ejemplo.
  • (b) NO done. Falta characterization verde: una caracterización en rojo significa que el comportamiento del catalog cambió respecto al golden master —el modern no reproduce algún caso—. Aunque el tráfico, el fallback, las discrepancias y las referencias estén en cero, borrar el legacy dejaría al modern sirviendo un comportamiento distinto del que se prometió preservar.
  • (c) NO done. Falta fallback == 0: aún caen 5 requests al legacy por fallback —el modern tiene un hueco (un caso que no cubre)—. Apagar el legacy dejaría esas 5 requests sin atender. El traffic_percent puede estar en 100, pero el fallback mayor que cero dice que el modern no está completo.
  • (d) NO done. Faltan dos: discrepancias == 0 (quedan 2 filas de datos que no cuadran entre viejo y nuevo) y legacy_refs == 0 (queda 1 referencia en el código). Solo el tráfico y el fallback están en cero —el estado engañoso, avanzado por las casillas visibles pero con dos frentes abiertos—.

La regla es siempre all(...): done solo si las cinco están marcadas. Una sola sin marcar significa que algo todavía depende del legacy o que el comportamiento no se preservó, y mientras eso pase, no se puede borrar.

Ejercicio 2 — La justificación medida. El método incremental atrapó 105 problemas antes de producción. (a) Reparte los 105 entre los pasos que los atraparon. (b) ¿Qué habría pasado con cada grupo si se hubiera hecho un big-bang? (c) ¿Por qué esta justificación es más fuerte que decir "incremental es mejor porque es más seguro"?

Ver solución

(a) Los 105 se reparten así: 3 regresiones de precio atrapadas por el golden master al comparar una reimplementación "limpia" contra el comportamiento congelado (L2); 100 compras por volumen que el fallback reveló que el modern no cubría, sin exponer a un usuario (L3); y 2 discrepancias de datos (una fila faltante, un campo mal traducido) que el parallel-run encontró antes del read-switch (L5). 3 + 100 + 2 = 105.

(b) Con un big-bang, cada grupo habría llegado a producción sin verificar: las 3 regresiones de precio se habrían servido a clientes (una vendiendo productos gratis, otras rompiendo la conciliación de un socio); las 100 compras por volumen se habrían calculado mal o fallado (el modern no cubría el bulk); y las 2 discrepancias de datos habrían dejado un producto desaparecido y otro a la décima parte de su precio. Todo descubierto por quejas y pérdidas, no por comparaciones —y con el negocio apagado durante la ventana de copia, sin vuelta atrás—.

(c) Porque "es más seguro" es una opinión que se puede discutir; 105 problemas atrapados antes de producción es un hecho medido que sale de correr el código de cada lección. La justificación no apela a una preferencia estética por lo incremental; muestra, con una cifra concreta, exactamente qué habría fallado con el big-bang y qué atrapó el incremental. Un argumento medido resiste el "pero el big-bang es más rápido" de una forma que un argumento de principios no: no dice "confía en mí", dice "aquí están los 105 problemas que el big-bang te habría enviado a producción".

Ejercicio 3 — Escribe el done de otra rebanada. Vas a arrancar la migración de orders de Mercado y te piden definir su done el día uno. (a) Escribe la checklist de condiciones. (b) ¿Por qué es mejor definirla ahora que cuando estés "casi"? (c) ¿Qué acción concreta dispara marcar todas las casillas?

Ver solución

(a) La checklist de done para orders, una por frente: (1) legacy_calls == 0 —ninguna request de orders toca el monolito legacy—; (2) fallback == 0 —el modern cubre todos los casos, ninguna request cae al legacy por fallback—; (3) discrepancias == 0 —los datos de orders migrados y verificados fila por fila—; (4) legacy_refs == 0 —el código nuevo de orders no tiene ninguna referencia al monolito—; (5) characterization verde —el comportamiento de orders (incluidas sus rarezas) se preservó respecto al golden master—. (Podría agregarse una condición específica de orders, como "todos los procesos batch nocturnos reapuntados al modern", porque orders tiene más flujos batch que el catalog.) Done solo si todas se cumplen.

(b) Porque definir el done al principio es un contrato con el futuro: fija la línea de meta antes de que la presión y las opiniones divergentes aparezcan. Cuando estés "casi", cada quien tendrá su idea de "terminado", y la tentación de declarar victoria en el frente más visible (el tráfico) será máxima —el momento más débil para definir el criterio—. Un done escrito el día uno resiste esa presión: "acordamos que no terminamos hasta que estas cinco casillas estén marcadas y el legacy borrado".

(c) Marcar todas las casillas dispara borrar el legacy de orders entero: el código del módulo en el repositorio, el servicio/deploy si tenía uno propio, y las tablas del legacy que ya nadie usa —con un posible periodo de gracia corto y con fecha de caducidad antes del borrado definitivo—. La acción no es "declarar en una reunión que terminamos" ni "apagar por si acaso"; es el borrado concreto que cobra el premio: orders deja de ser parte del monolito legacy, y el monolito es una rebanada más pequeño.

Resumen y siguiente paso

En esta lección diste el sexto y último paso del método: declarar el done y retirar el legacy (módulo 7). Ejecutaste el criterio de done como una lista de cinco condiciones que todas deben cumplirselegacy_calls == 0 (L6), fallback == 0 (L3), discrepancias == 0 (L5), legacy_refs == 0 (L6), characterization verde (L2)—, y viste, con la recepción de obra que solo se firma con toda la lista marcada y los andamios retirados, que done es una checklist (no la casilla más visible) y que done es borrar (no apagar por si acaso). El estado A "ya casi" dio done = False (faltaba una referencia); el estado B, con las cinco en verde, dio done = True → BORRAR, y el legacy del catalog se retiró de verdad. Y cerraste con la justificación medida: el método incremental atrapó 105 problemas antes de producción (3 regresiones de precio, 100 compras sin cubrir, 2 discrepancias de datos) que el big-bang habría enviado sin verificar, con el negocio apagado y sin vuelta atrás. Incremental venció al rewrite no por fe, sino por una cifra.

Antes de avanzar deberías poder: escribir la checklist de done de una migración; evaluar un estado y decir si está done y qué falta; explicar por qué done es una lista y por qué done es borrar; y defender, con números, por qué incremental venció al big-bang.

La lección 8 es el entregable del capstone y el cierre de toda la guía. Vas a integrar los seis pasos que ejecutaste por separado —caracterizar, facade, extraer, migrar datos, medir, done— en un solo programa que corre la modernización completa del catalog de punta a punta, con su salida literal fase por fase, terminando en done = True y el legacy borrado. Y vas a cerrar la guía: el método completo en tus manos, y el mapa de hacia dónde seguir —architecture-decisions-and-tradeoffs, event-driven-architecture, architectural-styles-and-boundaries, system-design-fundamentals y el ecosistema Data Engineering para migraciones a escala—.

Recursos

  • Martin Fowler, "StranglerFigApplication" (2004) — martinfowler.com/bliki/StranglerFigApplication.html. Fowler insiste en que la meta del strangler es que el legacy muera —se retire, no coexista—: el done de esta lección es el criterio que declara esa muerte y autoriza el borrado. En inglés.
  • Sam Newman, Monolith to Microservices (O'Reilly, 2019), cap. 3 — la última milla de la migración: retirar (no solo desconectar) la funcionalidad del monolito, y por qué dejarla "por si acaso" perpetúa el problema. La fuente de por qué done es borrar. En inglés.
  • Neal Ford, Rebecca Parsons y Patrick Kua, Building Evolutionary Architectures (O'Reilly, 2ª ed., 2022) — sobre definir criterios objetivos y verificables para el estado de una arquitectura; el done como checklist de condiciones medibles es esa idea aplicada al final de una migración. En inglés.
  • Martin Fowler, "Legacy Modernization" — martinfowler.com. El bliki con las entradas sobre modernización y retiro de sistemas legacy que fundamentan por qué "terminado" significa borrado y no apagado, y por qué el camino incremental y medido vence al big-bang. En inglés.