Módulo 1: Qué son de verdad los patrones

6. El mapa: los pocos patrones que de verdad importan

Descripción

Al terminar esta lección vas a tener el mapa honesto del catálogo: cuáles patrones aparecen de verdad en código real —son ocho, y con ellos cubres la enorme mayoría de lo que vas a encontrar y de lo que vas a necesitar nombrar—, cuáles son cultura general que puedes dejar para después sin ninguna culpa, y cuáles aparecen mucho hoy sin estar en el catálogo original. Vas a tener también las tres familias —creación, estructura, comportamiento— pero presentadas como lo que son: una forma de ordenar la cabeza, no una taxonomía para memorizar.

Esto importa porque el catálogo original tiene 23 patrones y eso, dicho así, suena a una lista que hay que aprenderse entera. No lo es. En una carrera de varios años vas a ver algunos constantemente, otros de vez en cuando y varios probablemente nunca. Tratarlos a todos con el mismo peso es la forma más rápida de agotarse estudiando y de terminar sin poder nombrar nada bien —porque el conocimiento quedó repartido en veintitrés capas delgadas en lugar de ocho capas gruesas—.

Y hay un beneficio secundario que quiero anunciar desde ahora: saber que la lista útil es corta quita presión. Mucha gente evita hablar de estructura en una revisión de código por miedo a usar mal un nombre, y ese miedo viene de creer que hay veintitrés cosas que dominar. No las hay. Con ocho nombres bien entendidos —de verdad entendidos, con su casilla de consecuencias— puedes participar en cualquier discusión de diseño. Los demás se consultan cuando aparecen, que es lo que hace todo el mundo, incluida la gente con veinte años de oficio.

Conexión con el módulo: la lección 5 te dio la técnica para reconocer estructuras. Esta lección te dice qué vale la pena reconocer, o sea sobre qué lista aplicar esa técnica. La lección 7 cierra el módulo advirtiendo contra el efecto secundario de tener el mapa —querer usarlo todo—, y el proyecto de la lección 8 te pide recorrer Boletia con este mapa en la mano. Hacia adelante, este mapa es el índice de los módulos 3, 4 y 5: cada uno de los ocho se estudia a fondo en alguno de ellos, y aquí te digo exactamente en cuál.

Cuatro acordes y cientos de canciones

Hay un chiste viejo entre músicos que dice que la mitad de la música popular de los últimos cincuenta años son los mismos cuatro acordes en distinto orden. Es una exageración, pero apunta a algo real: quien aprende a tocar guitarra descubre pronto que con un puñado pequeño de acordes puede acompañar una cantidad enorme de canciones, y que los acordes raros —los que tienen nombres largos y digitaciones incómodas— aparecen de vez en cuando y se buscan cuando hacen falta.

Nadie aprende guitarra memorizando el diccionario completo de acordes antes de tocar. Se aprenden los cinco o seis que sostienen casi todo, se tocan hasta que salen sin pensar, y el resto se incorpora cuando una canción concreta lo pide. Quien intenta el orden inverso —diccionario primero— normalmente abandona, y no porque le falte talento: porque estudió una lista en lugar de aprender a tocar.

El catálogo de patrones funciona igual. Hay un grupo pequeño que sostiene casi todo el código orientado a objetos que vas a leer, y hay un grupo largo de patrones que resuelven problemas específicos que quizás nunca tengas. Aprender bien los primeros —con su problema, su forma y sus consecuencias— vale muchísimo más que conocer los nombres de los veintitrés.

Y hay un paralelo más, que es el que quiero que te lleves. Un guitarrista con seis acordes bien tocados hace música. Un guitarrista que se sabe el diccionario y no toca ninguno con soltura no hace nada. La diferencia entre saber un patrón y conocerlo de lista es que el que lo sabe también sabe cuándo no usarlo, y eso solo se gana profundizando en pocos.

Ejemplo trabajado: los ocho, señalados sobre Boletia

Antes de las fichas, quiero que veas que los ocho no son abstractos: todos tienen un lugar en el sistema con el que estamos trabajando. Este es el mapa completo de Boletia con los ocho puestos encima.

boletia/
├── checkout/checkout.py     ← el orquestador. Hoy conoce demasiado.
│
├── pricing/                 ← 4 reglas de precio por tipo de boleto
│   └─────────────────────── ▶ STRATEGY   (elegir el cómo del cálculo)
│
├── payments/                ← 3 proveedores con APIs incompatibles
│   ├─────────────────────── ▶ FACTORY    (decidir cuál construir, en un lugar)
│   └─────────────────────── ▶ ADAPTER    (traducir cada SDK a nuestra forma)
│
├── notifications/           ← 3 canales + reintentos
│   ├─────────────────────── ▶ STRATEGY   (familia de canales intercambiables)
│   ├─────────────────────── ▶ DECORATOR  (RetryingChannel envuelve sin modificar)
│   └─────────────────────── ▶ OBSERVER   (lo que falta: avisar sin conocer a quién)
│
├── reports/                 ← 3 exportadores con el mismo esqueleto
│   └─────────────────────── ▶ TEMPLATE METHOD (mismo orden, un paso distinto)
│
├── api/routes.py            ← arma la Order pieza por pieza antes de cobrar
│   └─────────────────────── ▶ BUILDER    (construir algo complicado por partes)
│
└── plugins/                 ← registro dinámico, UNA implementación
    └─────────────────────── ▶ ninguno. Aquí sobra estructura, no falta.

Falta uno de los ocho en ese dibujo, y su ausencia es deliberada: el Facade. En Boletia todavía no hay ninguno, y ese es un hallazgo por sí mismo. Un Facade aparecería el día que alguien quiera darle a todo el módulo de pagos una puerta simple —payments.charge(order)— para que el resto del sistema no tenga que saber que por dentro hay proveedores, adaptadores y una fábrica. Hoy checkout conoce todo eso, y por eso es una función de trescientas líneas.

Qué esperar de este mapa. Cuatro observaciones.

La primera: los ocho caben en un sistema mediano y normal. No hace falta un proyecto exótico para encontrarlos. Boletia es una plataforma de venta de boletos sin nada raro, y ahí están todos.

La segunda: varios conviven en la misma carpeta. payments/ tiene Factory y Adapter porque resuelven dos problemas distintos —decidir cuál usar, y traducir el idioma de cada uno—. notifications/ tiene Strategy y Decorator superpuestos, como viste en la lección 5. Esperar que cada carpeta tenga exactamente un patrón es una expectativa de diagrama, no de código real.

La tercera: uno aparece por su ausencia. Reconocer que falta un Facade es tan valioso como reconocer que hay un Decorator, y es el tipo de observación que solo se puede hacer teniendo el mapa. Sin él, la sensación es "el checkout está enredado"; con él, es "el checkout hace de fachada de tres módulos sin serlo".

Y la cuarta: en el rincón sobre-diseñado no hay ningún patrón que valga, y eso también es leer bien. plugins/ tiene forma de algo, pero la respuesta correcta a "¿qué patrón hay aquí?" es "uno que no debería estar".

Los ocho que importan

Cada ficha va corta a propósito. Aquí no vas a aprender a implementarlos —eso son los módulos 3, 4 y 5—; vas a poder reconocerlos y ubicarlos. Léelas como se lee un índice.


Strategyelegir el cómo

  • El problema: una operación tiene varias formas de hacerse, y el código que la necesita no debería conocerlas todas ni crecer cada vez que aparece una nueva.
  • La forma: una interfaz común, varias implementaciones, y quien la usa recibe la que le toca sin saber cuál es.
  • En Boletia: las cuatro reglas de precio; los tres canales de notificación.
  • La pista al leer: un condicional que crece por tipo, o una familia de clases con el mismo método que llegan como parámetro.
  • El costo: más archivos y un salto extra para saber qué se ejecutó de verdad.
  • Se estudia en: módulo 3, lecciones 2 y 3.

