Diseño simple: las 4 reglas de Kent Beck, con un ejemplo
¿Cuándo está «bien diseñado» un programa? Es fácil discutirlo durante horas. Kent Beck propuso una respuesta corta: cuando cumple cuatro reglas, en este orden. El diseño simple es uno de los principios del código limpio (clean code).
| Nº | Regla | Pregunta que te haces |
|---|---|---|
| 1 | Pasa todos los tests | ¿Hace lo que debe, y puedo comprobarlo? |
| 2 | Revela la intención | ¿Otra persona entiende para qué sirve cada parte? |
| 3 | No contiene duplicados | ¿Cada idea está escrita en un único sitio? |
| 4 | Tiene los mínimos elementos | ¿Sobra alguna clase, función o capa? |
Este artículo resume el capítulo 12 de Clean Code, «Emergence», escrito por Jeff Langr, y lo contrasta con la explicación de Martin Fowler en BeckDesignRules.
Qué es el diseño emergente
En muchos parques hay un camino de tierra que nadie planificó: lo fue marcando la gente al cruzar por donde de verdad le venía bien. El diseño emergente se parece: en vez de decidir toda la estructura antes de empezar, la dejas aparecer a partir del uso real del código.
La diferencia con el parque es que en el código no basta con pisar. Hay que ordenar a propósito, y para eso están las cuatro reglas: escribes un poco de código, compruebas que los tests pasan y lo limpias. Repites. El diseño sale de muchas mejoras pequeñas.
Regla 1: pasa todos los tests
Lo primero es que el sistema haga lo que se espera. Un diseño puede ser perfecto sobre el papel, pero si no hay una forma sencilla de comprobar que funciona, no sabes si funciona.
El capítulo de Clean Code lo plantea así: un sistema que no se puede probar no se puede verificar, y uno que no se puede verificar no debería ponerse en producción.
Además, intentar que el código sea fácil de probar empuja a diseñarlo mejor. Según el mismo capítulo, te lleva a:
- Clases pequeñas, con un único propósito. Es el principio de responsabilidad única (SRP, Single Responsibility Principle): cada clase tiene un solo motivo para cambiar.
- Depender de abstracciones y no de detalles concretos. Es el principio de inversión de dependencias (DIP, Dependency Inversion Principle). Así puedes sustituir, por ejemplo, la base de datos real por una falsa en los tests.
- Poco acoplamiento y mucha cohesión: las piezas dependen poco unas de otras y lo que está junto tiene que ver entre sí.
Si quieres empezar por los tests, mira TDD, desarrollo dirigido por tests.
Reglas 2, 3 y 4: se cumplen refactorizando
Con los tests en verde, toca limpiar. Refactorizar es cambiar la estructura del código sin cambiar lo que hace. Los tests son lo que te quita el miedo: si rompes algo, te avisan en segundos.
Al refactorizar puedes:
- Aumentar la cohesión y reducir el acoplamiento.
- Separar responsabilidades y dividir el sistema en módulos.
- Reducir el tamaño de funciones y clases.
- Elegir mejores nombres.
- Eliminar duplicados.
- Reducir el número de clases y métodos.
¿Va antes la intención o los duplicados?
Clean Code pone «sin duplicados» antes que «expresividad». Fowler las ordena al revés y explica que el orden entre estas dos importa poco, porque se ayudan mutuamente: al quitar un duplicado sueles tener que ponerle nombre a la idea repetida, y eso la hace más clara.
Fowler también recoge que, si alguna vez chocan, Beck prefiere lo que ayuda a quien lee: «empathy wins over some strictly technical metric» (la empatía gana a una métrica estrictamente técnica). El ejemplo que menciona son los propios tests, donde a veces repetir un poco los hace más fáciles de leer.
Regla 2: revela la intención
El mayor coste de un proyecto de software suele estar en mantenerlo, no en escribirlo. Cuanto más cuesta entender el código, más tiempo se pierde y más fácil es meter errores al cambiarlo. Por eso el código tiene que dejar claro qué quería hacer quien lo escribió.
Ganas expresividad si:
- Eliges buenos nombres. Al leer el nombre de una clase o función no deberían sorprenderte sus responsabilidades.
- Haces funciones y clases pequeñas. Son más fáciles de nombrar, de escribir y de entender.
- Escribes tests. Un buen test es documentación con ejemplos: quien lo lee entiende cómo se usa una clase.
- Le dedicas tiempo al final. Lo habitual es que, en cuanto algo funciona, pases al siguiente problema. Para un momento y relee el código pensando en la próxima persona que lo abra.
Regla 3: no contiene duplicados
Si la misma regla de negocio está escrita en dos sitios, cuando cambie tendrás que acordarte de cambiar los dos. Y un día se te olvidará uno. Beck lo resumía como Once and Only Once (una vez y solo una vez); otros lo llaman DRY (Don’t Repeat Yourself, no te repitas). En qué se parece a YAGNI y KISS, y cuándo chocan, está en YAGNI, KISS y DRY.
Un ejemplo en JavaScript. Un carrito aplica un 10 % de descuento si pasas de 100 €, y la misma cuenta aparece copiada para los pedidos guardados:
// Antes: la regla del descuento está escrita dos veces
export function totalCarrito(lineas) {
let total = 0;
for (const linea of lineas) total += linea.precio * linea.unidades;
if (total > 100) total = total * 0.9;
return total;
}
export function totalPedidoGuardado(pedido) {
let total = 0;
for (const linea of pedido.lineas) total += linea.precio * linea.unidades;
if (total > 100) total = total * 0.9;
return total;
}
Primero, tests que fijan el comportamiento (regla 1):
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { totalCarrito, totalPedidoGuardado } from './carrito.js';
test('sin descuento si el total no pasa de 100 €', () => {
assert.equal(totalCarrito([{ precio: 20, unidades: 5 }]), 100);
});
test('10 % de descuento si el total pasa de 100 €', () => {
assert.equal(totalCarrito([{ precio: 60, unidades: 2 }]), 108);
});
test('un pedido guardado se calcula igual que el carrito', () => {
const lineas = [{ precio: 60, unidades: 2 }];
assert.equal(totalPedidoGuardado({ lineas }), totalCarrito(lineas));
});
Después, refactorizas. Al quitar el duplicado aparecen nombres que explican la regla (reglas 2 y 3 a la vez):
// Después: cada idea está en un único sitio y tiene nombre
const UMBRAL_DESCUENTO = 100;
const DESCUENTO = 0.1;
function subtotal(lineas) {
return lineas.reduce((suma, linea) => suma + linea.precio * linea.unidades, 0);
}
function conDescuento(importe) {
return importe > UMBRAL_DESCUENTO ? importe * (1 - DESCUENTO) : importe;
}
export function totalCarrito(lineas) {
return conDescuento(subtotal(lineas));
}
export function totalPedidoGuardado(pedido) {
return totalCarrito(pedido.lineas);
}
Los mismos tres tests pasan antes y después (node --test). Si mañana el descuento cambia al 15 %, lo cambias en una línea.
Regla 4: los mínimos elementos
Todo lo que no ayude a cumplir las tres reglas anteriores sobra: clases, funciones, interfaces o capas.
Es la regla de menor prioridad. Primero van los tests, la claridad y quitar duplicados; solo después reduces piezas. Lo que evita es añadir estructura «por si acaso»: una interfaz con una sola implementación que nadie más usará o una capa pensada para un requisito que no existe. Fowler señala que esa flexibilidad de reserva solía hacer los sistemas más difíciles de cambiar, no más fáciles.
Primero que funcione y se pruebe; después, que se entienda; al final, que no sobre nada.
Diseño simple cuando programas con IA
Esta sección es criterio propio del enfoque IA Limpia, no algo que escribieran Beck ni Fowler.
Un asistente de IA genera código muy rápido, y es fácil aceptar lo que «parece funcionar». Las cuatro reglas sirven como lista de revisión antes de darlo por bueno:
- Tests: ¿hay tests que demuestren que hace lo que pediste, y los has visto fallar y pasar?
- Intención: ¿entiendes cada nombre y cada función sin que te la expliquen?
- Duplicados: ¿ha copiado una lógica que ya existía en otra parte del proyecto?
- Elementos: ¿ha añadido clases, capas u opciones que nadie pidió?
El orden también ayuda a pedir cambios: primero que los tests pasen, luego que se lea bien y, por último, que sobre lo mínimo.
Tu siguiente paso
Abre un fichero en el que estés trabajando y repásalo con la tabla del principio, en orden. Si no tiene tests, empieza por ahí. Si ya los tiene, busca un duplicado y quítalo; es el cambio pequeño que propone la regla del Boy Scout: deja el código un poco mejor de como lo encontraste.
Fuentes
Consultadas el 7 de noviembre de 2026.
- Martin Fowler, BeckDesignRules (2 de marzo de 2015): formulación de las cuatro reglas, su orden, la relación entre intención y duplicados, y la frase de Beck sobre la empatía (nota 4 del artículo). Fowler cita como versión de referencia la de la primera edición de Extreme Programming Explained, de Kent Beck.
- Robert C. Martin (ed.), Clean Code: A Handbook of Agile Software Craftsmanship (Prentice Hall, 2008), capítulo 12, «Emergence», de Jeff Langr. Las ideas del capítulo se explican con nuestras palabras; no se cita su texto literal.
- El ejemplo de JavaScript se ha ejecutado con Node.js 24.21.0 y su runner de tests integrado (
node:test): los tres tests pasan con la versión de antes y con la de después del refactor.