wandres.dev
ESTADO A ESCALA · equipos y dominios

Convenciones que sobreviven al equipo: nombres, ubicación y reglas escritas

Una convención que solo existe en la cabeza de quienes la inventaron desaparece con la primera rotación de personal, y su desaparición no se anuncia: se manifiesta meses después como incoherencia difusa que nadie sabe cuándo empezó. Esta lección trata las convenciones de estado como artefactos de ingeniería con requisitos propios, examina por qué la mayoría se erosiona, y muestra cómo convertir un acuerdo frágil en una regla que el sistema aplica sin depender de la memoria de nadie.

⏱ 17 min

Toda base de código grande contiene los restos arqueológicos de varias convenciones sucesivas, y la lectura de esos estratos revela siempre la misma historia. Alguien estableció una regla, funcionó mientras las cuatro personas que la acordaron seguían presentes, se transmitió de forma oral a las siguientes cuatro con pérdidas, y hacia la tercera generación quedó reducida a un patrón que se imita sin entender, aplicado de forma incoherente y defendido con el argumento de que aquí siempre se ha hecho así. El problema no fue que la convención fuera mala, sino que se sostenía sobre memoria humana en un sistema donde la memoria humana rota cada dieciocho meses. Una convención de estado sobrevive únicamente si deja de depender de que alguien la recuerde.

🎯 Al terminar esta lección sabrás
  • Identificar por qué se erosionan las convenciones y qué las hace resistentes a la rotación.
  • Diseñar un vocabulario de nombres que codifique la clase de estado y su propiedad.
  • Establecer reglas de ubicación verificables por herramientas y no por revisión humana.
  • Escribir la regla junto a su motivo para que pueda revisarse en vez de fosilizarse.

Por qué se erosionan y qué las hace resistentes

Una convención se erosiona por tres mecanismos independientes que conviene separar porque tienen remedios distintos. El primero es la pérdida de transmisión: quien llega imita lo que ve en los archivos que abre, y si abre los tres peores, reproduce esos. El segundo es la deriva por excepción: cada desviación se justifica localmente por una urgencia real y ninguna se revierte cuando la urgencia pasa. El tercero es la pérdida del motivo: la regla sobrevive pero su razón no, y una regla sin razón no puede adaptarse cuando el contexto cambia, así que o se aplica ciegamente donde ya no sirve o se abandona entera cuando alguien nota que estorba.

📏

Verificable

Si una máquina puede comprobarla, no depende de que nadie la recuerde. La regla verificable falla al escribirla, no meses después en una revisión.

🧾

Justificada

La regla viaja con su motivo. Sin él nadie puede decidir si sigue aplicando, y una regla que no se puede revisar acaba fosilizada o abandonada.

🔢

Poca y estable

Cinco reglas que todo el mundo conoce valen más que cuarenta que nadie ha leído. El coste de una convención es el esfuerzo de recordarla.

🌱

Ejemplar

Existe un módulo de referencia, actualizado, que encarna la convención. La gente copia lo que ve, así que conviene que vea lo correcto.

De los tres mecanismos, el más subestimado es la deriva por excepción, porque cada caso individual resulta defendible y solo el agregado es destructivo. La dinámica es conocida en otros contextos: una norma admite una excepción justificada, la excepción crea un precedente, el precedente reduce el coste moral de la siguiente, y a partir de cierta densidad de excepciones la norma deja de describir el sistema y pasa a describir una aspiración. El antídoto no es la rigidez, que produce incumplimiento silencioso, sino registrar cada excepción con fecha y motivo, de modo que el conjunto sea visible y alguien pueda observar que ya son once.

// la excepcion registrada sigue siendo una excepcion; la no registrada
// se convierte en la nueva norma sin que nadie lo decida
// eslint-disable-next-line no-restricted-imports
// motivo: migracion de facturacion en curso  ->  retirar antes de 2026-09
import { indiceLineas } from "@app/dominios/carrito/interno"

La consecuencia práctica es que el trabajo de establecer convenciones no termina cuando el equipo se pone de acuerdo, sino cuando el acuerdo queda inscrito en algún artefacto que no olvida: una regla del linter, un generador de plantillas, una comprobación en integración continua o, en el peor caso aceptable, un documento breve que se revisa en cada incorporación. Cualquier convención que solo exista como consenso oral tiene fecha de caducidad, y esa fecha coincide con la salida de la segunda persona que la defendía.

// convencion oral: nadie la aplica cuando quien la propuso ya no esta
// "los derivados se nombran empezando por un verbo o un sustantivo de producto"

// convencion inscrita: falla en el momento de escribirla
// eslint: naming-convention sobre exports de */derivados.ts
//   selector -> prohibido    getX -> prohibido
//   totalCarrito, puedeEditar, resumenDePedido -> permitido

Un vocabulario que codifica la clase y la propiedad

