Patrones de Diseño y Principios SOLID

1

Patrones de Diseño y Principios SOLID en Python para Procesadores de Pago

Principios SOLID

2

Principio de Responsabilidad Única en Desarrollo de Software

3

Procesador de Pagos con Principios SOLID y Stripe

4

Aplicación del Principio de Responsabilidad Única en Procesador de Pagos

5

Principio Abierto-Cerrado en Desarrollo de Software

6

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

7

Principio de Sustitución de Liskov en Desarrollo de Software

8

Aplicación del Principio de Sustitución de Liskov en Python

9

Principio de Segregación de Interfaces en Software

10

Implementación del Principio de Segregación de Interfaces en Procesadores de Pago

11

Principio de Inversión de Dependencias en Software

12

Aplicación del Principio de Inversión de Dependencias en Python

Reestructuración del proyecto

13

Reestructuración de Código con Módulos en Python y Principios SOLID

Patrones de Diseño

14

Introducción a los Patrones de Diseño de Software

15

Patrón Strategy en Diseño de Software con Python

16

Implementación del Strategy Pattern en Procesador de Pagos en Python

17

Patrón Factory Pattern en Python: Creación de Objetos Dinámicos

18

Patrón Factory en Procesadores de Pago en Python

19

Patrón Decorador: Añadir Responsabilidades Dinámicas a Objetos

20

Aplicación del Patrón Decorador en Servicios de Pago

21

Patrón de Diseño Builder: Construcción de Objetos Complejos

22

Builder Pattern para Servicio de Pagos en Python

23

Patrón Observer: Gestión de Eventos y Notificaciones Automáticas

24

Patrón Observer en Sistemas de Pago: Implementación y Notificaciones

25

Patrón Chain of Responsibility en Validación de Pagos

26

Implementación del patrón Chain of Responsibility en validaciones de pago

27

Principios SOLID y Patrones de Diseño en Procesadores de Pago

No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Implementación del patrón Chain of Responsibility en validaciones de pago

26/27
Recursos

¿Cómo aplicar el patrón Chain of Responsibility en un servicio de pagos?

El patrón Chain of Responsibility es una herramienta poderosa que permite crear cadenas de validaciones de manera flexible y estructurada. En esta guía, exploraremos cómo aplicar este patrón a un servicio de procesamiento de pagos, modificando su arquitectura para utilizar una cadena de responsabilidades que valide tanto el cliente como los datos de pago.

¿Cómo encapsular los datos necesarios para las validaciones?

Para comenzar, es necesario encapsular los datos del cliente y del pago en una clase que llamaremos Request. Utilizando la librería Pydantic con BaseModel, podemos crear esta estructura de datos fácilmente.

from pydantic import BaseModel
from payment_data import PaymentData
from customer import CustomerData

class Request(BaseModel):
    customerData: CustomerData
    paymentData: PaymentData

¿Cómo definir una clase abstracta para la cadena de validaciones?

El siguiente paso es definir una clase abstracta que dictará la forma que deberán tomar las validaciones dentro de la cadena. Utilizaremos el módulo ABC para crear una clase abstracta que denominaremos ChainHandler.

from abc import ABC, abstractmethod
from typing import Self
from dataclasses import dataclass

@dataclass
class ChainHandler(ABC):
    nextHandler: Self = None

    def setNext(self, handler: Self) -> Self:
        self.nextHandler = handler
        return handler

    @abstractmethod
    def handle(self, request: Request):
        pass

¿Cómo implementar la validación de clientes en la cadena?

Para integrar la validación de clientes, crearemos una clase CustomerHandler que extienda ChainHandler y utliza un validador previamente definido.

from validations import CustomerValidator

class CustomerHandler(ChainHandler):
    def handle(self, request: Request):
        validator = CustomerValidator()
        
        try:
            valid = validator.validate(request.customerData)
            if self.nextHandler:
                self.nextHandler.handle(request)
        except Exception as e:
            print("Error:", e)
            raise e

¿Cómo modificar el servicio para usar la cadena de validaciones?

Una vez que tengamos los Handlers, debemos modificar el servicio de pagos para utilizar la cadena de responsabilidades y no depender de válidus individuales.

from commons import Request

def some_service_method(customer_data, payment_data):
    try:
        request = Request(customerData=customer_data, paymentData=payment_data)
        validator.handle(request)
    except Exception as e:
        print("Error en las validaciones")
        raise e

¿Cómo ajustar el builder para construir la cadena de validaciones?

Para integrar el nuevo sistema de validaciones dentro del builder, añadiremos un método que configure la cadena de validación. Nos aseguramos de que el builder retorne el tipo correcto y se encadene correctamente.

from customer_handler import CustomerHandler
from typing import Optional

class PaymentServiceBuilder:
    validator: Optional[ChainHandler] = None

    def setChainOfValidations(self) -> Self:
        customer_handler = CustomerHandler()
        self.validator = customer_handler
        return self

    def build(self):
        # Lógica adicional de construcción
        ...

¿Cómo integrar la configuración de la cadena en la aplicación principal?

En el método principal donde se configura el servicio de pagos, eliminamos los antiguos métodos de configuración de validadores y añadimos el nuevo método para definir la cadena de validaciones.

builder = PaymentServiceBuilder()
builder.setChainOfValidations()

Este enfoque no solo mejora la organización del código, sino que también facilita la extensión de comportamiento al permitir añadir fácilmente más validadores a la cadena. Animamos a los estudiantes a seguir explorando y expandiendo esta implementación según sus necesidades específicas. ¡Continúen aprendiendo!

Aportes 2

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

El \*\*Patrón Chain of Responsibility\*\* es ideal para implementar un flujo flexible de validaciones donde cada paso puede aceptar, rechazar o delegar una solicitud al siguiente manejador en la cadena. Supongamos que estamos construyendo un sistema para validar formularios de usuario con múltiples pasos de validación, como comprobar si los datos están completos, si el email tiene un formato válido y si la contraseña cumple los criterios de seguridad. \### Paso 1: Clase Base para los Manejadores La clase base define una estructura común para todos los pasos de validación. ```pythonfrom abc import ABC, abstractmethod class Validador(ABC):    def \_\_init\_\_(self):        self.siguiente = None     def establecer\_siguiente(self, validador):        """Establece el siguiente validador en la cadena."""        self.siguiente = validador        return validador     @abstractmethod    def manejar(self, datos):        """Intenta validar los datos o pasa al siguiente validador."""        pass``` \### Paso 2: Validadores Concretos Cada validador implementa su propia lógica de validación. ```pythonclass ValidadorDatosCompletos(Validador):    def manejar(self, datos):        if not datos.get("email") or not datos.get("password"):            return "Error: Datos incompletos."        elif self.siguiente:            return self.siguiente.manejar(datos)        return "Validación completada." class ValidadorFormatoEmail(Validador):    def manejar(self, datos):        if "@" not in datos.get("email", ""):            return "Error: Formato de email inválido."        elif self.siguiente:            return self.siguiente.manejar(datos)        return "Validación completada." class ValidadorSeguridadPassword(Validador):    def manejar(self, datos):        password = datos.get("password", "")        if len(password) < 8 or not any(char.isdigit() for char in password):            return "Error: Contraseña no cumple los criterios de seguridad."        elif self.siguiente:            return self.siguiente.manejar(datos)        return "Validación completada."``` \### Paso 3: Configuración de la Cadena de Validación Conectamos los validadores en un flujo secuencial. ```python# Crear los validadoresvalidador\_datos\_completos = ValidadorDatosCompletos()validador\_formato\_email = ValidadorFormatoEmail()validador\_seguridad\_password = ValidadorSeguridadPassword() \# Configurar la cadenavalidador\_datos\_completos.establecer\_siguiente(validador\_formato\_email).establecer\_siguiente(validador\_seguridad\_password)``` \### Paso 4: Probar el Sistema de Validación Validamos diferentes conjuntos de datos usando la cadena configurada. ```python# Datos de pruebacasos = \[    {"email": "", "password": ""},  # Datos incompletos    {"email": "usuario", "password": "12345678"},  # Formato de email inválido    {"email": "[email protected]", "password": "short"},  # Contraseña insegura    {"email": "[email protected]", "password": "secure123"}  # Datos válidos] \# Probar cada casofor i, caso in enumerate(casos, start=1):    print(f"Caso {i}: {caso}")    resultado = validador\_datos\_completos.manejar(caso)    print(f"Resultado: {resultado}\n")``` \### Salida Esperada ```Caso 1: {'email': '', 'password': ''}Resultado: Error: Datos incompletos. Caso 2: {'email': 'usuario', 'password': '12345678'}Resultado: Error: Formato de email inválido. Caso 3: {'email': '[email protected]', 'password': 'short'}Resultado: Error: Contraseña no cumple los criterios de seguridad. Caso 4: {'email': '[email protected]', 'password': 'secure123'}Resultado: Validación completada.``` \### Ventajas del Patrón Chain of Responsibility para Validaciones 1\. \*\*Modularidad\*\*: Cada validador tiene una única responsabilidad, facilitando la lectura y el mantenimiento.2. \*\*Flexibilidad\*\*: Es fácil agregar o quitar validadores sin afectar el sistema general.3. \*\*Reutilización\*\*: Los validadores pueden ser usados en otras cadenas de validación. \### Casos de Uso Reales \- Validación de formularios de usuario.- Procesamiento de reglas de negocio en sistemas complejos.- Flujos de autorización en aplicaciones. \### Conclusión El \*\*Patrón Chain of Responsibility\*\* es una solución elegante para implementar flujos de validación escalables y flexibles. En este ejemplo, los datos pasan por una serie de validadores, cada uno con la posibilidad de manejar la solicitud o delegarla al siguiente en la cadena. Este enfoque mejora la modularidad y el mantenimiento del código.
Hola, esta fue mi solución al reto: ```python from chain_handler import ChainHandler from payment import PaymentDataValidator from commons import Request class PaymentHandler(ChainHandler): def handle(self, request:Request): validator = PaymentDataValidator() #tomar la decisión de pasar al siguiente eslabón o no try: valid = validator.validate(request.payment_data) # si no levanta una excepción, pasa al siguiente eslabón if self._next_handler: # solo si el siguiente eslabón existe: self._next_handler.handle(request) except Exception as e: print(e) # payment_validator ya levanta las excepciones. raise e `````` Y así lo implementé el **builder.py:** ```python def set_payment_validation(self) -> Self: customer = CustomerHandler() payment = PaymentDataValidator() handle = ChainHandler() handle.handle(customer) handle.set_next(payment) self.validators = handle return self `````` @camilocsoto