Módulo 1: Qué son de verdad los patrones
1. Presentación del módulo: patrones como lenguaje, no como recetas
Descripción
Al terminar esta lección vas a tener tres cosas. Primero, una idea clara de qué promete esta guía y qué no: no salir con veintitrés nombres memorizados, sino con vocabulario para nombrar lo que ves en código ajeno y criterio para juzgar si una estructura se gana su lugar. Segundo, vas a conocer Boletia, la plataforma de venta de boletos sobre la que vamos a trabajar durante los ocho módulos, con el detalle suficiente para reconocerla cada vez que reaparezca. Y tercero, vas a tener el mapa completo de la guía y la frontera con las guías hermanas del ecosistema, para saber exactamente qué se aprende aquí y qué se aprende al lado.
Esto importa por una razón que se nota apenas entras a un equipo real. Casi todo el mundo estudia patrones de diseño al revés: se aprende una lista de nombres con sus diagramas, y después se sale a buscar dónde meterlos. El resultado de esa forma de estudiar tiene un nombre en la industria, y no es halagador: código sobre-diseñado. Tres capas de indirección para algo que era una función. Una fábrica que construye un solo tipo de objeto. Una interfaz con una sola implementación, que existe únicamente porque alguien leyó que "hay que programar contra interfaces". Ese código es más difícil de cambiar que el código sin patrones que quería reemplazar, y quien lo escribió normalmente creía estar haciendo lo correcto.
Esta guía invierte el orden. Primero instala qué es de verdad un patrón. Después el valor real que tiene —poder nombrar estructuras en una conversación—. Y solo después enseña a reconocerlos en código que otra persona escribió. Los módulos 3, 4, 5 y 6 sí enseñan patrones concretos, pero llegan sobre una base que ya sabe cuándo no usarlos. Ese orden es la diferencia entre alguien que aplica patrones y alguien que decide sobre ellos.
Conexión con el módulo: esta lección es el marco, no el contenido. Aquí todavía no vas a nombrar ningún patrón; vas a entender por qué el módulo está ordenado como está y vas a conocer el código sobre el que practicaremos todo. La lección 2 define qué es un patrón y desarma sus tres partes, con énfasis en la tercera —las consecuencias— que es la que casi nadie estudia. La lección 3 explica el superpoder real: el vocabulario compartido. La lección 4 cuenta de dónde salieron los patrones y por qué se descubrieron en vez de inventarse. La lección 5 te da la técnica concreta para reconocer un patrón en código que nadie etiquetó. La lección 6 dibuja el mapa honesto: cuáles de las docenas del catálogo aparecen de verdad. La lección 7 dice de frente cómo no estudiarlos, y prepara el terreno del módulo 2. Y la lección 8 —el proyecto— te pide recorrer Boletia y entregar un inventario de lo que reconoces, sin cambiar una línea.
Un oficio que no tenía nombres para sus propias cosas
Piensa en una cocina profesional durante un servicio. El jefe de cocina no dice: "pica cebolla, ajo y jitomate en cubos chicos, ponlos en aceite a fuego medio y déjalos hasta que la cebolla se ponga transparente y suelte su dulzor". Dice: "hazme un sofrito". Una palabra, y la persona del otro lado sabe la secuencia completa, el punto exacto y para qué sirve. Nadie inventó el sofrito en una reunión de chefs; alguien notó que esa misma secuencia aparecía al principio de un montón de platos distintos, le puso nombre, y el nombre se quedó porque era útil.
Fíjate en lo que ese nombre hace y en lo que no hace. No hace mejor cocinero a nadie: quien no sabe cocinar no cocina mejor por saber la palabra "sofrito". Lo que hace es volver comunicable algo que ya existía. Y de paso vuelve pensable: cuando tienes la palabra, puedes preguntarte cosas como "¿este plato de verdad necesita sofrito o lo estoy poniendo por costumbre?". Sin la palabra, esa pregunta es difícil de formular.
Los oficios maduros están llenos de estos nombres. Un médico dice "fractura por estrés" y con dos palabras transmite el mecanismo (carga repetida, no un golpe), el tratamiento probable (reposo) y el pronóstico. Un músico dice "un II-V-I" y otro músico sabe qué tocar. Un arquitecto dice "un patio central" y su colega ve la planta entera, con su ventilación y su luz.
La programación es un oficio joven y durante décadas no tuvo esos nombres. Dos personas podían escribir exactamente la misma estructura en el mismo mes, en dos empresas distintas, y no tener manera de reconocer que habían hecho lo mismo. Los patrones de diseño son, antes que ninguna otra cosa, el vocabulario que ese oficio se dio a sí mismo. Un patrón es un nombre para una solución que la gente ya estaba usando.
Esto ya deja ver por qué el estudio memorístico falla. Aprenderse "sofrito" sin haber sofrito nunca no te vuelve cocinero, y aprender la lista de nombres sin haber sentido el problema que cada uno resuelve no te vuelve mejor diseñador. Peor: te da un martillo nuevo y la tentación de ver clavos donde hay tornillos. Vamos a ver ese fenómeno con nombre y apellido en la lección 7.
Ejemplo trabajado: la misma revisión de código, con y sin vocabulario
Vamos a hacer visible el valor del vocabulario con una escena que ocurre todos los días. Estás revisando el cambio de un compañero en Boletia. Él agregó un tercer proveedor de pago y el código quedó así:
# Archivo: checkout/checkout.py
# Fragmento del checkout tras agregar el tercer proveedor de pago.
def charge(order, provider_name):
# Cada proveedor cobra distinto, así que decidimos aquí con un condicional.
if provider_name == "stripe":
client = StripeClient(api_key=settings.STRIPE_KEY)
# Stripe trabaja en centavos, por eso multiplicamos.
return client.create_charge(amount=int(order.total * 100), currency="MXN")
elif provider_name == "mercadopago":
client = MercadoPagoClient(token=settings.MP_TOKEN)
# MercadoPago quiere el monto como float y el concepto aparte.
return client.pay(order.total, description=f"Boletia #{order.id}")
elif provider_name == "cash":
# El pago en efectivo no cobra: genera una referencia para pagar en tienda.
reference = generate_cash_reference(order.id)
return {"status": "pending", "reference": reference}
else:
raise ValueError(f"Proveedor desconocido: {provider_name}")
Tú notas algo: cada vez que Boletia agregue un proveedor de pago, alguien va a tener que volver a esta función y meter otro elif. Y esa función vive en el corazón del checkout, el lugar donde nadie quiere equivocarse.
Cómo suena esa observación sin vocabulario compartido. Escribes un comentario en la revisión:
"Oye, veo que aquí hay un condicional que va creciendo cada vez que agregamos una forma de cobrar. Me preocupa que esta función se vuelva enorme y que cada proveedor nuevo obligue a tocar el checkout, que es la parte más delicada del sistema. ¿No sería mejor que cada proveedor viviera en su propio archivo, con la misma forma —el mismo nombre de método, los mismos parámetros—, y que el checkout solo pidiera 'cóbrame esto' sin saber cuál es? Así agregar un cuarto proveedor sería crear un archivo nuevo en vez de editar este."
Es un buen comentario. Es claro, es correcto, y te tomó cuatro minutos escribirlo. Tu compañero lo lee y tiene que reconstruir en su cabeza la estructura que estás describiendo, porque se la diste en prosa.
Cómo suena con vocabulario compartido. Escribes:
"Esto pide una Strategy: cada proveedor como una implementación de
PaymentProvider, y el checkout eligiendo cuál usar. Así agregar el cuarto es un archivo nuevo, no unelifmás en el corazón del sistema."
Dos líneas. Treinta segundos. Y tu compañero, que conoce la palabra, ya vio la estructura completa: la interfaz común, las clases que la implementan, el punto donde se elige. No tuvo que reconstruir nada.
Qué esperar de esta comparación. Lo primero que hay que decir es lo que no cambió: el diagnóstico es idéntico en los dos casos. El vocabulario no te hizo ver algo que no veías. Lo que cambió es el costo de transmitirlo —de cuatro minutos a treinta segundos— y la precisión con la que llegó al otro lado. Eso es el 80% del valor de los patrones en el trabajo diario, y por eso esta guía insiste tanto en la palabra "vocabulario".
Pero hay un segundo efecto, más silencioso y más importante. Cuando tienes el nombre, puedes hacerte la pregunta siguiente: "¿esto de verdad necesita una Strategy?". En este caso hay tres proveedores reales, con lógicas de verdad distintas, y Boletia planea agregar más. La Strategy se gana su lugar. Pero imagina que solo hubiera un proveedor y el if fuera un if de un solo caso: la misma estructura, aplicada ahí, sería puro peso muerto. Sin el nombre, esa pregunta es vaga. Con el nombre, es concreta y se puede discutir en equipo.
Y un tercer efecto, este menos agradable: el vocabulario mal usado hace daño. Si en vez de "Strategy" hubieras escrito "esto pide un Factory" —que es otra cosa—, tu compañero habría ido en una dirección equivocada con toda confianza. Nombrar mal confunde más que no nombrar. La lección 3 vuelve sobre esto en serio.
El caso de estudio de la guía: Boletia
Toda la guía trabaja sobre el mismo sistema inventado. La razón es la misma por la que un aprendiz de mecánico practica siempre sobre el mismo motor: si cada lección estrenara un proyecto nuevo, gastarías la mitad de tu atención entendiendo el contexto en vez de practicando la idea. Con un solo caso, para el módulo 4 ya conoces Boletia de memoria y puedes concentrarte en lo que cada lección agrega.
Boletia es una plataforma mediana de venta de boletos para eventos. Piensa en el tipo de sistema donde un organizador publica un concierto, un teatro o una conferencia, define cuántos boletos hay y de qué tipo, y la gente entra a comprar. Nada exótico. Justamente por eso sirve: es el tipo de sistema que existe en miles de empresas.
Boletia es terreno especialmente fértil para los patrones por una razón estructural: casi todo en ella varía. Y los patrones, como veremos en el módulo 3, viven exactamente donde algo varía.
- Notifica por varios canales. Cuando alguien compra, hay que avisarle. Por correo siempre; por SMS si dio su teléfono; por notificación push si tiene la app instalada. Y el organizador del evento también quiere enterarse.
- Cobra con varios proveedores de pago. Tarjeta a través de un proveedor, transferencia y billeteras a través de otro, y pago en efectivo en tienda mediante una referencia. Cada uno tiene una API distinta, con nombres distintos y hasta unidades distintas.
- Maneja tipos de boleto con reglas de precio diferentes. General, VIP, early-bird (descuento por comprar temprano, con fecha de corte) y cortesía (precio cero, con reglas propias sobre cuántas se pueden emitir).
- Exporta reportes en varios formatos. El organizador quiere su lista de asistentes en CSV, la administración quiere un PDF con el corte de caja y contabilidad quiere una hoja de cálculo.
Cuatro ejes de variación, cuatro lugares donde un patrón puede tener sentido. Pero Boletia también tiene el otro lado de la historia, y por eso es un caso honesto y no una maqueta: alguien, hace dos años, metió una arquitectura de plugins completa para el mapa de asientos —con registro dinámico, interfaz abstracta y descubrimiento automático de módulos— y hasta hoy existe una sola implementación. Ese rincón nadie lo entiende, nadie lo toca y todos le tienen respeto. Es el ejemplo vivo de una abstracción que no se ganó su lugar, y va a ser protagonista del módulo 2 y del proyecto final.
La historia de Boletia es la historia de casi todo el software real. Empezó como un script para vender boletos de un festival local. Funcionó, el festival creció, llegaron otros organizadores, y en tres años se convirtió en una plataforma con seis personas trabajando en ella. Las decisiones se tomaron en momentos distintos, con información distinta, y algunas de las que hoy se ven raras eran correctas cuando se tomaron. Y aquí entras tú: eres la persona nueva del equipo. No escribiste una línea de este código. Tu primer trabajo no es mejorarlo: es entenderlo y saber nombrarlo.
El modelo de datos
En el corazón de Boletia hay cuatro conceptos. Los identificadores van en inglés —Event, Ticket, Order, Customer— porque así es el mercado tech real: la documentación, las librerías y el equipo con el que vas a trabajar hablan ese idioma. La prosa que lees va en español; los nombres dentro del código, en inglés.
# Archivo: models/event.py
class Event:
id: int
name: str # "Festival Cumbre 2026"
venue: str # "Teatro Metropolitan"
starts_at: str # cuándo empieza el evento
organizer_id: int # el id del Customer que organiza
# Archivo: models/ticket.py
class Ticket:
id: int
event_id: int
kind: str # "general" | "vip" | "early_bird" | "courtesy"
base_price: float # el precio antes de aplicar reglas
seat: str | None # "A-14", o None si el evento es de admisión general
status: str # "available" | "reserved" | "sold"
# Archivo: models/order.py
class Order:
id: int
customer_id: int
ticket_ids: list[int]
total: float # se calcula aplicando las PricingRule a los tickets
provider: str # "stripe" | "mercadopago" | "cash" ← texto libre. Recuérdalo.
status: str # "pending" | "paid" | "cancelled"
created_at: str
# Archivo: models/customer.py
class Customer:
id: int
name: str
email: str
phone: str | None # si es None, no se puede notificar por SMS
push_token: str | None
Detente en tres detalles, porque van a reaparecer durante toda la guía:
Ticket.kindes un texto libre. En teoría solo vale"general","vip","early_bird"o"courtesy". En la práctica, como es un simplestr, hay condicionales repartidos por el código que lo comparan cada uno a su manera. Ese campo es el que va a empujar hacia una Strategy en el módulo 3.Order.providertambién es texto libre, y es lo que alimenta elif/elifque viste en el ejemplo trabajado. Ese campo es el que va a empujar hacia una Factory en el módulo 4.Customer.phoneyCustomer.push_tokenpueden serNone. Es decir, no todos los canales están disponibles para todos los clientes. Ese detalle —que parece menor— es el que hace interesante el problema de notificación del módulo 6.
Cómo está organizada por dentro
Boletia está escrita en Python, sin ningún framework grande, para que puedas leerla sin pelearte con la magia de una librería. Pero conviene decirlo desde ahora y lo vamos a repetir: los patrones son ideas agnósticas del lenguaje. La estructura que verás abajo existe casi igual en Java, en C#, en TypeScript o en Go. Python es el vehículo; las ideas viajan.
Más aún: hay lenguajes que vuelven innecesarios algunos patrones. Una Strategy escrita con clases en Java se convierte, en Python o en JavaScript, en pasar una función como argumento —y en ese caso la clase sobra—. Eso no significa que el patrón desaparezca: significa que el lenguaje ya lo trae resuelto. Cada vez que aparezca un caso así te lo voy a señalar, y el módulo 3 le dedica una lección entera.
Así se ven las carpetas de Boletia:
boletia/
├── app.py # punto de entrada: arranca la app y registra las rutas
├── api/
│ └── routes.py # endpoints HTTP: /events, /checkout, /reports
├── models/
│ ├── event.py # class Event
│ ├── ticket.py # class Ticket
│ ├── order.py # class Order
│ └── customer.py # class Customer
├── checkout/
│ └── checkout.py # checkout(): el corazón. ~300 líneas y creciendo.
├── pricing/
│ ├── rules.py # PricingRule y las reglas por tipo de boleto
│ └── calculator.py # aplica las reglas a una orden
├── payments/
│ ├── provider.py # PaymentProvider: la forma común de cobrar
│ ├── stripe_provider.py
│ ├── mercadopago_provider.py
│ └── cash_provider.py # genera referencia para pagar en tienda
├── notifications/
│ ├── channel.py # NotificationChannel: la forma común de avisar
│ ├── email_channel.py
│ ├── sms_channel.py
│ ├── push_channel.py
│ └── notifier.py # notify(): decide a quién y por dónde
├── reports/
│ ├── exporter.py # ReportExporter: la forma común de exportar
│ ├── csv_exporter.py
│ ├── pdf_exporter.py
│ └── xlsx_exporter.py
├── plugins/ # ← el rincón sobre-diseñado
│ ├── registry.py # PluginRegistry: registro y descubrimiento dinámico
│ ├── base.py # SeatingPlugin: la interfaz abstracta
│ └── impls/
│ └── default_seating.py # la ÚNICA implementación que existe
└── utils/
└── dates.py # parseo de fechas y zonas horarias
No hace falta memorizar esto ahora. Quédate con la forma general: hay cuatro carpetas que agrupan familias de cosas que varían (pricing, payments, notifications, reports), un archivo que las orquesta (checkout/checkout.py) y un rincón raro (plugins/). Esa forma no es casualidad: es exactamente el terreno donde los patrones viven.
Por dónde pasa una compra
Aquí está la idea más útil de la lección, y la que el proyecto del módulo te va a pedir recorrer. Cuando alguien compra un boleto en Boletia, la petición atraviesa el sistema en un orden bastante predecible:
Cliente (la app o el sitio)
│ POST /checkout {ticket_ids, provider, customer_id}
▼
api/routes.py ← recibe la petición y arma la Order
│
▼
checkout/checkout.py ← el orquestador: checkout(order)
│
├──► pricing/calculator.py ──► pricing/rules.py ← ¿cuánto se cobra?
│
├──► payments/... ← ¿con qué proveedor se cobra? (el if/elif)
│
├──► plugins/registry.py ← ¿hay asiento asignado? (el rincón raro)
│
└──► notifications/notifier.py ──► email / sms / push ← notify(): ¿a quién se avisa?
│
▼
api/routes.py ← devuelve la confirmación
▼
Cliente (recibe su boleto)
Ese recorrido es el esqueleto del sistema. Cada uno de los módulos 3 a 6 se va a parar en una de esas ramas: el módulo 3 en pricing, el módulo 4 en payments, el módulo 5 en la adaptación de las APIs externas de pago, el módulo 6 en notifications. Y los módulos 2 y 8 se van a parar en plugins/, que es la rama que no debería existir.
Los cinco rincones que vamos a visitar
Menciono estos cinco ahora porque van a reaparecer en cada módulo, y porque el proyecto de la lección 8 te pedirá recorrerlos por tu cuenta:
pricing/— cuatro reglas de precio. General usa el precio base. VIP le suma un porcentaje. Early-bird descuenta si la compra ocurre antes de una fecha de corte. Cortesía es precio cero con un tope de emisiones. Cuatro comportamientos distintos para la misma pregunta: "¿cuánto cuesta este boleto?".payments/— tres proveedores con APIs incompatibles. Uno recibe centavos como entero, otro recibe un float, el tercero ni siquiera cobra: genera una referencia. Tres formas de decir "cóbrame", y uncheckoutque hoy las conoce todas por dentro.notifications/— tres canales y varios interesados. Al comprar hay que avisarle al cliente (por los canales que tenga disponibles) y al organizador. Hoy elcheckoutllama a cada canal directamente, lo que significa que agregar un cuarto interesado obliga a tocar el checkout.reports/— tres exportadores con el mismo esqueleto. Los tres hacen lo mismo en el mismo orden: pedir los datos, ordenarlos, darles formato, escribir el archivo. Solo cambia el paso del formato. Ese "mismo esqueleto, un paso distinto" tiene nombre y lo veremos en el módulo 3.plugins/— la arquitectura para una sola implementación. Un registro dinámico, una clase base abstracta con cinco métodos, un mecanismo de descubrimiento que importa módulos por nombre… ydefault_seating.py, que es lo único que se registra desde que existe. Para saber qué hace el mapa de asientos hay que leer tres archivos en vez de uno.
Los primeros cuatro son lugares donde un patrón puede ganarse su lugar. El quinto es un lugar donde uno no se lo ganó. Que la guía tenga los dos casos no es un adorno: la mitad del criterio que quiero dejarte es saber distinguirlos.
El encargo que va a hilar toda la guía
Boletia no está aquí solo para que la mires. En el módulo 8 vas a recibir un encargo concreto, el tipo de encargo que llega un martes cualquiera:
"El
checkoutya no lo entiende nadie y el rincón de plugins nos da miedo. Necesitamos poder agregar un cuarto proveedor de pago sin tocar el corazón del sistema, y quitarnos de encima lo que sobra."
Fíjate que el encargo tiene las dos direcciones: agregar estructura donde falta e quitar estructura donde sobra. Casi todos los cursos de patrones enseñan solo la primera. Esta guía enseña las dos, y para el proyecto final vas a entregar no solo el código sino un documento corto que justifique cada decisión con su tradeoff. Se juzga por el criterio, no por la cantidad de patrones aplicados.
El mapa de la guía: qué te deja cada módulo
Los ocho módulos no están en cualquier orden. Van de entender qué es un patrón a saber cuándo no usarlo a conocer los que importan a usarlos como vocabulario de revisión. Fíjate especialmente en dónde está el módulo 2.
| Módulo | Qué instala | Capacidad con la que sales |
|---|---|---|
| 1. Qué son de verdad los patrones | La definición honesta: solución con nombre a un problema recurrente, descubierta y no inventada. El vocabulario como el valor principal | Nombrar estructuras en código ajeno y distinguir el puñado que importa del ruido del catálogo |
| 2. Cuándo NO abstraer | El contrapeso, antes que cualquier patrón concreto: cada abstracción se paga, la regla de tres, YAGNI, el plugin para una sola implementación | Decir "aquí no" con argumentos, y detectar abstracción prematura |
| 3. Comportamiento que varía | Strategy, Template Method, State. Y la frontera: cuándo una función de primera clase le gana a una clase | Separar lo que cambia de lo que no, sin convertir cada if en una jerarquía |
| 4. Crear objetos | Factory, Builder, Singleton (el sospechoso) e inyección de dependencias en palabras simples | Ordenar el "cómo se construye esto" sin ceremonia innecesaria |
| 5. Estructurar y adaptar | Adapter, Facade, Decorator, Composite. Y la línea con "solo escribe una función que envuelva" | Aislar una dependencia externa para que su desorden no se filtre |
| 6. Comunicar entre partes | Observer, Command, acoplamiento por evento. Y su costo escondido: el flujo que ya no puedes seguir con el dedo | Desacoplar quién avisa de quién escucha, sabiendo lo que pierdes |
| 7. Vocabulario de revisión | El otro lado del diccionario: code smells, God object, feature envy, shotgun surgery, anti-patrones | Nombrar un problema en una revisión de forma que sea accionable, no una sentencia |
| 8. Refactorizar con criterio (capstone) | El cierre: leer antes de tocar, detectar el patrón que quiere emerger y el que hay que quitar, pasos pequeños, justificar el porqué | Refactorizar un rincón real y defender cada decisión con su tradeoff |
Nota la forma del arco. El módulo 1 instala el lenguaje. El módulo 2 —justo antes de enseñar un solo patrón concreto— instala el freno. Los módulos 3 a 6 son el catálogo útil, agrupado por el tipo de problema que resuelve. El módulo 7 gira el vocabulario hacia la conversación de equipo. El módulo 8 junta todo.
Que el freno venga antes que el catálogo es deliberado y es, probablemente, la decisión de diseño más importante de esta guía. Enseñar Strategy antes de enseñar cuándo no usar Strategy es cómo se fabrica el síndrome del martillo nuevo.
La frontera: esta guía no es el ecosistema entero
Esta guía vive junto a otras del ecosistema Software Development, y tiene una regla estricta sobre qué enseña y qué no. Conviene que la conozcas desde ahora para que no esperes de aquí algo que le toca a otra.
| Tema | Qué se ve aquí | Dónde vive de verdad |
|---|---|---|
| Conceptos base: descomposición, responsabilidad única, acoplamiento, cohesión, abstracción básica, tradeoffs | Se dan por sabidos y se aplican. Cuando digo "esto acopla el checkout a la API de pago", asumo que la palabra "acopla" ya significa algo para ti | software-development-foundations-guide — ahí se construye ese andamiaje desde cero |
| El oficio del code review: cómo escribir el PR, cómo comentar sin fricción, cómo defender una decisión ante el equipo | Los patrones aparecen como el vocabulario que hace posible ese review. La lección 3 y el módulo 7 entero viven en esa intersección | clean-code-and-code-review-guide — el proceso, la etiqueta y la mecánica del review |
| Arquitectura a nivel sistema: microservicios, límites de servicio, capas de despliegue, colas y mensajería | Nada. Aquí los patrones son de código: viven dentro de un proceso, entre clases y funciones | La guía de arquitectura y diseño de sistemas |
| Un lenguaje o framework específico | Python como vehículo legible, nada más. Se dice explícitamente cuándo un lenguaje vuelve innecesario un patrón | Las guías del lenguaje o framework que uses |
| El catálogo GoF completo, los 23 | Los ocho que aparecen de verdad, con profundidad. El resto se menciona como cultura general en la lección 6 | El libro original, si algún día quieres el diccionario completo |
La regla mecánica para recordarlo: si algo suena a "cómo se organiza el código dentro de un programa", es esta guía. Si suena a "cómo se organiza un sistema entre programas", es la de arquitectura. Y si suena a "qué escribo en el comentario del PR", es la de clean code y review —aunque el vocabulario que uses en ese comentario te lo dé esta.
Un matiz sobre la primera fila, porque es la más importante. Esta guía construye encima de las fundaciones. Si nunca oíste hablar de acoplamiento o de responsabilidad única, no es que no vayas a poder seguirla —vas a poder—, pero varias frases te van a sonar a que les falta un piso. Ese piso está en la guía de fundaciones, y es el orden recomendado. Si ya lo tienes, aquí vas a reconocer que los patrones son, en buena medida, nombres para formas concretas de aplicar esos principios. Strategy es una manera específica de bajar el acoplamiento entre quien decide y quien ejecuta. Facade es una manera específica de subir la cohesión de una interfaz. No son un tema nuevo: son el vocabulario de un tema que ya conoces.
Errores comunes
Creer que la meta es memorizar los veintitrés patrones (conceptual). Qué pasa: alguien llega a una guía de patrones con la expectativa de salir recitando la lista completa, con sus diagramas, listo para responder "¿qué patrones conoces?" en una entrevista. Estudia los nombres, se los aprende, y en la primera base de código real no reconoce ninguno —porque en el código real nadie escribe un comentario que diga "aquí empieza el Decorator"—. Por qué pasa: la lista es lo único concreto y evaluable de un tema que, en el fondo, es criterio. Memorizar se siente como progreso. Cómo detectarlo: si puedes recitar la definición de Adapter pero no podrías señalarlo en un archivo que nunca viste, tienes la lista y no tienes la habilidad. Cómo corregirlo: invierte el orden. Parte del problema, no del nombre. Este módulo entero está diseñado para eso, y la lección 5 te da la técnica de reconocimiento sobre código sin etiquetas.
Suponer que más patrones significa mejor código (de criterio). Qué pasa: alguien aprende cinco patrones y empieza a introducirlos donde puede, con la sensación honesta de estar profesionalizando el código. Un if de dos ramas se convierte en una jerarquía de clases; una función de diez líneas se convierte en una interfaz, dos implementaciones y una fábrica. El resultado tiene más archivos, más indirección y menos gente capaz de entenderlo. Por qué pasa: los patrones se presentan casi siempre como soluciones, casi nunca con su costo. Y el costo —la indirección— no se ve en el diagrama; se siente meses después, cuando alguien intenta seguir el flujo con el dedo y no puede. Cómo detectarlo: si para entender qué pasa cuando el usuario aprieta un botón tienes que abrir cuatro archivos, hay demasiada indirección. El rincón plugins/ de Boletia es exactamente eso. Cómo corregirlo: el módulo 2 completo. Y mientras tanto, la pregunta de bolsillo: "¿cuántas implementaciones distintas existen hoy, de verdad?". Si la respuesta es una, no hace falta un patrón.
Esperar que esta guía enseñe arquitectura de sistemas (de expectativa). Qué pasa: alguien llega buscando microservicios, colas de mensajes o cómo partir un monolito, porque en el mercado la palabra "patrones" también se usa para eso ("patrones de arquitectura", "patrones de integración"). Encuentra clases de Python y se desorienta. Por qué pasa: el mismo término nombra dos niveles muy distintos. Los patrones de esta guía —los de la tradición GoF— viven dentro de un programa: entre clases, funciones y objetos. Los de arquitectura viven entre programas: entre servicios, procesos y máquinas. Cómo detectarlo: si tu pregunta involucra la red, es del otro nivel. Cómo corregirlo: consulta la tabla de fronteras. Y toma nota de algo útil: el criterio que vas a construir aquí —¿esta abstracción se gana su lugar?— es exactamente el mismo criterio que se aplica allá, con costos mucho más caros. Quien no sabe decir "no" a una interfaz innecesaria tampoco sabe decir "no" a un microservicio innecesario.
Ejercicios
Ejercicio 1 — Encuentra el "sofrito" de tu propio trabajo. Piensa en un oficio, deporte o afición que practiques y que no sea programar. Anota tres términos que usen las personas de ese ambiente y que un recién llegado no entendería. Para cada uno, escribe: (a) qué comprime esa palabra —es decir, cuántas frases haría falta para explicarla a alguien de fuera—, y (b) si alguna vez viste a alguien usarla mal, y qué confusión provocó.
Ver solución
No hay respuesta única, porque el oficio es tuyo. Lo que sí tiene una forma reconocible es el resultado.
Sobre (a): casi siempre descubrirás que un término del oficio comprime entre dos y cinco frases, y que además transmite algo más que la definición —transmite cuándo se usa—. Alguien que juega fútbol dice "presión alta" y no está describiendo una posición: está describiendo una intención, un riesgo y un momento del partido. Esa densidad es exactamente la que tiene la palabra "Strategy" para dos programadores que la conocen.
Sobre (b): este es el punto del ejercicio. Casi todo el mundo recuerda algún caso donde alguien usó un término del oficio incorrectamente y el malentendido costó más que si nunca lo hubiera usado. El otro lado escuchó la palabra, activó todo el significado asociado, y actuó sobre información equivocada. Con los patrones ocurre igual y con más frecuencia de la que se admite: decir "esto es un Factory" cuando es un Builder manda a tu compañero a resolver un problema que no tiene.
Por qué funciona: acabas de comprobar por tu cuenta las dos caras de la tesis de esta guía. El vocabulario compartido es un multiplicador de comunicación, y el vocabulario mal usado es un multiplicador de confusión. La lección 3 desarrolla las dos.
Ejercicio 2 — Ubica los rincones de Boletia en su carpeta. Sin volver a mirar el árbol de directorios, escribe de memoria en qué carpeta vive cada una de estas cosas, y una frase sobre qué problema hay ahí: (a) las cuatro reglas de precio, (b) los tres proveedores de pago, (c) la función que orquesta la compra completa, (d) el rincón sobre-diseñado.
Ver solución
(a) pricing/, con rules.py (las reglas por tipo de boleto) y calculator.py (quien las aplica). El problema: cuatro comportamientos distintos para la misma pregunta —"¿cuánto cuesta este boleto?"— que hoy se resuelven con condicionales repartidos, porque Ticket.kind es un texto libre.
(b) payments/, con provider.py como forma común y un archivo por proveedor. El problema: las tres APIs externas son incompatibles entre sí —una recibe centavos como entero, otra un float, la tercera no cobra sino que genera una referencia— y hoy el checkout conoce esas diferencias por dentro.
(c) checkout/checkout.py. El problema: son unas trescientas líneas que orquestan precio, cobro, asientos y notificación, y crecen cada vez que se agrega un proveedor o un tipo de boleto. Es el corazón del sistema y el lugar donde nadie quiere equivocarse.
(d) plugins/, con registry.py, base.py y una sola implementación en impls/default_seating.py. El problema: hay un mecanismo completo de extensión —registro, interfaz abstracta, descubrimiento dinámico— para algo que nunca tuvo más de una implementación. Entender el mapa de asientos exige leer tres archivos en vez de uno.
Por qué funciona: memorizar el árbol no es el objetivo; el objetivo es que asocies cada carpeta con el tipo de problema que vive ahí. Esa asociación es la que va a hacer que en el módulo 3, cuando aparezca la palabra Strategy, ya tengas un lugar concreto donde probarla.
Ejercicio 3 — Clasifica cinco preguntas según la guía que las responde. Para cada pregunta, decide si la responde esta guía, software-development-foundations-guide, clean-code-and-code-review-guide o la guía de arquitectura de sistemas. Justifica en una línea. (a) "¿Qué significa que dos módulos estén acoplados?" (b) "¿Cómo le digo a mi compañero que su función hace demasiadas cosas, sin que se lo tome mal?" (c) "¿Cuándo conviene partir este servicio en dos y comunicarlos por una cola?" (d) "¿Cómo se llama la estructura donde un objeto envuelve a otro y le agrega comportamiento?" (e) "¿Vale la pena introducir una interfaz aquí, si hoy solo hay una implementación?"
Ver solución
(a) software-development-foundations-guide. Es un concepto base. Aquí lo usamos todo el tiempo, pero damos por sabido qué significa.
(b) clean-code-and-code-review-guide. La pregunta es sobre el oficio de la revisión: cómo se comunica una observación sin generar fricción. Ahora bien, el vocabulario que hace corto y preciso ese comentario —"esto es un God object", "aquí hay feature envy"— te lo da el módulo 7 de esta guía. Las dos se tocan: aquella enseña la conversación, esta enseña las palabras.
(c) La guía de arquitectura de sistemas. Involucra la red, los procesos y el despliegue. Está fuera del alcance de esta.
(d) Esta guía, módulo 5: es un Decorator. Es exactamente el tipo de pregunta de vocabulario que estamos aquí para responder.
(e) Esta guía, y es su pregunta central. Módulo 2 completo, con la regla de tres y el anti-patrón del plugin para una sola implementación. Nota que la pregunta no es "¿cómo se hace una interfaz?" —eso es sintaxis— sino "¿vale la pena?" —eso es criterio—.
Por qué funciona: saber a qué guía le toca cada pregunta te ahorra frustración y, más importante, te enseña a ver el ecosistema como un conjunto con divisiones deliberadas en vez de como cursos sueltos que se solapan.
Resumen y siguiente paso
En esta lección viste que un patrón, antes que cualquier otra cosa, es un nombre: el mismo tipo de nombre que la cocina le puso al sofrito o la medicina a la fractura por estrés. Viste con un caso concreto que el valor de ese nombre no está en que te haga ver mejor, sino en que te permite transmitir en treinta segundos lo que sin él toma cuatro minutos —y que un nombre mal usado hace más daño que ninguno—.
Conociste Boletia, la plataforma de venta de boletos que nos va a acompañar los ocho módulos: sus modelos (Event, Ticket, Order, Customer), su organización en carpetas, el recorrido que hace una compra, y sus cinco rincones —cuatro donde un patrón puede ganarse su lugar (pricing, payments, notifications, reports) y uno donde claramente no se lo ganó (plugins/)—. Recibiste el mapa de los ocho módulos, con el módulo 2 puesto a propósito antes de cualquier patrón concreto. Y viste la frontera con las guías hermanas: los conceptos base se dan por sabidos, el proceso del review es de al lado, y la arquitectura de sistemas es otro nivel.
Antes de avanzar deberías poder: explicar en una frase qué promete esta guía y qué no; describir qué es Boletia y nombrar sus cuatro ejes de variación; señalar cuál de sus rincones sobra y por qué; y decir qué diferencia esta guía de sus dos vecinas más cercanas.
Lo que todavía no tenemos es la definición precisa. "Un patrón es un nombre" es un buen punto de partida y una verdad a medias: un patrón tiene tres partes, y la que casi nadie estudia es justamente la que da criterio. La lección 2 las desarma una por una, y te va a dejar una forma de leer cualquier patrón —incluidos los que esta guía no cubre— que sirve para el resto de tu carrera.
Recursos
- Design Patterns: Elements of Reusable Object-Oriented Software (Gamma, Helm, Johnson, Vlissides) — el libro original de 1994, el que le puso nombre al catálogo. No es una lectura para principiantes ni hace falta leerlo entero; conviene conocerlo como fuente.
- Refactoring Guru — Design Patterns — la referencia visual más clara que existe hoy, con ejemplos en varios lenguajes. Útil como diccionario de consulta, no como plan de estudio.
- The Grug Brained Developer — un ensayo humorístico y sorprendentemente profundo sobre la complejidad como el enemigo real. Es, en el fondo, el módulo 2 de esta guía contado como comedia.
- A Timeless Way of Building (Christopher Alexander) — el libro de arquitectura de edificios del que salió la idea de "patrón". La lección 4 cuenta esa historia.