Contenido del curso
Principios SOLID
- 2

Qué es el principio de responsabilidad única
05:58 min - 3

Procesador de pagos en Python con Stripe
11:13 min - 4

Cómo aplicar SRP en un procesador de pagos con Stripe
25:19 min - 5

Principio open-closed en Python
02:39 min - 6

Clases abstractas y principio abierto-cerrado
14:46 min - 7

Principio de Liskov en S.O.L.I.D.
03:18 min - 8

Principio de sustitución de Liskov en Python
06:38 min - 9

Principio de segregación de interfaces en SOLID
02:33 min - 10

Segregación de interfaces en procesadores de pagos
09:05 min - 11

Principio de inversión de dependencias en SOLID
04:13 min - 12

Principio de inversión de dependencias: servicio de pagos flexible
05:56 min
Reestructuración del proyecto
Patrones de Diseño
- 14

Qué son los patrones de diseño: definición y categorías
03:54 min - 15

Strategy Pattern con Python y setprocessor
01:55 min - 16

Strategy Pattern para pagos en Python
10:58 min - 17

Factory Pattern: centralizar creación de objetos
03:04 min - 18

Patrón Factory para procesar pagos con match
11:06 min - 19

Qué es el patrón Decorator
03:06 min - 20

Patrón decorador en servicios de pagos
12:57 min - 21

Builder Pattern: construcción paso a paso
01:28 min - 22

Builder Pattern aplicado a un servicio de pagos
Viendo ahora - 23

Observer Pattern en sistemas de eventos
01:48 min - 24

Observer en sistemas de pagos con Python
11:11 min - 25

Chain of Responsibility para validar pagos
02:04 min - 26

Chain of Responsibility en servicios de pagos
16:27 min - 27

Código funcional vs código mantenible en Python
03:19 min
Builder Pattern aplicado a un servicio de pagos
Resumen
Construir un servicio con muchas dependencias puede volverse caótico si intentas instanciar todo de golpe. El patrón Builder en Python resuelve ese problema separando la construcción paso a paso, y aquí verás cómo aplicarlo a un payment service real, combinándolo con el patrón Factory.
Esta guía es para ti si estás aprendiendo patrones de diseño aplicados a servicios con múltiples validadores, procesadores y notificadores, y quieres ver cómo orquestar todo sin acoplar tu código.
¿Cuándo conviene usar el patrón Builder?
El Builder brilla cuando una clase necesita muchas configuraciones o pasos previos antes de instanciarse. En el caso del payment service, hay validadores, procesadores, notificadores y logger involucrados, así que tiene sentido construirlo por partes [00:09].
¿Qué es el patrón Builder? Es un patrón creacional que separa la construcción de un objeto complejo de su representación, permitiendo crear distintas variantes con los mismos pasos.
¿Cómo se estructura la clase PaymentServiceBuilder?
El primer paso es crear un archivo Builder.py con una clase PaymentServiceBuilder que tenga los mismos atributos que la clase final, pero con una particularidad clave: todos los atributos deben ser opcionales y con valor por defecto None [00:33]. Esto permite ir llenándolos progresivamente.
La clase se marca también como data class para simplificar la definición. Después se importan los protocolos y clases que cada atributo va a recibir, eliminando los que no se usen.
¿Cómo definir los métodos set del builder?
El segundo paso es crear un método set por cada atributo. Aquí conviene separar los atributos en dos grupos según su complejidad [01:30].
Setters simples sin lógica de validación
Algunos componentes no dependen de abstracciones y se pueden instanciar directamente:
set_logger: instancia unTransactionLoggery lo asigna aself.logger.set_payment_validator: instanciaPaymentDataValidator.set_customer_validator: instanciaCustomerValidator.
Cada método recibe self, asigna el atributo y termina con return self. Ese retorno de self es lo que habilita el method chaining, es decir, encadenar llamadas como builder.set_logger().set_payment_validator() [02:14].
Setters que dependen de lógica externa
El set_payment_processor se apoya en un factory creado previamente, que decide cuál es el mejor procesador según el tipo de pago [03:05]. Recibe un PaymentData adicional y llama a PaymentProcessorFactory.create_payment_processor(payment_data).
Aquí ocurre algo interesante: estás mezclando dos patrones de diseño. El Factory decide la mejor implementación para el contexto, y el Builder orquesta la construcción dinámica del servicio completo [03:55].
El set_notifier recibe un CustomerData y elige notificador con cláusulas if:
- Si el
contact_infotiene email, usaEmailNotifier. - Si tiene número de teléfono, usa
SMSNotifiercon un gateway personalizado. - Si no tiene ninguno, lanza
raise ValueError("No se puede seleccionar clase de notificación")[05:12].
Una buena práctica que se sugiere: crear también un factory para el notificador, en lugar de resolverlo con if dentro del builder.
¿Para qué sirve el método build y cómo validar dependencias?
El tercer paso es el método build, responsable de validar que toda la información necesaria está presente antes de instanciar la clase final [06:14].
¿Qué hace el método build en el patrón Builder? Verifica que los atributos requeridos no sean
Noney devuelve la instancia final del objeto. Si falta algo, lanza una excepción clara.
La validación se hace con all() sobre una lista de los atributos obligatorios: payment_processor, notifier, customer_validator, payment_validator y logger. Si alguno es None, all() retorna False y entra a la rama de error.
Cómo notificar qué dependencia falta
En vez de fallar con un mensaje genérico, el builder construye una lista missing iterando sobre tuplas (name, value) de cada atributo requerido. Si el value es None, agrega el name a la lista. Al final lanza raise ValueError(f"Missing dependencies: {missing}") [07:46].
Esto evita que el error explote sin contexto y te dice exactamente qué setter olvidaste llamar.
Una vez validado todo, el método retorna PaymentService(...) pasándole cada atributo desde self. Si tu editor marca una advertencia porque cree que un atributo puede ser None, puedes ignorarla con seguridad: la validación previa ya garantiza que no lo es [09:08].
¿Cómo se usa el builder en el código cliente?
La instanciación queda mucho más limpia. Primero creas el builder, encadenas los setters y terminas con build():
python from builder import PaymentServiceBuilder
builder = PaymentServiceBuilder() service = (builder .set_logger() .set_payment_validator() .set_customer_validator() .set_payment_processor(payment_data) .set_notifier(customer_data) .build())
Si quitas el .build() final, lo que tienes es una instancia del builder, no del servicio. Solo al invocar build() obtienes la instancia tipada como PaymentService [10:34].
Qué pasa cuando falta una dependencia
Si omites, por ejemplo, set_payment_validator y ejecutas build(), el flujo entra a la validación, detecta que payment_validator está en None, lo agrega a missing y lanza la excepción indicando que la dependencia faltante es el payment validator [11:25]. Diagnóstico inmediato, sin adivinar.
Un reto que puedes intentar: agrega un método al builder que decore el comportamiento original del payment service usando los decorators vistos en clases anteriores. ¿Cómo lo resolverías tú? Déjalo en los comentarios.