jueves, 31 de mayo de 2018

Principio de inversión de dependencia (DIP) - Clean Architecture

El principio de inversión de dependencia o The Dependency Inversion Principle (DIP) (en inglés) establece que los sistemas más flexibles son aquellos cuyas dependencias de código son aquellas que dependen de abstracciones y no de implementaciones concretas.

Tanto en los lenguajes compilados como en los interpretados se debería hacer uso de las abstracciones de manera que se importasen sólo interfaces y clases abstractas, no se debería depender de ninguna abstracción. Esto es claramente algo imposible ya que, en algún momento, hay que importar la implementación de esa abstracción.


Abstracciones estables

Las interface abstractas son más estables que las implementaciones ya que un cambio en una interface implica un cambio en la implementación pero al revés no se cumple. Se puede cambiar una implementación pero esto no debería afectar a la interface. Por esta razón las interfaces son menos volátiles.

Los buenos arquitectos y diseñadores de software se centran en reducir la volatilidad de las interfaces. Tratan de encontrar la manera de añadir funcionalidad sin hacer cambios en las interfaces. Esto es el «Software Design 101».

La estrategia es utilizar interfaces abstractas estables en vez de implementaciones concretas que pueden cambiar fácilmente.

Hay una serie de prácticas para llevar a cabo este principio:

    • No hacer referencia a las implementaciones: hacer referencia a las interfaces abstractas. Generalmente se usan el patrón Abstract Factory para la creación de objetos.
    • No heredar de implementaciones volátiles: la herencia es un dependencia por lo que debería usarse con cuidado.
    • No sobrescribir funciones concretas: La implementación de funciones contienen dependencias a veces. Cuando se sobrescribe una función no se elimina estas dependencias si no que se heredan. Para administrar estas dependencias se debería hacer una función abstracta y crear varias implementaciones.
    • Nunca mencionar el nombre de nada concreto y volátil: esto es básicamente el principio.

Factorias

En cualquier lenguaje de programación la creación de un objeto crea un dependencia de código de la definición de ese objeto.

En la mayoría de los lenguajes orientados a objetos se debería usar el el patrón factoría abstracta o «Abstract Factory» para gestionar estas dependencias no deseadas.

El siguiente diagrama muestra cómo «Application» usa «ServiceImp» a través de la interfaz «Service». Sin embargo, «Application» debe crear una instancia de «ServiceImp» de alguna manera. Para lograr esto sin crear una dependencia de código «Application» hace una llamada al método «create» de la interfaz «ServiceFactory». Este método está implementado en la clase «ServiceFactoryImp» el cual implementa la interfaz «ServiceFactory». Esta implementación crea la instancia de «OrderImp» y la devuelve como un servicio.



Este diseño tiene un límite de arquitectura definido separando las abstracciones de sus implementaciones. Las dependencias, representadas por el sentido de las flechas, siempre van en la misma dirección, hacia el lado de la abstracción.

 «Application» utiliza las abstracciones (interfaces) que contiene todas las reglas de negocio. Las implementaciones contienen el código para las reglas de negocio.

El flujo de control pasa por «inyectar», o sea, pasar como parámetro una instancia de «ServiceFactoryImp» al constructor o a un método de «Application» el cual tenga definido en su implementación un parámetro de tipo «ServiceFactory». De esta manera «Application» opera de manera abstracta.

Implementación de componentes

Es imposible cumplir DIP ya que en algún momento hay que incluir la dependencia pero sí que se pueden reducir al mínimo estas y guardarlas separadas del resto del sistema, por ejemplo, en factorías.

Conclusión

Este principio será el más visible en la organización de la arquitectura.

No hay comentarios:

Publicar un comentario