Inyección de dependencia

En la programación orientada a objetos, un patrón de diseño que regula las dependencias de un objeto en tiempo de ejecución se conoce como inyección de dependencias ( DI , Inglés dependencia 'dependencia' y la inyección 'inyección', alemán  dependencia de la inyección o la introducción de dependencias ) Otro objetivo, este La dependencia se almacena en una ubicación central, no la genera el objeto inicializado en sí.

Significado de la palabra

El término Inyección de dependencia fue introducido en 2004 por el desarrollador de software Martin Fowler para aclarar el entonces término Inversión de control : “ Inversión de control es un término demasiado genérico y, por lo tanto, la gente lo encuentra confuso. Como resultado de una gran discusión con varios defensores de la [Inversión de control], nos decidimos por el nombre Inyección de dependencia. ”( Martin Fowler : martinfowler.com)

antecedentes

Con la inyección de dependencia es posible, de acuerdo con el principio de responsabilidad única  , transferir la responsabilidad de la construcción de la red de dependencia entre los objetos de un programa de las clases individuales a un componente central .

En un sistema convencional de programación orientada a objetos, por otro lado, cada objeto es responsable de administrar sus dependencias, es decir, los objetos y recursos necesarios. Para hacer esto, cada objeto debe tener algún conocimiento de su entorno que normalmente no necesitaría para llevar a cabo su tarea real.

La inyección de dependencia transfiere la responsabilidad de crear y vincular objetos a un componente independiente, como un marco configurable externamente . Esto hace que el código del objeto sea más independiente de su entorno. Esto puede evitar dependencias de clases específicas al compilar y, en particular, facilita la creación de pruebas unitarias .

ventajas y desventajas

ventajas

  • El cliente tiene la flexibilidad de ser configurable. Solo se fija el comportamiento del cliente. El cliente puede reaccionar a cualquier cosa que admita la interfaz intrínseca esperada por el cliente.
  • Los detalles de configuración de un sistema se pueden mover a archivos de configuración para que el sistema se pueda reconfigurar sin volver a compilar. Se pueden escribir configuraciones separadas para diferentes situaciones que requieren diferentes implementaciones de componentes. Esto incluye, pero no se limita a, pruebas.
  • Debido a que no se requiere ningún cambio en el comportamiento del código, se puede usar como refactorización en código heredado. El resultado son clientes que son más independientes y más fáciles de probar de forma aislada mediante el uso de apéndices u objetos ficticios que simulan otros objetos que no se están probando. Esta simple verificación es a menudo el primer beneficio que se observa al utilizar la inyección de dependencia.
  • El cliente puede eliminar todo el conocimiento de una implementación específica que necesite utilizar. Esto ayuda a aislar al cliente de los efectos de los cambios y errores de diseño. Promueve la reutilización, la capacidad de prueba y la capacidad de mantenimiento.
  • Reducción del código repetitivo en los objetos de la aplicación, ya que todo el trabajo de inicialización o configuración de dependencias lo realiza un componente proveedor.
  • Desarrollo simultáneo o independiente. Dos desarrolladores pueden desarrollar clases de forma independiente que se utilicen entre sí, mientras que todo lo que necesitan saber es la interfaz a través de la cual se comunican las clases . Los complementos suelen ser desarrollados por terceros que ni siquiera hablan con los desarrolladores que crearon el producto que utiliza los complementos.
  • Se reduce el acoplamiento entre una clase y su dependencia.

desventaja

  • Se crean clientes cuyos detalles de configuración deben ser proporcionados por el código de diseño. Esto puede ser una molestia cuando existen configuraciones predeterminadas obvias disponibles.
  • La lectura de códigos puede resultar difícil porque separa el comportamiento de la construcción. Esto significa que los desarrolladores deben consultar otros archivos para realizar un seguimiento del rendimiento de un sistema.
  • Los marcos de inyección de dependencia se implementan con reflexión o programación dinámica . Esto puede dificultar el uso de la automatización IDE , p. Ej. B. Buscar referencias, ver jerarquía de llamadas y refactorizaciones seguras . El uso de la reflexión también puede afectar el desempeño del programa.
  • Por lo general, se requiere más trabajo de desarrollo inicial porque no puede predecir cuándo y dónde se necesitará, sino más bien preguntar si se inyectará y luego asegurarse de que se haya inyectado.
  • Se necesita un esfuerzo para salir de las clases y entrar en los vínculos entre las clases que pueden no siempre ser deseables o fáciles de mantener.
  • Se puede promover la dependencia de un marco de inyección de dependencia.

estructura

Image
Un ejemplo de un diagrama de clases y un diagrama de secuencia de UML para el patrón de diseño de inyección de dependencia .

En el diagrama de clases de UML , la clase de cliente, para la que se requieren objetos ServiceA y ServiceB , no instancia directamente las clases ServiceA1 y ServiceB1 . En cambio, una clase Injector crea los objetos y los inyecta en el cliente , haciendo que el cliente sea independiente de cómo se crean los objetos.

Los UML diagrama de secuencia muestra las interacciones de tiempo de ejecución: El inyector - objeto crea el ServiceA1 y ServiceB1 objetos . A continuación, el inyector crea el objeto cliente e inyecta los objetos ServiceA1 y ServiceB1 .

implementación

Martin Fowler describe tres formas diferentes de establecer las referencias requeridas, que asocia con el término Inyección de dependencia: Inyección de constructor , Inyección de interfaz e Inyección de setter (sección Formas de inyección de dependencia en). Todos los procedimientos descritos por él utilizan llamadas a métodos en los que las dependencias a establecer no son valores de retorno sino parámetros .

Inyección de constructor

Las dependencias de otras clases están disponibles a través de constructores.

class Abhängiges {
  private Abhängigkeit abhängigkeit;

  //Konstruktor
  public Abhängiges(final Abhängigkeit abhängigkeit) {
    this.abhängigkeit = abhängigkeit;
  }
}

class Injizierer {
  void methode() {
    final Abhängigkeit abhängigkeit = ... ;
    final Abhängiges abhängiges = new Abhängiges(abhängigkeit);
  }
}

Inyección de interfaz

El módulo de la clase de inyección define una interfaz que deben implementar las clases dependientes para que las dependencias estén disponibles en tiempo de ejecución.

interface IInjizierbar {
  void injiziere(final Abhängigkeit abhängigkeit);
}

class Abhängiges implements IInjizierbar {
  private final Abhängigkeit abhängigkeit;

  public void injiziere(final Abhängigkeit abhängigkeit) {
    this.abhängigkeit = abhängigkeit;
  }
}

class Injizierer {
  void methode() {
    final Abhängigkeit abhängigkeit = ... ;
    final IInjizierbar injizierbares = ... ;
    injizierbares.injiziere(abhängigkeit);
  }
}

Inyección de setter

La clase dependiente proporciona métodos que se utilizan para proporcionar las dependencias.

class Abhängiges {
  private Abhängigkeit abhängigkeit;

  public void setAbhängigkeit(final Abhängigkeit abhängigkeit) {
    this.abhängigkeit = abhängigkeit;
  }
}

class Injizierer {
  void methode() {
    final Abhängiges abhängiges = ... ;
    final Abhängigkeit abhängigkeit = ... ;
    abhängiges.setAbhängigkeit(abhängigkeit);
  }
}

Otras opciones de implementación

También es posible implementar la inyección de dependencia de otras formas, como se usa en algunos marcos. Por ejemplo, dependiendo de las posibilidades del lenguaje de programación, las dependencias se pueden establecer por reflexión o estableciendo la referencia a él directamente en la memoria, incluso sin llamadas a métodos.

Hay varios marcos para varios lenguajes de programación y plataformas de implementación que brindan soluciones listas para usar. Estos implementan el patrón con, en algunos casos, una funcionalidad extensa y avanzada, como leer la configuración de los archivos y verificar su corrección formal. Consulte la lista de marcos de inyección de dependencia .

Dependiendo del marco DI utilizado, puede tener la desventaja de que la lógica del programa debe subcontratarse a archivos de configuración, lo que puede reducir la claridad y dificultar el mantenimiento: los desarrolladores ahora deben tener en cuenta la configuración para comprender la código, que también es utilizado por algunas herramientas de análisis de código (por ejemplo, búsqueda de dependencias o refactorización respaldada por IDE ).

Esta desventaja se puede evitar implementando la inyección de dependencia, similar al patrón de diseño Abstract Factory, sin el uso de un marco como parte del programa en sí. Este tipo de implementación se denomina "Inyección de dependencia de bricolaje" o "DIY-DI" para abreviar.

Evidencia individual

  1. Inyección de dependencias en ASP.NET Core , Microsoft Docs
  2. ^ A b Martin Fowler: Inversión de contenedores de control y el patrón de inyección de dependencia. 23 de enero de 2004 (inglés) Consultado el 16 de mayo de 2013.
  3. Cómo funciona la inyección de dependencia (DI) en Spring Java Application Development. DZone
  4. Ben Yu: Tipos de inyección de dependencia. ( Recuerdo de la original, del 18 de agosto, 2013, en el Archivo de Internet ) Información: El archivo de enlace se inserta de forma automática y sin embargo no ha sido comprobado. Verifique el enlace original y de archivo de acuerdo con las instrucciones y luego elimine este aviso. (Inglés) consultado el 16 de mayo de 2013. @ 1@ 2Plantilla: Webachiv / IABot / yan.codehaus.org
  5. Chad Parry: DIY-DI (PDF) 9 de marzo de 2010. Consultado el 29 de junio de 2014.