Los nombres son la convención de mayor alcance porque se leen mil veces por cada vez que se escriben. Un buen vocabulario de estado hace visible en el propio identificador dos cosas que de otro modo exigen abrir archivos: a qué clase de estado pertenece el dato y quién lo posee. La clase importa porque las reglas de manipulación difieren radicalmente entre estado de servidor, estado de interfaz, estado de formulario y estado derivado, y confundirlas es el origen de la mayoría de los defectos de sincronización. La propiedad importa porque determina a quién hay que preguntar antes de cambiar la forma.

flowchart LR
D[dominio pedidos] --> E[estado propio interno]
D --> R[lecturas derivadas exportadas]
D --> O[operaciones exportadas]
R --> C1[resumenDePedido]
R --> C2[puedeCancelarse]
O --> C3[cancelarPedido]
E --> C4[privado no exportado]

Conviene notar por qué los prefijos técnicos heredados de los primeros años del ecosistema envejecieron mal. Un nombre como selectCarritoTotal codifica el mecanismo, que es la parte más volátil del sistema, y calla el significado, que es la parte estable. Cuando el mecanismo cambia, y cambia cada pocos años, o bien el nombre miente o bien hay que renombrar cientos de referencias. Nombrar por el hecho de producto invierte esa relación: totalDelCarrito seguirá siendo cierto cuando el motor de derivación se haya sustituido dos veces, porque describe algo que pertenece al dominio y no a la infraestructura.

Un vocabulario mínimo que funciona en la práctica distingue cuatro formas. Las lecturas derivadas llevan nombre de hecho del producto, sin prefijo técnico, porque describen lo que es cierto y no cómo se calcula. Las operaciones llevan verbo en infinitivo y expresan la intención del usuario, no la mutación resultante. Los datos remotos llevan la clave de consulta como identidad y nunca se copian a otro ámbito. Y todo lo interno carece de nombre público, que es la forma más económica de declararlo privado.

La propiedad se codifica mejor en la ruta que en el identificador, porque la ruta ya existe y no cuesta nada leerla. Un nombre importado desde el dominio de pedidos declara su dueño sin necesidad de prefijos, y esa es una de las razones por las que la organización por dominio hace innecesarias muchas convenciones de nomenclatura que la organización por artefacto obligaba a inventar. Cuando la estructura dice la mitad de lo que hacía falta decir, el vocabulario puede ser la mitad de grande, y un vocabulario más pequeño es un vocabulario que la gente recuerda.

// clase y propiedad legibles en el propio nombre
export const puedeCancelarse = derivar(...)    // hecho del producto, no calculo
export function cancelarPedido(id: string) {}  // intencion, no mutacion
export const clavePedido = (id: string) => ["pedidos", id] as const  // remoto

// prohibido por convencion: revela implementacion y ata el interior
// export const getPedidosMap = ...
// export function setEstadoPedido(...)

La convención de nombres se hace efectiva sobre todo en la frontera, donde puede verificarse. No hace falta regular cómo se llaman las variables locales de nadie, y de hecho intentarlo desprestigia el conjunto; basta con imponer la forma de lo que cada dominio exporta, que es lo único que otros van a leer. Esa restricción del alcance de la regla, del interior a la superficie, reduce el número de conflictos en revisión de código casi a cero y conserva íntegro el beneficio, que estaba en el vocabulario público y no en el privado.

// la regla se aplica solo a lo exportado desde el indice del dominio
// interior libre: nombres locales, abreviaturas, variables de trabajo
const m = construirIndice(lineas)          // nadie fuera lo vera nunca

// superficie regulada: hecho de producto o verbo de intencion
export const totalDelCarrito = derivar(() => sumar(m))
ℹ️
Nombrar por intención frena la mutación oportunista

Una operación llamada setEstadoPedido invita a que cualquiera escriba cualquier valor desde cualquier sitio, porque su nombre no acota nada. Una llamada cancelarPedido obliga a que la lógica de qué implica cancelar viva dentro del dominio, donde puede validarse y evolucionar. La convención de nombres no es cosmética: determina dónde tiende a acumularse la lógica, y la lógica se acumula siempre en el lado que el vocabulario hace más cómodo.

Reglas escritas, verificables y con motivo

Antes de automatizar nada conviene aceptar un límite: hay convenciones importantes que ninguna herramienta puede comprobar, empezando por la que decide si un dato pertenece a un dominio o a otro. Pretender verificarlo produce reglas elaboradas que aciertan la mitad de las veces y que el equipo acaba desactivando, con el efecto colateral de desacreditar también las reglas que sí funcionaban. La política sensata es automatizar todo lo mecánico para liberar la atención de la revisión humana, y reservar esa atención para las pocas decisiones que exigen juicio, que son también las únicas cuyo coste de equivocarse es alto.

Una regla de ubicación es la más fácil de automatizar y la que más deriva evita, porque decide de antemano la pregunta que más veces se repite en cualquier equipo: dónde pongo esto. Formulada con precisión suficiente puede comprobarse en cada cambio, y entonces deja de consumir atención humana. La formulación importa: prohibir importaciones profundas entre dominios es verificable, mientras que pedir que el código esté bien organizado no lo es y por tanto no es una regla sino un deseo.

// regla verificable: nadie importa el interior de otro dominio
// eslint no-restricted-imports:
//   patrones prohibidos -> src/dominios/*/!(index)*
//   motivo -> preservar la libertad de reorganizar el interior sin coordinar

// regla verificable: el estado remoto no se copia a ambitos de cliente
//   prohibido -> asignar el resultado de useQuery a un store global
//   motivo -> dos copias del mismo dato divergen en cuanto una se invalida

Hay una jerarquía de mecanismos de aplicación que conviene recorrer de arriba abajo antes de conformarse con un documento. En lo más alto está hacer que la violación sea imposible por construcción: si el interior de un dominio no aparece en el índice, nadie puede importarlo aunque quiera. Después viene la comprobación automática, que permite la violación pero la detiene antes de integrarse. Después la plantilla o el generador, que hace que el camino correcto sea también el más rápido. Y solo al final el documento, que depende por completo de que alguien lo lea y lo recuerde, y que por eso debe reservarse para lo que ninguna herramienta puede verificar.

// jerarquia de aplicacion, de mas fuerte a mas debil
// 1. imposible: exports.package.json restringe los puntos de entrada
// 2. verificado: regla de lint que falla la integracion continua
// 3. guiado: plantilla que crea el dominio ya conforme
// 4. escrito: documento breve con el motivo, para lo no verificable

Escribir el motivo junto a la regla parece un detalle documental y es en realidad el elemento que permite que la convención evolucione en vez de fosilizarse. Sin motivo, cualquier regla se convierte en un tabú: nadie la discute y nadie la retira aunque el contexto que la justificaba haya desaparecido, con lo que el conjunto de reglas solo crece y su credibilidad se erosiona hasta que el equipo empieza a ignorarlas todas por igual. Con motivo, una regla puede refutarse, y una regla refutable es la única que puede mantenerse viva.

Queda un requisito que rara vez se formula y que decide si una convención sobrevive a la primera incorporación masiva: debe ser aplicable sin conocer el resto del sistema. Una regla que exige entender el mapa completo de dominios antes de decidir dónde poner un archivo se incumplirá durante los tres primeros meses de cada persona nueva, que son justo aquellos en los que más archivos se crean copiando algo. Las convenciones que resisten son las que se pueden aplicar mirando únicamente el archivo que se está escribiendo y su carpeta inmediata, y esa restricción, que parece pobre, es la que las hace transmisibles sin maestro.

💡
El módulo de referencia vale más que el documento

Mantén un dominio pequeño y real como ejemplo canónico, actualizado cada vez que la convención cambie, y señálalo en la incorporación de cada persona. La gente aprende por imitación mucho antes que por lectura, y un ejemplo correcto compite con ventaja contra los seis archivos antiguos que también podría haber abierto. Un documento explica la regla; un módulo ejemplar la hace inevitable.

Una convención es un mecanismo de transmisión, no un acuerdo

El error de fondo al pensar las convenciones consiste en tratarlas como acuerdos entre las personas que hoy están en el equipo, cuando su función real es transmitir decisiones a personas que todavía no han llegado y que nunca podrán preguntar por qué. Un acuerdo se sostiene sobre la presencia de quienes lo firmaron; una convención tiene que funcionar precisamente cuando esa presencia ha desaparecido, y por eso los requisitos de ambas cosas son distintos. Un acuerdo necesita ser razonable y aceptado. Una convención necesita algo mucho más exigente: ser aprendible sin maestro, verificable sin juicio experto, y revisable sin arqueología. De ahí que las convenciones que sobreviven no sean las más inteligentes sino las más baratas de reconstruir, y de ahí también que la sofisticación sea, en este terreno, un defecto. Un esquema de organización que exige entender una teoría para aplicarlo correctamente será aplicado incorrectamente en cuanto la teoría deje de circular, y su aplicación incorrecta es peor que su ausencia, porque produce una apariencia de estructura que oculta la falta de estructura real. La consecuencia práctica es incómoda para quien disfruta diseñando sistemas: la mejor convención de estado que un equipo puede adoptar es la más simple que resuelva el problema, inscrita en herramientas que la comprueben, ilustrada por un ejemplo vivo y acompañada de un motivo que permita retirarla cuando deje de servir. Todo lo demás es memoria humana, y la memoria humana es el único componente del sistema que nadie ha conseguido versionar.

⚔️ Convierte un acuerdo en una regla
  1. Enumera las convenciones de estado que tu equipo aplica de hecho y márcalas según estén escritas, sean verificables y tengan motivo registrado.
  2. Elige la más violada y determina si el problema es de transmisión, de excepciones acumuladas o de motivo perdido.
  3. Reformúlala en términos comprobables por una herramienta y añádela a la configuración del linter con su motivo en un comentario.
  4. Selecciona un dominio pequeño, ponlo en conformidad total y decláralo módulo de referencia en la guía de incorporación.
  5. Revisa el conjunto completo de reglas y retira todas aquellas cuyo motivo ya no puedas defender ante alguien que acaba de llegar.