Implementación del Principio Abierto-Cerrado en Procesadores de Pago y Notificadores

Clase 6 de 27Curso de Patrones de Diseño y SOLID en Python

Resumen

El principio de abierto-cerrado promueve la creación de código que permita extender funcionalidades sin modificar el comportamiento original. A continuación, veremos cómo se puede aplicar este principio en el contexto de un procesador de pagos que debe añadir nuevas pasarelas sin cambiar el código existente.

¿Cómo se aplica el principio abierto-cerrado en un procesador de pagos?

La clave para implementar el principio abierto-cerrado en un sistema de pagos es diseñar el código de manera que pueda admitir nuevas pasarelas sin modificar la estructura existente. Esto se logra utilizando clases abstractas o interfaces que actúan como intermediarios. Así, los procesadores de pagos específicos, como Stripe, pueden heredar de estas clases abstractas y añadir su propia lógica sin afectar el código original.

¿Qué cambios se hicieron para implementar una nueva pasarela?

Para incorporar una nueva pasarela de pagos en este caso:

  • Se creó una nueva carpeta con ejemplos de antes y después de aplicar el principio abierto-cerrado.
  • Los datos del cliente y el pago se refactorizaron utilizando Pydantic, que es la librería más popular en Python para validaciones de datos.
  • Se introdujeron modelos de datos tipados para CustomerData y PaymentData, con campos claros como montos (enteros) y fuentes de pago (cadenas de texto).

¿Cómo se manejan los datos con Pydantic?

Pydantic permite definir modelos de datos que facilitan la validación y tipado. Por ejemplo, el modelo CustomerData contiene atributos como name (nombre del cliente) y contact_info (información de contacto), que incluye campos opcionales como teléfono o correo electrónico. Esto hace que la manipulación de datos sea más clara y segura.

¿Cómo se crean nuevas pasarelas de pagos usando clases abstractas?

Primero, se define una clase abstracta que representará un procesador de pagos. Esta clase no contiene lógica interna, sino que se utiliza para definir la firma del método principal, processTransaction. Los procesadores de pagos como Stripe implementan esta clase abstracta, heredando su forma y añadiendo la lógica específica para procesar las transacciones.

  • Se define una clase abstracta PaymentProcessor que incluye el método processTransaction.
  • Stripe, por ejemplo, hereda de esta clase abstracta para implementar su propia lógica de procesamiento.
  • El servicio de pagos ya no depende de la implementación concreta de Stripe, sino que interactúa con la clase abstracta, lo que facilita añadir nuevas pasarelas sin tocar el código base.

¿Cómo se manejan las notificaciones de confirmación?

Se siguió una estrategia similar para las notificaciones. Al igual que con los procesadores de pagos, se creó una clase abstracta Notifier que define la firma del método SendConfirmation. Esto permite crear diferentes implementaciones, como un notificador por correo electrónico o un notificador por SMS, sin afectar la estructura del código original.

  • Se introdujo un EmailNotifier y un SMSNotifier, ambos heredando de la clase abstracta Notifier.
  • El código decide dinámicamente qué tipo de notificación enviar según los datos del cliente, ya sea por correo o por SMS.

¿Cómo se extendió el código sin modificar su estructura original?

Al final, el servicio de pagos se extendió para que permitiera enviar notificaciones vía SMS sin cambiar su base de código. Esto se logró creando una nueva clase SMSNotifier que también hereda de Notifier. El código puede cambiar entre el envío de correos o mensajes de texto con solo ajustar la implementación del servicio, cumpliendo así con el principio abierto-cerrado.