No tienes acceso a esta clase

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

Aplicar el Principio de Inversión de Dependencias (DIP)

12/27
Recursos

El principio de inversión de dependencias es clave para mejorar la arquitectura del código, y este ejemplo sobre el servicio de pagos lo ilustra perfectamente. En lugar de que la clase de alto nivel dependa de detalles de las clases de bajo nivel, se trabaja con abstracciones, lo que permite mayor flexibilidad al añadir nuevas funcionalidades.

¿Cumple el código con el principio de inversión de dependencias?

Sí, el código cumple con el principio desde el momento en que el servicio de pagos (clase de alto nivel) no depende directamente de los detalles de los procesadores de pagos, validadores o notificadores, sino de interfaces o protocolos. Esto significa que, si alguna de las implementaciones cambia, el servicio de alto nivel no requiere modificaciones, ya que interactúa únicamente con las abstracciones.

¿Qué detalles pueden mejorar para aplicar mejor el principio?

Aunque la implementación está alineada con el principio de inversión de dependencias, hay un detalle por mejorar: las clases de alto nivel aún instancian clases de bajo nivel dentro de sus atributos, como los validadores o el logger. Para eliminar esta dependencia, se recomienda remover esas “default factories” y en su lugar, inyectar todas las dependencias desde fuera del servicio. Esto garantizaría una mayor adherencia al principio.

¿Cómo se instancia el servicio de pagos aplicando el principio?

El código muestra claramente cómo se instancian las dependencias antes de crear el servicio de pagos. Se crea el procesador de pagos de Stripe, un notificador de email, los validadores de clientes y pagos, así como el logger. Luego, se pasa cada dependencia al PaymentService, asegurando que el servicio de alto nivel no conozca los detalles internos de las clases de bajo nivel.

  • Se instancia el procesador de Stripe y se reutiliza para recurrencias y reembolsos.
  • Si se requiere un servicio con otro procesador, como uno offline, el cambio es sencillo porque las clases están desacopladas.

¿Cómo permite la inyección de dependencias mejorar la flexibilidad del código?

La inyección de dependencias facilita la flexibilidad, ya que permite cambiar las implementaciones sin modificar el servicio principal. Si en lugar de Stripe se requiere otro procesador o un notificador distinto como SMS, el código solo necesita ajustar las instancias que se pasan al servicio, sin afectar el código principal.

Aportes 5

Preguntas 2

Ordenar por:

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

Mi solución al reto: (creo) **1 Cortar y pegar:** en la clase `StripePaymentProcessor` están las funciones que precisamente hacen devoluciones y recurrencia, por lo que solo es cortar y pegar ese código en las respectivas clases. **2 Borrar las funciones e instanciar las clases:** Luego, borras las funciones que ya no necesitan en `StripePaymentProcessor`, (así que ya estarías cumpliendo con el principio S), e instancias las clases así: ![](https://static.platzi.com/media/user_upload/image-1d6e312e-f557-4a2e-b42c-1d5b05505e42.jpg) las interfaces `PaymentProcessorProtocol, RefundPaymentProtocol, RecurringPaymentProtocol` ya solo son instancias del método de la clase de `StripePaymentProcessor`: lo que me confunde de esto último es que, la clase en cuestión (`StripePaymentProcessor`) ahora sería una clase de alto nivel porque define la lógica de negocio... o no sé, agradecería si alguien puede corregirme 😅 ¿Hay algo que entendí mal o que no es correcto? :<
El Principio de Inversión de Dependencias (DIP) establece que las clases de alto nivel no deben depender de clases de bajo nivel, sino de abstractions, como interfaces o protocolos. Los puntos básicos son: 1. **Dependencias hacia abstracciones:** Un módulo de alto nivel no debe depender de un módulo de bajo nivel. Ambos deberían depender de abstracciones. 2. **Inversión de dependencias:** Las dependencias deben ser inyectadas en lugar de ser creadas dentro de las clases, promoviendo un código más flexible y fácil de modificar. 3. **Facilitación de pruebas:** Permite que las pruebas unitarias sean más simples, ya que se pueden inyectar dependencias simuladas. Este principio mejora la mantenibilidad y escalabilidad del código.
Otro ejemplo de un codigo que aplica el DIP: ```js from abc import ABC, abstractmethod class Heroe(ABC): # Abstracción @abstractmethod def atacar(self): pass class Batman(Heroe): def atacar(self): print("Batman lanza un batarang") class Superman(Heroe): def atacar(self): print("Superman lanza su visión láser") class SuperHeroe: def __init__(self, heroe: Heroe): # Dependencia en una abstracción self.heroe = heroe def realizar_ataque(self): self.heroe.atacar() # Uso batman = Batman() superman = Superman() # Ahora puedes usar cualquier héroe que implemente la interfaz `Heroe` super_heroe1 = SuperHeroe(batman) super_heroe2 = SuperHeroe(superman) ```
Otro ejemplo sencillo de un codigo que viola el DIP: ```js class Batman: def atacar(self): print("Batman lanza un batarang") class SuperHeroe: def __init__(self): self.heroe = Batman() # Dependencia directa de una clase concreta def realizar_ataque(self): self.heroe.atacar() # Uso heroe = SuperHeroe() heroe.realizar_ataque() ```
En el código de ejemplo, las dependencias se inyectaron en la creación de la clase `PaymentService`. Las instancias de las dependencias como `StripePaymentProcessor`, `EmailNotifier`, `CustomerValidator`, `PaymentValidator` y `Logger` se pasaron como argumentos al constructor de `PaymentService`, garantizando que esta clase no dependa de la creación de las clases de bajo nivel.