Segregación de interfaces en procesadores de pagos
Clase 10 de 27 • Curso de Patrones de Diseño y SOLID en Python
Contenido del curso
Principios SOLID
- 2

Principio de responsabilidad única en SOLID
05:59 min - 3

Refactorizando código Python con principios SOLID
11:14 min - 4

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

Open Closed Principle: extensión sin modificación
02:39 min - 6

Cómo usar clases abstractas en Python
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

Interface Segregation: cuándo separar contratos
02:33 min - 10

Segregación de interfaces en procesadores de pagos
Viendo ahora - 11

Principio de inversión de dependencias explicado
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:05 min - 18

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

Patrón Decorator en 5 pasos para funcionalidad dinámica
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 para servicios de pagos
18:55 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

Arquitectura robusta para procesadores de pago
03:19 min
Aplicar el principio de segregación de interfaces en un procesador de pagos evita dependencias innecesarias y errores en tiempo de ejecución. Aquí verás cómo separar responsabilidades en protocolos específicos para cobros, reembolsos y recurrencias, con ejemplos prácticos usando Stripe y un procesador offline. La meta: clases que solo dependan de lo que realmente usan.
¿Cómo aplicar el principio de segregación de interfaces en un procesador de pagos?
El punto de partida es un procesador que ahora incluye dos métodos nuevos: reembolso y crear recurrencia. Además, se añadió un procesador de pagos offline que solo imprime el cobro, simulando efectivo. Al no tener pasarela, no puede reembolsar ni crear recurrencias, por lo que lanzar excepciones en esos métodos revela la violación al principio: una clase no debería depender de métodos que no puede implementar.
- Se cambia el retorno de process transaction para no depender de un charge de Stripe. Ahora se define un resultado con: estatus exitoso o fallido, monto, ID de transacción y mensaje de la pasarela.
- El procesador offline no soporta refund ni recurring: levantar excepciones lo hace evidente y guía la refactorización.
¿Qué problema revela el procesador de pagos offline?
Cuando el offline processor implementa métodos de reembolso y recurrencia que no puede cumplir, se obliga a los clientes a depender de funciones inútiles. Eso contraviene el principio de segregación de interfaces y dificulta el mantenimiento.
¿Qué protocolos separar: cobro, reembolso y recurrencia?
La solución es crear tres protocolos con un único propósito cada uno: uno para cobrar, otro para reembolsar y otro para recurrencia. Así, cada clase implementa solo lo que necesita.
from typing import Protocol, Optional
class PMProcessorProtocol(Protocol):
def process_transaction(self, amount: int) -> dict: ...
class RefundPaymentProtocol(Protocol):
def refund_payment(self, transaction_id: str) -> None: ...
class RecurringPaymentProtocol(Protocol):
def create_recurring(self, amount: int, interval: str) -> None: ...
¿Qué cambios de diseño y código se realizan para Stripe y offline?
En Stripe, se implementan los tres métodos porque la pasarela soporta cobros, reembolsos y recurrencias. El procesador offline solo implementa cobros.
- Stripe: hereda de los tres protocolos. Soporta todo el flujo.
- Offline: hereda solo de
PMProcessorProtocol. No tiene reembolso ni recurrencia.
class StripeProcessor(PMProcessorProtocol, RefundPaymentProtocol, RecurringPaymentProtocol):
def process_transaction(self, amount: int) -> dict:
# lógica real de Stripe
return {"status": "success", "amount": amount}
def refund_payment(self, transaction_id: str) -> None:
# refund real en Stripe
...
def create_recurring(self, amount: int, interval: str) -> None:
# plan/recurrencia en Stripe
...
class OfflineProcessor(PMProcessorProtocol):
def process_transaction(self, amount: int) -> dict:
print(f"Cobrando en efectivo: {amount}")
return {"status": "success", "amount": amount}
Nota: se menciona renombrar la clase base para cumplir un estándar: PM Processor Protocol. El objetivo es claridad y consistencia en nombres.
¿Cómo adaptar el servicio para refund y recurrencia opcionales?
Como los métodos de refund y recurring ya no están en el payment processor general, el service agrega dos atributos opcionales: refund_processor y recurring_processor. Se valida None antes de llamar y, de no existir, se lanza una excepción clara.
- Agregar atributos opcionales:
Optional[RefundPaymentProtocol]yOptional[RecurringPaymentProtocol]. - Validar antes de ejecutar: si es None, lanzar
Exceptioncon mensajes explícitos. - Instanciación flexible: con Stripe, un solo procesador puede cubrir los tres flujos; con offline, no se pasan refund ni recurring.
class PaymentService:
def __init__(
self,
payment_processor: PMProcessorProtocol,
refund_processor: Optional[RefundPaymentProtocol] = None,
recurring_processor: Optional[RecurringPaymentProtocol] = None,
) -> None:
self.payment_processor = payment_processor
self.refund_processor = refund_processor
self.recurring_processor = recurring_processor
def refund(self, transaction_id: str) -> None:
if not self.refund_processor:
raise Exception("this processor does not support refunds")
self.refund_processor.refund_payment(transaction_id)
def create_recurring(self, amount: int, interval: str) -> None:
if not self.recurring_processor:
raise Exception("This processor does not support recurrent")
self.recurring_processor.create_recurring(amount, interval)
Instanciación con Stripe como único procesador para todo:
stripe = StripeProcessor()
service = PaymentService(
payment_processor=stripe,
refund_processor=stripe,
recurring_processor=stripe,
)
Instanciación con offline solo para cobros en efectivo:
offline = OfflineProcessor()
service_cash = PaymentService(
payment_processor=offline,
# sin refund ni recurring para mantener la segregación
)
Palabras clave y habilidades puestas en práctica: - Principio de segregación de interfaces: evitar dependencias a métodos no usados. - Protocolos especializados: PMProcessorProtocol, RefundPaymentProtocol, RecurringPaymentProtocol. - Tipos opcionales y validación de None: robustez en el service. - Excepciones claras: mensajes orientados a capacidades del procesador. - Independencia de pasarela: retorno genérico en process transaction (estatus, monto, id, mensaje).
¿Qué otras mejoras aplicarías para reforzar la segregación de interfaces en este caso de uso de procesadores de pago? Comparte tus ideas y ejemplos en comentarios.