Saltar al contenido
arbelxez

5 min de lectura

Los guards que defienden el criterio cuando no estás mirando

Un principio que no rompe el build se erosiona. Nunca de golpe: se va por excepciones razonables, un martes, con prisa y con alguien esperando. Por eso los criterios de este sitio no viven en un documento de convenciones, sino en scripts que fallan ruidosamente y me dejan sin desplegar.

01

Un principio que no rompe el build se erosiona

Todos los equipos tienen un documento de buenas prácticas y todos lo incumplen igual: nadie lo rompe a propósito. Alguien tiene un caso raro y de verdad urgente, lo resuelve por fuera de la regla, y esa excepción queda en el repositorio como precedente. La siguiente ya no discute, copia. Un año después la regla existe en prosa y no existe en el código. La diferencia entre un criterio y una opinión es si algo se pone rojo cuando lo rompes.

Este sitio tiene los suyos y son aburridamente concretos. check-rhythm impide que la portada ponga dos ráfagas seguidas. check-dry prohíbe que una receta de clases viva fuera de la única fuente que la define. check-design-tokens rompe el build si aparece un color en crudo en vez de un token. check-translations exige que los dos idiomas tengan exactamente la misma forma. check-max-lines corta los archivos largos. check-clean-architecture defiende que las páginas sean servidor puro.

Un guard se escribe en el momento de decidir, no después. En el momento de decidir todavía sé por qué la decisión importa y qué caso concreto quiero impedir; tres meses más tarde solo me queda la costumbre, y una costumbre no se puede programar. También por eso un guard se encadena al lint el día en que existe lo que defiende: mientras tanto se ejecuta a mano, y eso queda escrito en su cabecera para que nadie crea que está vigilando algo que aún no vigila.

02

Cómo se elige el umbral

El máximo de líneas por archivo aquí son 800. Es un número, y los números tienen que poder defenderse. No lo escogí como aspiración sino midiendo primero el repositorio: un umbral que falla el día que lo enciendes no es un guard, es una lista de tareas pendientes disfrazada, y lo primero que hace un equipo con una lista así es silenciarla. El umbral tiene que estar donde hoy pasa todo y mañana duele partir el archivo que se descuidó.

Un guard es código, así que tiene bugs, y sus bugs son peores que los normales. check-max-lines contaba 801 líneas en un archivo de 800 porque el salto de línea final dejaba un elemento vacío al partir el texto: el umbral efectivo era 799 y fallaba cuando no debía. Un guard que se equivoca en contra enseña a la gente a desconfiar de todos los guards, y esa desconfianza es exactamente lo que un repositorio no puede permitirse.

03

Toda exención es una grieta con nombre

check-design-tokens tiene cuatro archivos exentos, y cada uno lleva escrito al lado por qué. El CSS global, porque es donde se definen los tokens. El manifiesto y la configuración del sitio, porque la plataforma pide ahí un color literal. Y el armazón compartido del layout, porque el enrutado bilingüe parte la raíz en dos y el themeColor que exige la Metadata API de Next tiene que vivir en un solo sitio. Ninguna de esas cuatro es una excepción: son el borde de la regla, dicho en voz alta.

La exención peligrosa es la que no lleva motivo, porque no se puede revisar. Cuando una lista de exentos crece más rápido que el código que vigila, el problema dejó de ser el código: la regla está mal planteada y hay que reescribirla, no seguir perdonándola. Un guard con demasiadas exenciones sigue apareciendo verde en el registro del build, y esa es su forma más cara de fallar, porque parece que sigue trabajando.

04

Un falso positivo se ve; un falso negativo no

check-rhythm empezó queriendo comparar dos listas: el orden de la portada en un JSON y el mismo orden en un archivo de TypeScript. Leer TypeScript con expresiones regulares se pierde siempre —una palabra parecida dentro de un tipo desplaza el emparejamiento e inventa discrepancias, o peor, las esconde—, así que el guard cambió de pregunta. En vez de comparar dos fuentes, exige que solo haya una: el archivo de configuración tiene que importar el JSON. Por construcción ya no pueden divergir.

Esa es la elección de fondo. Un guard puede fallar de dos maneras, y no cuestan lo mismo. El falso positivo me interrumpe, me hace mirar y en el peor caso me cuesta dos minutos de fastidio. El falso negativo no me cuesta nada hoy y me cuesta el criterio entero dentro de seis meses, cuando ya hay veinte archivos que lo incumplen y arreglarlo es un proyecto en vez de una línea.

Por eso los guards de aquí prefieren ser estrictos y explicarse: cada error dice el archivo, la línea y qué hacer en su lugar. check-clean-architecture no acepta un hook fuera de un componente de cliente ni una página que se declare cliente. check-translations carga los dos diccionarios y compara su forma entera. Ninguno opina sobre si el código es bonito. Solo sostienen decisiones que yo ya tomé, en los días en que no me acuerdo de por qué las tomé.