Pregunta

He estado usando StructureMap recientemente y he disfrutado muchísimo la experiencia.Sin embargo, puedo ver cómo uno puede dejarse llevar fácilmente por la interconexión de todo y terminar con clases que incorporan una gran cantidad de interfaces en sus constructores.Aunque eso realmente no es un gran problema cuando se utiliza un marco de inyección de dependencia, todavía se siente que hay ciertas propiedades que realmente no necesitan ser interconectadas solo por el hecho de interconectarlas.

¿Dónde se traza la línea sobre qué interconectar versus simplemente agregar una propiedad a la clase?

¿Fue útil?

Solución

Piensa en tu diseño.DI le permite cambiar el funcionamiento de su código mediante cambios de configuración.También le permite romper las dependencias entre clases para que pueda aislar y probar objetos más fácilmente.Tienes que determinar dónde esto tiene sentido y dónde no.No hay una respuesta fácil.

Una buena regla general es que si es demasiado difícil de probar, tendrás algunos problemas con la responsabilidad única y las dependencias estáticas.Aísle el código que realiza una única función en una clase y rompa esa dependencia estática extrayendo una interfaz y utilizando un marco DI para inyectar la instancia correcta en tiempo de ejecución.Al hacer esto, resulta trivial probar las dos partes por separado.

Otros consejos

El principal problema con la inyección de dependencia es que, si bien da la apariencia de una arquitectura débilmente acoplada, en realidad no es así.

Lo que realmente estás haciendo es mover ese acoplamiento del tiempo de compilación al tiempo de ejecución, pero aún así, si la clase A necesita alguna interfaz B para funcionar, aún es necesario proporcionar una instancia de una clase que implemente la interfaz B.

La inyección de dependencia solo debe usarse para las partes de la aplicación que deben cambiarse dinámicamente sin volver a compilar el código base.

Usos que he visto útiles para un patrón de Inversión de Control:

  • Una arquitectura de complemento.Entonces, al establecer los puntos de entrada correctos, se puede definir el contrato para el servicio que se debe brindar.
  • Arquitectura similar a un flujo de trabajo.Donde puedes conectar varios componentes conectando dinámicamente la salida de un componente a la entrada de otro.
  • Aplicación por cliente.Digamos que tiene varios clientes que pagan por un conjunto de "características" de su proyecto.Al utilizar la inyección de dependencia, puede proporcionar fácilmente solo los componentes principales y algunos componentes "agregados" que brindan solo las funciones que el cliente pagó.
  • Traducción.Aunque esto generalmente no se hace con fines de traducción, puede "inyectar" archivos de diferentes idiomas según lo necesite la aplicación.Eso incluye interfaces de usuario RTL o LTR según sea necesario.

La inyección de dependencia solo debe usarse para las partes de la aplicación que deben cambiarse dinámicamente sin recompensar el código base

DI debe usarse para aislar su código de recursos externos (bases de datos, servicios web, archivos xml, arquitectura de complementos).La cantidad de tiempo que llevaría probar su lógica en el código sería casi prohibitiva para muchas empresas si está probando componentes que DEPENDEN de una base de datos.

En la mayoría de las aplicaciones, la base de datos no cambiará dinámicamente (aunque podría hacerlo), pero en términos generales, casi siempre es una buena práctica NO vincular su aplicación a un recurso externo en particular.La cantidad involucrada en el cambio de recursos debe ser baja (las clases de acceso a datos rara vez deben tener una complejidad ciclomática superior a uno en sus métodos).

¿Qué quieres decir con "simplemente agregar una propiedad a una clase"?

Mi regla general es hacer que la unidad de clase sea comprobable.Si su clase se basa en los detalles de implementación de otra clase, es necesario refactorizarla/abstraerla hasta el punto de que las clases puedan probarse de forma aislada.

EDITAR:Mencionas una gran cantidad de interfaces en el constructor.Recomendaría utilizar setters/getters en su lugar.Creo que hace que las cosas sean mucho más fáciles de mantener a largo plazo.

Lo hago sólo cuando ayuda a separar las preocupaciones.

Como tal vez entre proyectos, proporcionaría una interfaz para los implementadores en uno de mis proyectos de biblioteca y el proyecto de implementación inyectaría cualquier implementación específica que deseen.

Pero eso es todo...en todos los demás casos simplemente haría que el sistema fuera innecesariamente complejo

Incluso con todos los hechos y procesos del mundo..Cada decisión se reduce a una decisión judicial. Olvidé dónde leí eso.
Creo que es más una llamada de experiencia/tiempo de vuelo.Básicamente, si ve la dependencia como un objeto candidato que puede ser reemplazado en un futuro próximo, utilice la inyección de dependencia.Si veo 'claseA y sus dependencias' como un bloque para sustitución, entonces probablemente no usaré DI para los departamentos de A.

El mayor beneficio es que le ayudará a comprender o incluso descubrir la arquitectura de su aplicación.Podrá ver muy claramente cómo funcionan sus cadenas de dependencia y podrá realizar cambios en partes individuales sin necesidad de cambiar cosas que no están relacionadas.Terminará con una aplicación débilmente acoplada.Esto lo impulsará a lograr un mejor diseño y se sorprenderá cuando pueda seguir realizando mejoras porque su diseño lo ayudará a seguir separando y organizando el código en el futuro.También puede facilitar las pruebas unitarias porque ahora tiene una forma natural de sustituir implementaciones de interfaces particulares.

Hay algunas aplicaciones que son simplemente desechables, pero si hay alguna duda, seguiría adelante y crearía las interfaces.Después de un poco de práctica, no es una gran carga.

Otro tema con el que lucho es ¿Dónde debería utilizar la inyección de dependencia? ¿A dónde lleva su dependencia de StructureMap?¿Solo en la aplicación de inicio?¿Eso significa que todas las implementaciones deben transmitirse desde la capa superior hasta la capa inferior?

Yo uso Castle Windsor/Microkernel, no tengo experiencia con nada más pero me gusta mucho.

¿En cuanto a cómo decides qué inyectar?Hasta ahora la siguiente regla general me ha resultado muy útil:Si la clase es tan simple que no necesita pruebas unitarias, puede crear una instancia de ella en la clase; de ​​lo contrario, probablemente desee tener una dependencia a través del constructor.

En cuanto a si debería crear una interfaz o simplemente hacer que sus métodos y propiedades sean virtuales, creo que debería seguir la ruta de la interfaz si a) puede ver que la clase tiene cierto nivel de reutilización en una aplicación diferente (es decir,un registrador) o b) si debido a la cantidad de parámetros del constructor o porque hay una cantidad significativa de lógica en el constructor, la clase es difícil de burlar.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top