Factorydecidir qué construir, en un solo lugar

  • El problema: la decisión de qué objeto crear está repetida en varios lugares, y cada tipo nuevo obliga a acordarse de todos.
  • La forma: una función o clase cuyo único trabajo es devolver el objeto correcto ya armado; el resto del código pide y recibe sin saber el tipo concreto.
  • En Boletia: elegir el proveedor de pago según Order.provider; elegir el exportador según el formato pedido.
  • La pista al leer: un create_, make_, build_ o for_ con un if o un diccionario de tipos adentro.
  • El costo: una indirección más entre "quiero un X" y "tengo un X"; si es una fábrica para un solo tipo, es puro peso.
  • Se estudia en: módulo 4, lecciones 2 y 3.

Adapterhacer que dos interfaces incompatibles se entiendan

  • El problema: algo externo —un SDK, una librería, un servicio— habla un idioma distinto al de tu código, y ese idioma se está filtrando a todas partes.
  • La forma: una clase en medio que expone la interfaz que tu código ya usaba y por dentro traduce a la del otro.
  • En Boletia: cada proveedor de pago envolviendo el SDK de su proveedor, traduciendo argumentos y respuesta.
  • La pista al leer: un objeto guarda a otro y los nombres de los métodos de afuera y de adentro no coinciden; hay conversión de argumentos o de formato de salida.
  • El costo: una capa más; y el riesgo de que el adaptador se vuelva una copia delgada que no adapta nada.
  • Se estudia en: módulo 5, lecciones 2 y 3.

Facadeuna puerta simple a algo complicado

  • El problema: para hacer una cosa hay que coordinar cinco piezas en cierto orden, y todo el que la necesita tiene que aprenderse las cinco.
  • La forma: una interfaz nueva y estrecha que expone la operación completa y esconde la coordinación.
  • En Boletia: todavía no existe. Aparecería como un payments.charge(order) que esconde fábrica, adaptadores y reintentos.
  • La pista al leer: una clase que envuelve varias cosas, con métodos que hacen varias llamadas internas y ofrecen una operación de más alto nivel.
  • El costo: si la fachada no cubre todos los casos, la gente empieza a saltarla, y terminas con dos caminos de entrada.
  • Se estudia en: módulo 5, lección 4.

Decoratoragregar comportamiento sin tocar el original

  • El problema: quieres que algo haga una cosa más —registrar, reintentar, cachear, validar— sin modificar su código ni el de quien lo usa.
  • La forma: un objeto que envuelve a otro de la misma interfaz, hace lo suyo antes o después, y delega.
  • En Boletia: RetryingChannel, que agrega reintentos a cualquier canal sin que el canal se entere.
  • La pista al leer: un objeto guarda a otro y los métodos se llaman igual en ambos; hay algo alrededor de la delegación.
  • El costo: si se apilan tres o cuatro, seguir qué pasó de verdad en una ejecución se vuelve un rompecabezas.
  • Se estudia en: módulo 5, lección 5.

Observeravisar sin saber a quién

  • El problema: cuando ocurre algo, varias partes tienen que enterarse, y quien lo provoca no debería conocerlas a todas ni crecer cada vez que aparece una interesada nueva.
  • La forma: quien provoca publica un hecho; los interesados se suscriben; un bucle recorre la lista avisando.
  • En Boletia: lo que falta en checkout, que hoy conoce por nombre a los cinco destinatarios de una compra.
  • La pista al leer: una colección de listeners, subscribers, handlers o callbacks, métodos para agregarse y quitarse, y un bucle que dispara.
  • El costo: el más caro de los ocho. El flujo deja de poder seguirse con el dedo: para saber qué pasa al comprar hay que ir a ver quién está suscrito, y eso puede depender de la configuración.
  • Se estudia en: módulo 6, lecciones 2 y 3.

