Módulo 11 · Habilidades no técnicas

Lección 48 — Documentación y ADRs

Registrar decisiones de diseño para que nadie (ni tú) tenga que adivinar.

Publicada
En esta lección
  1. Ejercicio 1 — El mapa de docs
  2. Ejercicio 2 — Los ADRs
  3. Ejercicio 3 — La referencia viva
  4. Ejercicio 4 — La caducidad
  5. Ejercicio 5 — El onboarding
  6. Resumen del profesor

Ejercicio 1 — El mapa de docs

  1. El audit honesto: un README de 380 líneas que mezcla instalación (tutorial), comandos (referencia), filosofía (explicación) y 3 howtos enterrados — nadie navega el README de todo: el lector busca SU pregunta y se pierde. Los hallazgos típicos: el runbook del 47 ( how-to bien), el.env.example ( referencia), la filosofía de la 24 escrita en comentario de código (: es explicación y va en ADR).
  2. La estructura queda: onboarding.md (tutorial), howtos/{nuevo-endpoint,rotar-secreto}.md, reference/{api,eventos,env}.md, adr/ (12 ficheros + índice), postmortems/ (2). Cada doc con su cabecera de revisión.
  3. El test del lector en la PR: "este doc responde: ¿cómo añado un endpoint con problem+json?" — el howto de 60 líneas que sirve a ESA pregunta; la filosofía del formato va enlazada al ADR-0002, no mezclada.

Ejercicio 2 — Los ADRs

  1. El ADR modelo (el 0009, saga orquestada):
markdown
# ADR-0009 — Saga orquestada para el checkout
Fecha: 2027-09-18 · Estado: aceptado · Decide: backend
## Contexto
El cobro es remoto (32): sin transacción distribuida. Volumen: 50k compras/día;
el negocio exige "el usuario queda confirmado en <15 min". Equipo: 1.
## Decisión
Orquestación con tabla PurchaseSaga (32): estados, reconciliación por intent (14),
compensaciones idempotentes. Coreografía para lo periférico (emails, analytics).
## Consecuencias
+ La saga reanuda tras caídas (tabla = verdad); UNKNOWN manejado (32); auditable.
− Una tabla + estados que mantener; el orquestador es código acoplado al negocio.
## Revisión
Si los flujos multi-servicio del 53 superan 3 sagas orquestadas, evaluar el motor
(temporal/camunda). Trigger: número de sagas, no moda.
  1. El índice: la tabla del §3 con 12 filas + enlaces dobles (ADR ↔ lección): el compañero nuevo lee 1 página y sabe POR QUÉ el sistema es como es.
  1. El ADR-0018 y el viejo: el 0011 queda con Estado: superseded por ADR-0018 SIN borrarse ni editarse (la decisión histórica fue correcta CON su contexto de entonces: borrarla borra el aprendizaje); el 0018 enlaza hacia atrás. La cadena: la historia de decisiones es una lista enlazada, no un fichero mutable.

Ejercicio 3 — La referencia viva

  1. El test doc↔código:
python
def test_referencia_de_eventos_coincide():
    eventos_doc = parsear_tabla("docs/reference/eventos.md")          # el doc
    eventos_cod = {e.event_type for e in EVENTOS_REGISTRADOS}         # el código
    assert eventos_cod == eventos_doc, "El doc de eventos miente: sincronízalo"

El doc que diverge del código rompe el build: la referencia viva es la única que sobrevive a los meses.

  1. El schema de la API: manage.py spectacular --file docs/reference/openapi.yaml en el pipeline (41): el doc de la API se GENERA, jamás se copia — el PR que cambia el contrato regenera el yaml y el diff del doc aparece en la PR (la revisión del 50 lo ve).
  1. La referencia de env: el test que lee .env.example y el settings.py y verifica que cada env("X") del settings tiene su fila en el example (y viceversa): la divergencia settings↔doc rompe el build. El mecanismo (20 líneas) compra para siempre la verdad de la referencia de configuración.

Ejercicio 4 — La caducidad

  1. La cabecera + el check: Última revisión: 2027-09-28 · Dueño: backend en cada doc; el script del CI:
python
# tools/check_doc_freshness.py (20 líneas)
for doc in DOCS.glob("**/*.md"):
    dias = (hoy - parsea_revision(doc)).days
    if dias > 180: warn(doc, "posiblemente podrido: revisa o archiva")

El warning (no el error: no bloquea el merge) aparece en el build: la caducidad explícita vence al silencio — y el doc que se revisa y sigue válido actualiza la fecha en 10 s.

  1. Los tests-guard de los docs: test_listados_sin_total (39) y test_disponibilidad_no_cacheada_en_checkout (38) con los nombres EXACTOS enlazados desde los docs: "si este test muere, este doc miente" — la afirmación documentada que es código es la única indestructible.
  1. El README de 30 líneas: la matriz (tutorial → onboarding.md · how-to → howtos/ · referencia → reference/ · porqué → adr/) + el estado del proyecto (compose up, tests, deploy). La puerta, no la casa: el README largo es el doc muerto más común del software.

Ejercicio 5 — El onboarding

  1. El tutorial (extracto):
1. git clone && cd ticketflow
2. cp .env.example .env (27) — los valores de dev funcionan salvo DATABASE_URL
3. docker compose up -d (40) — espera los healthchecks
4. docker compose run --rm web python manage.py migrate && seed_demo
5. pytest tests/unit -q → verde en <10 s (33)
6. Lee docs/adr/README.md (12 decisiones, 1 página) y haz tu PR de presentación
  1. La prueba real en máquina limpia: faltaban 3 pasos (el digest del node para el front de pruebas, la TZ del seed, el token de la pasarela sandbox del 14). El doc arreglado con lo descubierto: el tutorial que no se sigue paso a paso es ficción — la regla: cada PR de doc nueva se sigue una vez.
  1. Las 5 que más sirvieron (la respuesta modelo): el runbook del 47 (MTTR −40% el día del incidente), el ADR-0009 (la saga: el porqué que ahorró 2 debates), el.env.example del 27 (el onboarding sin piedras), la tabla de eventos del 45 (el diagnóstico por grep), y este onboarding probado (el day-1 de cualquiera). La regla personal: cuando el tiempo aprieta, documenta PRIMERO lo que el incidente o el onboarding van a preguntar mañana — el resto puede esperar el trimestre.

Resumen del profesor

  • Un formato por lector (Diátaxis): tutorial, how-to, referencia, explicación — el README de todo es el doc que nadie lee.
  • El ADR: una decisión, contexto con números, consecuencias honestas, trigger de revisión; se reemplaza (Supersede), nunca se edita.
  • Docs-as-code: en el repo, en el PR, generados del código donde se pueda, con caducidad explícita y tests-guard para las afirmaciones que pueden ser código.