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:
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?
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.
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.
buenas prácticas, desarrollo, SOLID
[…] Dependency Inversion – SOLID V […]