Template Methodel mismo esqueleto, pasos distintos

  • El problema: varias variantes hacen exactamente los mismos pasos en el mismo orden y solo difieren en uno o dos; el orden está copiado en todas.
  • La forma: el esqueleto escrito una sola vez, con huecos que cada variante rellena.
  • En Boletia: los tres exportadores de reportes —traer, ordenar, formatear, escribir—, donde solo cambia el formato.
  • La pista al leer: un método largo en una clase base que llama a métodos vacíos o abstractos que las hijas implementan.
  • El costo: ata las variantes a un esqueleto común. El día que una necesite un orden distinto, aparecen banderas y parámetros que lo ensucian todo.
  • Se estudia en: módulo 3, lección 4.

Builderarmar algo complicado por partes

  • El problema: construir un objeto exige muchos datos, algunos opcionales, algunos con reglas entre sí; el constructor tiene ocho parámetros y nadie sabe cuáles son obligatorios.
  • La forma: un objeto intermedio al que se le van agregando piezas y que al final entrega el objeto terminado y validado.
  • En Boletia: armar una Order —boletos, cliente, cupón, proveedor, comisión, moneda— antes de cobrarla.
  • La pista al leer: llamadas encadenadas (.with_x().with_y().build()) o un objeto que se llena en pasos y tiene un método final.
  • El costo: el objeto puede quedar a medio construir mientras se arma; hay que decidir dónde se validan las reglas.
  • Se estudia en: módulo 4, lección 4.

Ocho fichas. Si te quedas solo con esto de toda la lección, ya tienes con qué participar en cualquier conversación de estructura.

Las tres familias: para ordenar, no para memorizar

El catálogo original agrupó los patrones en tres familias. La agrupación es útil, pero no por la razón que suele darse. No sirve para clasificar —a nadie le pagan por clasificar patrones—; sirve para buscar. Cuando tienes un problema y no sabes qué opciones existen, la familia te dice en qué estante mirar.

FamiliaLa pregunta que respondeLos ocho que caen aquí
Creación"¿Cómo se construye esto y quién decide qué tipo?"Factory, Builder
Estructura"¿Cómo se componen estas piezas entre sí?"Adapter, Facade, Decorator
Comportamiento"¿Quién hace qué, y quién le avisa a quién?"Strategy, Observer, Template Method

La forma práctica de usarlo es al revés de como se enseña. No preguntes "¿de qué familia es el Decorator?" —eso es trivia—. Pregunta al revés, partiendo de tu problema:

  • "Mi dolor está en la construcción: tengo la decisión de qué crear repartida en cuatro lugares." → estante de creación.
  • "Mi dolor está en la composición: esta librería externa me está contaminando veinte archivos." → estante de estructura.
  • "Mi dolor está en el reparto de responsabilidades: esta función conoce a demasiada gente." → estante de comportamiento.

Fíjate que en los tres casos la frase del dolor viene antes que el estante. Ese es el uso correcto, y es coherente con todo lo que llevamos: del problema al patrón, nunca al revés.

Una advertencia sobre las familias, porque genera confusión al estudiar. Las fronteras no son limpias y no importa que no lo sean. El Template Method se parece a Strategy pero está en otra casilla; State y Strategy tienen forma casi idéntica y están juntos; algunos patrones se podrían argumentar en dos familias. Discutir la clasificación es un pasatiempo, no una habilidad. Si alguna vez estás en una conversación sobre si algo es estructural o de comportamiento, y esa conversación no está ayudando a decidir nada sobre el código, es una señal de que el tema se convirtió en trivia.

El resto del catálogo: qué es cultura general

Los quince restantes del catálogo original no son malos ni están obsoletos. Simplemente resuelven problemas menos frecuentes. Vale la pena saber que existen —para reconocer el nombre si alguien lo menciona— y no vale la pena estudiarlos hasta que aparezca su problema.

Un resumen rápido, agrupado por qué tan seguido los vas a ver:

Los que aparecen de vez en cuando, en contextos específicos.

  • Singleton — una sola instancia global de algo. Es el más famoso del catálogo y el que más problemas causa: introduce estado global disfrazado, complica las pruebas y esconde dependencias. Lo vas a ver mucho en código ajeno, así que hay que reconocerlo; el módulo 4 le dedica una lección con el título "el patrón del que más hay que desconfiar".
  • Iterator — recorrer una colección sin exponer cómo está guardada. Aparece muchísimo, pero ya viene de fábrica en casi todos los lenguajes modernos: cada vez que escribes un for sobre algo en Python, estás usando uno. Rara vez lo implementas a mano.
  • Command — empaquetar una acción como objeto para poder guardarla, encolarla o deshacerla. Aparece en editores, en sistemas de tareas y en colas de trabajo. Se ve en el módulo 6.
  • State — el comportamiento cambia según el estado interno del objeto. Útil cuando hay una máquina de estados de verdad. Se ve en el módulo 3.
  • Composite — tratar igual a un elemento y a un grupo de elementos. Aparece en árboles: menús, carpetas, componentes de interfaz. Se ve en el módulo 5.
  • Proxy — controlar el acceso a otro objeto: caché, permisos, creación diferida, medición. Se confunde con el Decorator y conviene saber distinguirlos.

Los que probablemente no vas a necesitar en años.

  • Abstract Factory — familias de objetos relacionados que deben crearse juntos y combinados. Su problema es real pero poco común.
  • Bridge — separar una abstracción de su implementación para que las dos varíen por su lado. Poderoso, difícil de explicar y raro en la práctica.
  • Flyweight — compartir objetos idénticos para ahorrar memoria. Nació en una época de restricciones de memoria muy distintas.
  • Prototype — crear objetos copiando otro. En lenguajes con copia fácil, apenas se nota como patrón.
  • Memento — capturar el estado de un objeto para poder restaurarlo. Aparece en deshacer/rehacer.
  • Mediator — centralizar la comunicación entre muchos objetos. Su riesgo es evidente: el mediador se convierte en un God object.
  • Chain of Responsibility — pasar una petición por una cadena hasta que alguien la atiende. Vive sobre todo en el software de servidores web, donde se llama middleware.
  • Visitor — agregar operaciones a una jerarquía sin modificarla. Aparece en compiladores y procesadores de árboles. Es de los más difíciles y de los menos frecuentes.
  • Interpreter — construir un intérprete para un lenguaje pequeño. Muy específico.

Que esta lista exista y que no la vayamos a estudiar es una decisión deliberada de la guía y quiero que quede dicha con todas sus letras: conocer estos quince no te vuelve mejor programador. Reconocer un Visitor si te lo encuentras es útil; estudiarlo antes de encontrarlo es tiempo que rinde más en otro lado. Si algún día tu problema es "necesito agregar operaciones nuevas a un árbol de tipos sin tocar las clases", vas a buscar, vas a encontrar el Visitor, y con la plantilla de tres casillas de la lección 2 lo vas a entender en media hora. Eso es suficiente.

Los que no están en el catálogo y sí vas a ver

El catálogo original es de 1994 y el oficio siguió descubriendo senderos. Estos no son GoF, pero aparecen en conversaciones reales con la misma naturalidad, y conviene que reconozcas los nombres:

  • Repository — concentrar en un lugar el acceso a los datos, para que el resto del código pida objetos y no sepa de consultas ni de tablas. En Boletia sería el papel de repository.get_order().
  • Dependency Injection — en vez de que un objeto construya lo que necesita, se lo pasan desde fuera. Suena grande y es una idea pequeña; el módulo 4 le dedica una lección con el título "en palabras simples".
  • Null Object — en lugar de devolver None y obligar a todos a preguntar, devolver un objeto que cumple la interfaz y no hace nada. En Boletia, un NoOpChannel para clientes sin teléfono evitaría varios condicionales.
  • Value Object — un objeto pequeño e inmutable que se compara por su contenido y no por su identidad. Un Money(amount, currency) en Boletia evitaría la mitad de los errores de redondeo y de moneda.
  • Middleware / Pipeline — una cadena de piezas por la que pasa una petición, cada una pudiendo actuar o dejar pasar. Es Chain of Responsibility con otro nombre y en su hábitat natural.

Hay una familia más que verás mencionada seguido —Circuit Breaker, Retry con backoff, Bulkhead— y que conviene ubicar bien: son patrones de resiliencia entre servicios, o sea del nivel de arquitectura de sistemas. Están fuera del alcance de esta guía, que trabaja dentro de un proceso. Los menciono para que reconozcas la frontera cuando alguien los traiga a una conversación: comparten la palabra "patrón" y viven en otro piso del edificio.

Errores comunes

Estudiar los veintitrés con el mismo peso (de estudio). Qué pasa: alguien decide "aprenderse los patrones" y arma un plan de veintitrés fichas. Llega al octavo o noveno con la energía baja, y termina con veintitrés conocimientos superficiales en lugar de ocho sólidos. En una revisión real no puede usar ninguno con confianza, porque de todos sabe el diagrama y de ninguno las consecuencias. Por qué pasa: la lista existe y las listas invitan a completarse. Además, "me sé los 23" suena a logro medible, mientras que "entiendo ocho de verdad" suena a menos. Cómo detectarlo: si puedes nombrar quince patrones pero no puedes decir el costo de ninguno, tienes anchura sin profundidad. Cómo corregirlo: los ocho de esta lección, con su casilla de consecuencias completa, y el resto por consulta cuando aparezca su problema. Es lo que hace la gente con experiencia, aunque no lo diga.

Usar las familias como si fueran una taxonomía obligatoria (conceptual). Qué pasa: alguien invierte esfuerzo en clasificar correctamente cada patrón y en discutir si algo es estructural o de comportamiento. Es una actividad que se siente rigurosa y no cambia ninguna decisión sobre el código. Por qué pasa: las tres familias son lo más parecido a una estructura formal que tiene el tema, y las estructuras formales atraen a quien quiere sentir que está aprendiendo algo sólido. Cómo detectarlo: si una conversación sobre patrones lleva cinco minutos y todavía no se habló de código concreto, se convirtió en trivia. Cómo corregirlo: usa las familias solo en la dirección útil —del dolor al estante— y acepta que las fronteras son borrosas por diseño.

Descartar un patrón porque "no está en la lista de los ocho" (de criterio). Qué pasa: alguien lee esta lección, se queda con los ocho, y meses después rechaza una propuesta perfectamente buena porque el patrón involucrado no estaba en el mapa. El mapa se convirtió en un límite en vez de una prioridad de estudio. Por qué pasa: es la reacción natural a cualquier lista corta —se lee como exhaustiva—. Cómo detectarlo: si tu argumento contra algo es "eso casi no se usa", no es un argumento sobre tu caso; es una estadística sobre otros casos. Cómo corregirlo: recuerda para qué es el mapa. Dice qué estudiar primero, no qué es válido. Si tu problema es exactamente el que resuelve un Visitor, el Visitor es la respuesta correcta aunque sea raro. La pregunta siempre es la misma: ¿tengo el problema? Con eso alcanza.

Ejercicios

Ejercicio 1 — Del dolor al estante. Para cada queja, escribe: (a) a qué familia pertenece el problema, (b) qué patrón de los ocho es el candidato más probable, (c) una condición que tendría que cumplirse para que valga la pena.

  1. "Cada vez que agregamos un tipo de reporte, hay que tocar tres archivos que ni siquiera son del módulo de reportes."
  2. "Para mandar un correo de confirmación hay que llamar a cinco cosas en el orden correcto, y ya hay tres lugares que lo hacen, cada uno con su propia versión del orden."
  3. "Cambiamos de proveedor de SMS y tuvimos que tocar catorce archivos, porque el nombre de su función estaba escrito por todos lados."
  4. "Queremos registrar cuánto tarda cada envío de notificación, pero no queremos meter código de medición dentro de cada canal."
Ver solución

