Módulo 1: What A Design System Is

Mantenibilidad y la única fuente de verdad

Descripción

La lección anterior midió el drift que ya existe: cuánto desorden carga una UI ad-hoc. Esta lección mide algo distinto y, para muchos equipos, más doloroso: el costo de cambiar a propósito. Una UI no es un monumento que se construye una vez y se admira; es algo vivo que cambia todo el tiempo —"oscurezcamos el azul de marca", "hagamos las esquinas menos redondeadas", "subamos un punto el tamaño del cuerpo"—. La pregunta que define si tu UI es mantenible es simple: cuando quieres cambiar un valor, ¿cuántos lugares tienes que tocar?

En una UI ad-hoc, la respuesta es "tantos como veces escribiste el valor" —y peor: "más los que se te olviden"—. En un sistema, la respuesta es uno. Esa diferencia —N ediciones frágiles contra 1 edición confiable— es lo que se llama tener una única fuente de verdad (en inglés, single source of truth): cada decisión de diseño vive en un lugar, y todo lo demás la referencia. Cambias el lugar, y el cambio se propaga solo. Es, quizás, el argumento más práctico de por qué montar un sistema.

Conexión con el módulo. La lección 4 mostró el drift como desorden acumulado; esta muestra el otro lado: el sistema no solo evita que las cosas diverjan, sino que hace barato y seguro evolucionarlas. Es la consecuencia directa del flujo hacia arriba de la lección 3: como cada capa referencia la de abajo, un cambio en un token sube solo por utilidades, componentes y patrones. Aquí lo medimos: 1 edición contra N. La lección 6 mostrará que esta misma propiedad —cambiar en un lugar, propagar a todos— es lo que hace que la accesibilidad sea garantizable a escala.

Una analogía: el número de teléfono en la agenda

Imagina que tu mejor amigo cambia de número de teléfono. Tienes dos formas de haber guardado su número.

La forma ad-hoc: cada vez que lo necesitaste, escribiste su número directamente donde lo usabas —en una nota pegada al refri, en el margen de un cuaderno, en un mensaje viejo, en un post-it del trabajo—. Ahora que cambió de número, tienes que ir a cada lugar donde lo escribiste, encontrarlo y corregirlo. ¿Cuántos lugares hay? No estás seguro. Corriges los que recuerdas. Y tres semanas después marcas el número viejo desde un post-it que se te olvidó, y no entiendes por qué no contesta. El número estaba escrito en N lugares; cambiarlo fue N ediciones y un olvido garantizado.

La forma con sistema: guardaste su número una vez, en la agenda del teléfono, bajo su nombre ("Andrés"). En todos lados —mensajes, llamadas, notas— te referiste a "Andrés", no al número. Cuando cambia de número, editas una entrada en la agenda, y automáticamente todo lo que decía "Andrés" marca el número nuevo. Una edición. Cero olvidos posibles, porque el número solo existía en un lugar.

La agenda es la única fuente de verdad. El nombre "Andrés" es la referencia (como color.primary); el número es el valor (como #2563eb). Guardar el número directamente en cada lugar es el ad-hoc; guardarlo una vez y referirte por nombre es el sistema. Y la diferencia no es de comodidad: es de confiabilidad. La versión de agenda no puede dejar un post-it desactualizado, porque no hay post-its: hay una entrada. Todo este módulo es esa agenda aplicada al diseño.

De cerca: qué significa "una única fuente de verdad"

Es un principio que viene de la ingeniería de software en general, y dice: cada dato debe tener exactamente una representación autorizada; todo lo demás la referencia, no la copia. Cuando un dato vive en un solo lugar, ese lugar es "la verdad", y no hay forma de que dos copias se contradigan, porque no hay copias.

En un sistema de diseño, la única fuente de verdad de cada decisión es su token. El valor de "el azul de marca" vive en color.primary y en ningún otro lado. La utilidad bg-primary no tiene el valor; lo lee de color.primary. El componente Button no tiene el color; usa bg-primary, que lee color.primary. Nadie más que el token conoce el valor #2563eb. Por eso, para cambiarlo, solo hay un lugar donde tocar.

Compara con el ad-hoc, donde no hay fuente de verdad: hay N copias del valor, todas "igual de autorizadas", ninguna sabiendo de las otras. No hay una que mande; hay N que compiten, y cuando difieren (drift, lección 4), ninguna es "la correcta". La única fuente de verdad elimina esa ambigüedad de raíz: siempre hay exactamente una respuesta a "¿cuál es el azul de marca?", porque hay exactamente un lugar donde está escrito.

Esto tiene una consecuencia que vale la pena nombrar: el cambio y la consistencia son el mismo problema visto desde dos lados. Una UI con una sola fuente de verdad es consistente (no puede divergir) y barata de cambiar (un solo lugar), por la misma razón estructural. No son dos beneficios separados que el sistema te da; son la misma propiedad —"cada decisión vive en un lugar"— mirada de frente y de perfil.

Ejemplo trabajado: cambiar el azul de marca, contado

Pongámosle números al dolor. El equipo de Mercado decide oscurecer el azul de marca (de #3b82f6 a #2563eb, un azul más profundo). Vamos a modelar el costo del cambio en las dos versiones y contar, literal, cuántas ediciones cuesta cada una.

En la versión ad-hoc, el valor está copiado en varios archivos (y uno ya venía divergido —#3c83f6—, herencia del drift). En la versión de sistema, el valor vive en un token que los componentes referencian:

// L5 — unica fuente de verdad: cambiar "el azul de marca" a un tono mas oscuro.
// Ad-hoc: el valor esta copiado en N lugares -> N ediciones (y las que se olviden).
const adHocUsages = [
  { file: 'Button.css',      value: '#3b82f6' },
  { file: 'ProductCard.css', value: '#3b82f6' },
  { file: 'SearchBar.css',   value: '#3c83f6' }, // ya venia divergido
  { file: 'Badge.css',       value: '#3b82f6' },
  { file: 'checkout.css',    value: '#3b82f6' },
];
const newValue = '#2563eb';
const editsNeeded = adHocUsages.length;

console.log('=== Cambiar el azul de marca a ' + newValue + ' ===\n');
console.log('Ad-hoc (valor copiado en cada archivo):');
console.log('  lugares a editar a mano: ' + editsNeeded);
console.log('  riesgo: olvidar uno deja una pantalla con el color viejo\n');

// Sistema: el valor vive en UN token. Los componentes lo referencian.
const token = { 'color.primary': '#3b82f6' };
const componentsUsingToken = ['Button', 'ProductCard', 'SearchBar', 'Badge', 'checkout'];
token['color.primary'] = newValue; // una sola edicion

console.log('Con un sistema (todos referencian el token color.primary):');
console.log('  ediciones necesarias: 1');
console.log('  componentes actualizados automaticamente: ' + componentsUsingToken.length);
console.log('  valor resuelto ahora en todos: ' + token['color.primary']);

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

=== Cambiar el azul de marca a #2563eb ===

Ad-hoc (valor copiado en cada archivo):
  lugares a editar a mano: 5
  riesgo: olvidar uno deja una pantalla con el color viejo

Con un sistema (todos referencian el token color.primary):
  ediciones necesarias: 1
  componentes actualizados automaticamente: 5
  valor resuelto ahora en todos: #2563eb

Lee las dos cifras clave lado a lado: 5 ediciones contra 1 edición, para el mismo cambio.

En la versión ad-hoc, el azul está escrito en cinco archivos, así que oscurecerlo cuesta cinco ediciones manuales. Y la línea del "riesgo" no es decorativa: es el problema de verdad. Cinco ediciones a mano es cinco oportunidades de olvidar una. Si te saltas checkout.css, el checkout se queda con el azul viejo, y —como en el ejercicio del foco de la lección 4— nadie lo nota hasta que un usuario lo ve. El costo del ad-hoc no es solo el trabajo de las cinco ediciones; es la fragilidad: el cambio puede salir a medias, y las medias tintas son bugs silenciosos.

En la versión de sistema, el azul vive en un solo lugar —el token color.primary—. Cambiarlo es una edición. Y fíjate en la línea que lo hace valioso: "componentes actualizados automáticamente: 5". No editaste el Button, ni el ProductCard, ni el checkout; se actualizaron solos, porque no tenían el valor, lo referenciaban. La onda subió por las capas (lección 3): cambió el token, y con él bg-primary, y con él los cinco componentes. Una edición, cero olvidos posibles, cero fragilidad. El cambio no puede salir a medias, porque solo había un lugar que cambiar.

Ahora extrapola, porque ahí está el argumento real. Cinco usos es un ejemplo de juguete; un storefront real usa el color de marca en decenas o cientos de lugares. En ad-hoc, eso son decenas o cientos de ediciones y una probabilidad prácticamente segura de olvidar varias. En el sistema, sigue siendo una edición, sin importar si son 5 usos o 500. El costo del cambio en un sistema no crece con el tamaño de la UI; en ad-hoc, crece linealmente y se vuelve impagable. Esa es la diferencia entre una UI que se mantiene sola y una que se pudre.

Una pregunta para llevarte: el ejemplo cambió el valor de un token. ¿Qué pasaría si en vez de un color quisieras cambiar el tema entero —de claro a oscuro—? La respuesta es la misma propiedad a mayor escala: cambias el conjunto de valores que los tokens resuelven, y toda la UI cambia de tema sin tocar un solo componente. Eso es el theming, y es el módulo 2 y el 6; nace de esta misma idea de la única fuente de verdad.

Un matiz: la indirección tiene un pequeño precio (que vale la pena)

Seamos honestos: la única fuente de verdad no es gratis. Referirte a color.primary en vez de a #2563eb agrega un paso —una indirección—: para saber de qué color es algo, tienes que ir a mirar qué vale el token. Un valor directo (#2563eb) se lee de inmediato; un token (color.primary) hay que "resolverlo". Ese es el precio.

Pero es un precio pequeño y que se paga una vez (al leer el código), contra un beneficio grande y recurrente (cada cambio, para siempre). Y a cambio ganas algo que el valor directo no puede dar: el nombre dice el rol. #2563eb no te dice para qué sirve ese azul; color.primary te dice que es el color de las acciones principales. La indirección no solo habilita el cambio barato; también hace el código más legible, porque los nombres cargan intención. Es un intercambio que casi siempre conviene: un poquito más de ceremonia al leer, muchísima menos fragilidad al cambiar. (La lección 2 ya tocó el reverso de esto: no todo merece un token; lo genuinamente único puede quedarse directo, porque no hay cambio-en-muchos-lugares que optimizar.)

Errores comunes

Copiar el valor "solo esta vez". Qué pasa: existe el token, pero en un momento de prisa alguien escribe #2563eb directo en un componente "para no ir a buscar el token". Por qué pasa: en el instante, copiar el valor es más rápido que referenciar. Cómo detectarlo: haces un cambio en el token y casi todo se actualiza —pero una pantalla se queda con el color viejo, porque ahí el valor estaba hardcodeado—. Cómo corregirlo: cada valor escrito directamente es un post-it fuera de la agenda: una copia que la única fuente de verdad no gobierna, y que divergirá en el próximo cambio. La regla es dura: si existe un token para algo, siempre se referencia el token, nunca se escribe el valor. Un solo valor hardcodeado rompe la promesa de "un cambio, todo se actualiza".

Crear varias "fuentes de verdad" para lo mismo. Qué pasa: hay un token color.primary en el CSS, otra constante PRIMARY_BLUE en el JavaScript, y un tercer valor en la config del correo, todos con el azul de marca. Por qué pasa: cada capa técnica define su propia copia "por conveniencia". Cómo detectarlo: cambias uno y los otros dos quedan desactualizados —volvió el drift, ahora entre sistemas—. Cómo corregirlo: única fuente de verdad significa una, no "una por tecnología". El valor debe vivir en un lugar y las demás capas leerlo de ahí (el módulo 2 y 3 muestran cómo Tailwind y el CSS comparten los mismos tokens). Tener tres fuentes de verdad es no tener ninguna: es exactamente el problema que el sistema venía a resolver, disfrazado de organización.

Confundir "una fuente de verdad" con "un archivo gigante". Qué pasa: en el afán de centralizar, alguien mete todos los estilos de la app en un solo archivo enorme y lo llama "el sistema". Por qué pasa: se lee "un solo lugar" como "un solo archivo". Cómo detectarlo: tienes un archivo de 3000 líneas que nadie entiende, y "cambiar el azul" sigue siendo difícil porque está enterrado entre mil cosas. Cómo corregirlo: única fuente de verdad no es sobre cuántos archivos; es sobre que cada decisión viva en un lugar identificable y con nombre. Los tokens pueden estar bien organizados en varios archivos (colores, espaciado, tipografía); lo que importa es que "el azul de marca" esté definido una vez, con un nombre claro, y que todo lo referencie. Centralizar el valor, sí; amontonar todo el CSS, no.

Ejercicios

Ejercicio 1 — Cuenta las ediciones. Para cada escenario, di cuántas ediciones cuesta el cambio en la versión ad-hoc y cuántas en la versión de sistema:

  • (a) El radio de las esquinas del ProductCard (8px) está escrito en 4 componentes; se quiere cambiar a 6px. Con sistema, es el token radius-md.
  • (b) Se quiere subir el tamaño del texto del cuerpo de 16px a 17px; el 16px está escrito directo en 20 lugares. Con sistema, es el token text-base.
Ver solución
  • (a) Ad-hoc: 4 ediciones. Sistema: 1. En ad-hoc, 8px está en 4 componentes → 4 ediciones a mano (y el riesgo de olvidar uno). En sistema, cambias radius-md una vez y los 4 componentes se actualizan solos.
  • (b) Ad-hoc: 20 ediciones. Sistema: 1. Aquí el contraste es brutal: 20 lugares a corregir a mano (con probabilidad casi segura de olvidar alguno) contra una edición del token text-base. Y nota lo importante: si mañana fueran 200 usos, el ad-hoc sería 200 ediciones pero el sistema seguiría siendo 1. El costo del sistema no crece con el tamaño; el del ad-hoc, sí.

La moraleja: la ventaja del sistema no es lineal, es estructural. En ambos casos el sistema cuesta 1; el ad-hoc cuesta "cuantas veces se copió el valor".

Ejercicio 2 — Encuentra el post-it perdido. El equipo de Mercado tiene el token color.primary y lo usa en casi todo. Cambian el token de azul a verde. Todo se vuelve verde… menos el botón "Comprar ahora" de la página de producto, que sigue azul. Sin ver el código, ¿qué pasó, y cómo se corrige?

Ver solución

Lo que pasó: el botón "Comprar ahora" no referenciaba el token; tenía el azul escrito directamente (background: #3b82f6 a mano, en vez de bg-primary / var(--color-primary)). Es un "post-it fuera de la agenda": una copia del valor que la única fuente de verdad no gobierna. Cuando el token cambió a verde, ese botón se quedó con su copia vieja del azul, porque nunca leyó el token.

Cómo se corrige: reemplazar el valor hardcodeado por una referencia al token (bg-primary / var(--color-primary)). A partir de ahí, ese botón también obedecerá los cambios del token. Este es exactamente el primer error común ("copiar el valor solo esta vez") mordiendo en la práctica: un solo valor directo rompe la promesa de "un cambio, todo se actualiza". La única fuente de verdad solo funciona si todo la referencia; una sola excepción es un bug esperando su turno.

Ejercicio 3 — Consistencia y cambio son lo mismo. Explica, con tus palabras, por qué una UI con una única fuente de verdad es a la vez más consistente y más barata de cambiar. ¿Son dos beneficios distintos o el mismo?

Ver solución

Son el mismo beneficio visto desde dos lados, y la razón estructural es una sola: cada decisión vive en exactamente un lugar.

  • Visto desde la consistencia: como el valor existe en un solo lugar y todo lo referencia, no puede haber dos versiones que difieran. No hay drift posible, porque no hay copias que puedan divergir. La consistencia es automática.
  • Visto desde el cambio: como el valor existe en un solo lugar, cambiarlo es tocar ese único lugar, y la referencia hace que todo lo demás se actualice solo. El cambio es barato y confiable.

Las dos propiedades salen de la misma estructura ("un lugar por decisión"). No es que el sistema te dé dos regalos separados; es que "un lugar por decisión" es la consistencia mirada de frente y es la mantenibilidad mirada de perfil. Por eso, cuando alguien rompe la regla (hardcodea un valor), rompe las dos a la vez: crea una copia que puede divergir (menos consistencia) y que hay que editar aparte (más costo de cambio). El drift y el costo de mantenimiento son síntomas de la misma enfermedad —no tener una sola fuente de verdad—, y el token es la única cura de ambos.

Resumen y siguiente paso

En esta lección mediste el argumento más práctico del sistema: la mantenibilidad. Con la agenda del teléfono viste que guardar el número una vez bajo un nombre —y referirte por el nombre— hace que un cambio de número sea una edición sin olvidos, contra los N post-its dispersos del ad-hoc. Aprendiste qué es una única fuente de verdad —cada decisión vive en un lugar, todo lo demás la referencia— y que su token es ese lugar en un sistema de diseño. Lo mediste ejecutando: oscurecer el azul de marca costó 5 ediciones frágiles en ad-hoc contra 1 edición confiable en el sistema, con 5 componentes actualizándose solos —y entendiste que ese "1" no crece aunque la UI tenga 500 usos—. Y viste la idea más profunda: consistencia y cambio barato son el mismo beneficio, porque ambos salen de "cada decisión vive en un lugar".

Antes de avanzar deberías poder: definir "única fuente de verdad" y por qué el token lo es; contar el costo de un cambio en ad-hoc vs sistema; detectar un valor hardcodeado que rompe la propiedad; y explicar por qué consistencia y mantenibilidad son la misma cosa.

La lección 6 lleva esta propiedad a un terreno donde importa muchísimo: la accesibilidad como propiedad del sistema. Si la accesibilidad —contraste suficiente, foco visible, roles correctos— se resuelve dentro del sistema (en el token, en el componente), entonces se garantiza una vez y vale para toda la UI, igual que el cambio de color se propagó a los cinco componentes. Vas a ver cómo un sistema convierte la accesibilidad de "algo que cada pantalla debe recordar hacer" en "algo que se hereda gratis", y a medir la diferencia.

Recursos