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
Viendo ahora - 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
18:54 min - 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
Cómo aplicar SRP en un procesador de pagos con Stripe




Todos los cursos GRATIS
Resumen
Aplicar el principio de responsabilidad única (SRP) en Python con Stripe no solo ordena el código: también hace el flujo de cobro más claro, testeable y mantenible. Aquí verás cómo se pasó de un PaymentProcessor monolítico a un diseño con validadores, servicio orquestador y componentes dedicados para notificación y registro, usando data class, type hints y manejo de excepciones.
¿Qué problema resuelve el principio de responsabilidad única en este procesador de pagos?
Separar responsabilidades evita que una clase haga de todo: validar, cobrar, notificar y loguear. El punto de partida fue un procesador rudimentario que incumplía SOLID. Se reorganizó con clases específicas: CustomerValidation, PaymentDataValidator, Notifier, TransactionLogger y un StripePaymentProcessor, coordinadas por PaymentService.
- Importaciones y entorno al inicio del archivo: organización estándar de la industria.
- PaymentProcessor como data class: instanciación simple sin definir init manual.
- processTransaction con type hints: retorna una instancia de Stripe Charge.
- Validaciones con excepciones:
ValueErroren lugar de objetos vacíos. - Corrección de flujo: si no hay email ni teléfono, igual se devuelve el charge exitoso.
¿Cómo estaba el código antes y qué ajustes iniciales se hicieron?
- Importaciones y variables de entorno (por ejemplo,
stripe_api_key) movidas al inicio. PaymentProcessorconvertido en data class para simplificar instanciación.- Firma de
processTransactionconservada, ahora con retorno tipado a Charge. - Validaciones reemplazadas por
raise ValueErrorcon mensajes claros. - Bug corregido: ausencia de email y teléfono ya no corta el flujo; se devuelve el cargo igualmente.
¿Cuáles responsabilidades se identifican y por qué separarlas?
- Validación de customer: nombre y contact info correctos.
- Validación de pago: existencia de
sourceenpayment_data. - Procesamiento del pago: interacción con la librería de Stripe.
- Notificación: por email o SMS, comportamiento moqueado.
- Registro en logs: persistir contexto del cargo.
Separarlas permite que cada clase cambie por razones únicas, cumpliendo SRP.
¿Qué clases nuevas encapsulan cada responsabilidad?
- CustomerValidation con
validate(customer_data). - PaymentDataValidator con
validate(payment_data). - Notifier con
sendConfirmation(customer_data)para email o teléfono. - TransactionLogger con
log(customer_data, payment_data, charge). - StripePaymentProcessor (renombrado para ser semántico) con
processTransaction(...). - PaymentService como orquestador.
Ejemplo de estructura mínima:
from dataclasses import dataclass class CustomerValidation: def validate(self, customer_data: dict) -> None: if not customer_data.get("name"): raise ValueError("missing name") if not customer_data.get("contact_info"): raise ValueError("missing contact info") class PaymentDataValidator: def validate(self, payment_data: dict) -> None: if "source" not in payment_data: raise ValueError("missing source") class Notifier: def sendConfirmation(self, customer_data: dict) -> None: if customer_data.get("email"): print("enviar email moqueado.") elif customer_data.get("phone"): print("enviar sms moqueado.") class TransactionLogger: def log(self, customer_data: dict, payment_data: dict, charge): print(f"pagó {payment_data['amount']} la persona {customer_data['name']}")
¿Cómo coordina PaymentService el flujo con validadores, processor y notificaciones?
PaymentService concentra el flujo: valida datos, procesa con StripePaymentProcessor, notifica con Notifier y registra con TransactionLogger. Devuelve el Charge de Stripe y propaga stripe_error si algo falla. Se usa try/except para manejar ValueError ya emitidos por los validadores.
@dataclass class PaymentService: customer_validator: CustomerValidation payment_validator: PaymentDataValidator stripe_payment_processor notifier: Notifier transaction_logger: TransactionLogger def processTransaction(self, customer_data: dict, payment_data: dict) -> "Charge": try: self.customer_validator.validate(customer_data) except ValueError as e: raise e try: self.payment_validator.validate(payment_data) except ValueError as e: raise e try: charge = self.stripe_payment_processor.processTransaction(customer_data, payment_data) except stripe_error as e: raise e self.notifier.sendConfirmation(customer_data) self.transaction_logger.log(customer_data, payment_data, charge) return charge
¿Qué cambio clave evita errores en las validaciones?
En lugar de if esperando booleanos, los validadores ya hacen raise ValueError. Por eso, en PaymentService se usa try/except y se re-lanza la misma excepción. Esto elimina falsos positivos de validación y simplifica el control de flujo.
try: customer_validator.validate(customer_data) except ValueError as e: raise e
¿Qué se corrige en notificaciones y retorno del cargo?
- Si no hay
emailniphone, el flujo continúa y se retorna el charge exitoso. - La notificación es moqueada: impresión por consola según disponibilidad de contacto.
- El logger persiste contexto: monto (p. ej., 500 o 700) y nombre (p. ej., John Doe).
¿Cómo se maneja un fallo de Stripe con tokens de prueba?
- Se reproducen fallos con token de riesgo como “radar block”: la tarjeta es declinada por defecto.
- El StripePaymentProcessor levanta la excepción capturada; PaymentService la propaga.
- En el código cliente, se puede envolver la llamada en try/except y reportar: “falló el procesamiento: {error}”.
try: charge = payment_service.processTransaction(customer_data, payment_data) except Exception as e: print(f"falló el procesamiento: {e}")
¿Qué habilidades y conceptos aplicas al refactor bajo SOLID?
Refactorizar con SRP exige precisión y criterio. Aquí se aplican prácticas de alto impacto para código de pagos en producción.
- SRP (principio de responsabilidad única): cada clase cambia por una razón única.
- Orquestación con PaymentService: coordina validación, cobro, notificación y logging.
- Renombramiento semántico:
StripePaymentProcessorrefleja su dominio real. - Python data class: instanciación clara, sin
__init__explícito. - Python type hints:
processTransaction -> Chargemejora legibilidad y contratos. - Manejo de excepciones:
ValueErroren validaciones; propagación destripe_error. - Mocks funcionales: envío de email/SMS como impresión controlada.
- Corrección de flujo: retorno del charge aunque no haya medios de contacto.
- Depuración con debugger y breakpoints: verificación de estados intermedios.
- Pruebas de error con tokens de Stripe: “radar block” simula tarjeta declinada.
¿Tú cómo separarías aún más las responsabilidades o qué cambios harías para reforzar SRP en este flujo de pagos? Comparte tus ideas y mejoras en los comentarios.