1. (a) Creación. El dolor está en "quién decide qué se construye": la decisión del tipo de reporte está regada. (b) Factory —concentrar la decisión en un lugar para que los tres archivos externos solo pidan—. (c) Que haya al menos tres tipos reales y que la lista siga creciendo; con dos tipos estables, una fábrica es ceremonia. También conviene verificar por qué esos tres archivos externos deciden el tipo: puede que el problema real sea otro y que la fábrica solo lo tape.

2. (a) Estructura. El dolor está en la composición: una operación exige coordinar cinco piezas. (b) Facade —una puerta única send_confirmation(order) que esconde el orden—. (c) Que la secuencia sea de verdad la misma en los tres lugares. Si cada uno tiene variaciones legítimas, una fachada rígida los va a obligar a saltarla, y terminas con dos caminos de entrada, que es peor que el problema original.

3. (a) Estructura. Una dependencia externa está filtrada por todo el código. (b) Adapter —una clase que hable nuestro idioma y traduzca al del proveedor, de modo que cambiarlo toque un archivo—. (c) Que exista una segunda opción real o la expectativa razonable de cambiar. Ojo con el matiz: aquí el argumento se sostiene incluso con un solo proveedor, porque el problema no es la variedad sino el contagio —catorce archivos que hablan un idioma ajeno—. Es una de las pocas situaciones donde una sola implementación puede justificar la abstracción, y por eso el módulo 5 la trata con cuidado.

4. (a) Estructura. (b) Decorator —un TimingChannel que envuelve a cualquier canal, mide y delega—. (c) Que la medición sea de verdad genérica y aplicable a todos por igual. Si cada canal necesita medir cosas distintas, el envoltorio no sirve y hay que ponerlo dentro. Y conviene notar que ya existe un decorador de reintentos: apilar dos —medición sobre reintento, o al revés— tiene consecuencias distintas según el orden, y eso hay que decidirlo a propósito.

Por qué funciona: en los cuatro casos partiste del dolor y llegaste al estante, nunca al revés. Y en los cuatro, la condición de (c) fue lo que decidió de verdad —incluso cuando el patrón era el correcto—.

Ejercicio 2 — Audita tu propio mapa. Sin volver a mirar las fichas, escribe de memoria los ocho patrones del mapa y, para cada uno, una sola frase con su costo —no su beneficio—. Después compara con las fichas y marca cuáles no pudiste.

Ver solución

Los costos, en la forma más corta posible:

  • Strategy — más archivos y un salto extra para saber qué se ejecutó de verdad.
  • Factory — una indirección entre pedir el objeto y tenerlo; si hay un solo tipo, es peso muerto.
  • Adapter — una capa más, con el riesgo de volverse una copia delgada que no traduce nada.
  • Facade — si no cubre todos los casos, la gente la salta y quedan dos caminos de entrada.
  • Decorator — apilados, seguir qué ocurrió en una ejecución concreta se vuelve un rompecabezas.
  • Observer — el más caro: el flujo deja de poder seguirse con el dedo, y quién escucha puede depender de la configuración.
  • Template Method — ata las variantes a un esqueleto común; cuando una diverge, aparecen banderas.
  • Builder — el objeto existe a medio construir mientras se arma; hay que decidir dónde viven las validaciones.

Sobre las que no pudiste: eso no es un fallo de memoria, es información. Los costos son la parte que el material sobre patrones sistemáticamente omite, así que es normal que sean los que menos se retienen. Si te faltaron más de dos o tres, vale la pena volver a las fichas y leerlas solo por la línea del costo, ignorando el resto.

Por qué funciona: este ejercicio invierte deliberadamente lo que todo el mundo memoriza. Cualquiera puede decir para qué sirve un Observer; poca gente puede decir qué se paga por él. Y en una discusión de diseño real, la persona que puede decir el costo es la que decide.

Ejercicio 3 — El patrón que falta. En el mapa de Boletia señalamos que no hay ningún Facade y que eso es un hallazgo. Elige otro de los ocho que tampoco esté claramente presente hoy en Boletia, y escribe: (a) por qué no está, (b) qué tendría que pasar para que se ganara su lugar, (c) qué señal concreta te avisaría de que llegó ese momento.

Ver solución

Hay varias respuestas válidas. Dos ejemplos desarrollados.

Opción: el Observer. (a) No está porque checkout conoce por nombre a los cinco destinatarios de una compra y les habla directo. Esa forma directa es más simple y perfectamente razonable con pocos destinatarios. (b) Se ganaría su lugar cuando aparezcan interesados que no tengan nada que ver con el cobro —fraude, facturación, un webhook para el organizador— y cuando el hecho de que uno falle no deba tumbar el cobro. (c) La señal concreta: el día que alguien tenga que abrir checkout.py, el archivo más delicado del sistema, solo para agregar un destinatario que no tiene relación con cobrar. Ese es el momento. Antes de eso es adivinar.

Opción: el Builder. (a) Hoy la Order se arma en api/routes.py con unas pocas asignaciones, y alcanza. (b) Se ganaría su lugar cuando armar una orden implique reglas entre campos —un cupón que exige cierto tipo de boleto, una moneda que restringe proveedores, cortesías que no pueden mezclarse con pagos— y cuando esas reglas empiecen a estar repetidas en varios lugares que crean órdenes. (c) La señal: que aparezca un segundo lugar donde se construyen órdenes —por ejemplo, la venta en taquilla o una importación masiva— y que las validaciones se copien ahí. La duplicación de las reglas de construcción es la señal, no la cantidad de campos.

Por qué funciona: las tres preguntas te obligan a hacer explícito el criterio en lugar de la forma. Y la pregunta (c) es la más valiosa de las tres: convierte un juicio vago —"cuando haga falta"— en un disparador observable. Un equipo que sabe decir "cuando pase X, refactorizamos esto" toma decisiones mucho mejores que uno que abstrae por si acaso o que nunca abstrae. El módulo 2 va a formalizar ese disparador con la regla de tres.

Resumen y siguiente paso

En esta lección recibiste el mapa honesto. De las docenas del catálogo, ocho aparecen constantemente en código real: Strategy, Factory, Adapter, Facade, Decorator, Observer, Template Method y Builder. Los viste señalados sobre Boletia y comprobaste que los ocho caben en un sistema mediano y normal, que varios conviven en la misma carpeta, que uno —el Facade— aparece por su ausencia, y que en el rincón sobre-diseñado no hay ninguno que valga.

Tienes las ocho fichas con lo esencial: el problema en una frase, la forma, dónde está en Boletia, la pista para reconocerlo, su costo, y en qué módulo se estudia a fondo. Tienes las tres familias —creación, estructura, comportamiento— usadas en la dirección correcta: del dolor al estante, nunca al revés, y con el permiso explícito de no tomarte sus fronteras demasiado en serio. Tienes el resto del catálogo ubicado como cultura general, con el Singleton marcado como algo que hay que reconocer aunque casi nunca convenga escribir. Y tienes los que no son GoF y sí verás: Repository, Dependency Injection, Null Object, Value Object, Middleware, más la frontera con los patrones de resiliencia, que viven en el piso de la arquitectura de sistemas.

Antes de avanzar deberías poder: nombrar los ocho y decir el costo de al menos cinco; ubicar un dolor concreto en la familia que le corresponde; y explicar por qué "no está en la lista de los ocho" no es un argumento contra un patrón.

Con el mapa en la mano viene el riesgo. Tener ocho nombres frescos produce un efecto muy documentado y muy incómodo: de pronto todo el código que lees parece pedir uno. La lección 7 se dedica entera a eso —cómo no estudiar patrones—: el síndrome del martillo nuevo, la trampa de memorizar diagramas, la creencia de que más patrones es mejor código, y qué hacer en su lugar. Es la lección que prepara el terreno del módulo 2, que trata completo sobre cuándo no abstraer.

Recursos