Principio de inversión de la dependencia

Buenas prácticas,Desarrollo,Sin categoría

Dependency Inversion – Solid V

17 Abr , 2020  

Dependency Inversion, dependiendo de abstracciones, no de implementaciones

El último de los principios básicos de programación orientada a objetos nos insta a desacoplar módulos de software, a través de las siguientes directrices:

  • Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Ambos deberían depender de abstracciones.
  • Las abrastracciones no deberían depender de implementaciones concretas. Son las implementaciones las que deben depender de abstracciones.

La idea detrás de este principio es aislar nuestras clases detrás de un límite (las abstracciones) para que, en caso de que las implementaciones concretas que están detrás sufran modificaciones nuestra clase siga funcionando correctamente. Esto es algo que suena muy bonito pero que quizá no sea tan sencillo de entender. ¿Qué tal si proponemos un ejemplo?

Un robot periodista como ejemplo

Vamos a utilizar como ejemplo un robot periodista que se encarga de difundir noticias. El código sería el siguiente:

class NewsRobot
  def broadcast(news)
    FantasicBlog.new.print(news)
  end
end

class FantasicBlog
  def post(news)
    puts news
  end
end

robot_emilio = NewsRobot.new
robot_emilio.broadcast("New great article fom codigojose.com!")

Teniendo este código como referencia, nuestro robot funcionará perfectamente y difundirá las noticias en nuestro blog sin ningún problema, pero…

¿Y si mañana quisiéramos publicar las noticias en otros medios, ocmo por ejemplo Twitter, periódicos, otros blog? Nos veríamos obligados a modificar nuestra clase NewsRobot (que vendría a ser la implementación de alto nivel) porque depende directamente y de forma exclusiva de FantasticBlog. ¿Cómo podemos solucionar este problema? Utilizando la inyección de dependencias.

Implementando inyección de dependencias en nuestro robot

class NewsRobot
  def broadcast(news, platform = FantasticBlog)
    platform.new.post(news)
  end
end

Si observamos el nuevo bloque de código veremos que la modificación realizada es la injección de la dependencia platform. Esta abstracción nos permite poder emitir nuestras notificas en diferentes medios sin que nuestra clase NewsRobot tenga que verse afectada, por lo que podríamos hacer lo siguiente:

class NewsRobot
  def broadcast(news, platform = FantasticBlog)
    platform.new.post(news)
  end
end

class FantasicBlog
  def post(news)
    puts news
  end
end

class AnotherBlog
  def post(news)
    puts news
  end
end

class Twitter
  def post(news)
    tweet news
  end
end

robot_emilio = NewsRobot.new
robot_emilio.broadcast("New great article fom codigojose.com!") # Utilizará la plataforma por defecto FantasticBlog
robot_emilio.broadcast("New great article fom codigojose.com!", AnotherBlog)
robot_emilio.broadcast("New great article fom codigojose.com!", Twitter)

Como vemos, hemos conseguido difundir noticias en varios medios sin tener que realizar modificaciones sobre nuestra clase NewsRobot debido a que ésta ya no depende de ninguna implementación externa. Esta implementación se vuelve mucho más flexible, robusta y es mucho más sencillo realizar pruebas sobre la misma. Si ahora quisiéramos realizar una serie de pruebas unitarias sobre nuestro NewsRobot solo tendríamos que hacer un Mock de cualquier plataforma para comprobar el correcto funcionamiento.

Más información

Visita el resto de la serie de artículos

, ,


One Response

Deja un comentario

A %d blogueros les gusta esto: