2008-08-26 22 views
16

He estado usando StructureMap recientemente y he disfrutado la experiencia a fondo. Sin embargo, puedo ver cómo uno puede dejarse llevar fácilmente interconectando todo y terminar con clases que llevan una gran cantidad de interfaces a sus constructores. A pesar de que 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.¿Cuándo usa la inyección de dependencia?

¿Dónde se dibuja la línea sobre qué interfaz interactuar frente a solo agregar una propiedad a la clase?

Respuesta

9

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

Una buena regla general es que si es demasiado difícil de probar, tiene 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 usando un marco DI para inyectar la instancia correcta en el tiempo de ejecución. Al hacer esto, haces que sea trivial probar las dos partes por separado.

2

¿Qué quiere decir con "solo agregar una propiedad a una clase?"

Mi regla de oro es hacer que la unidad de clase sea comprobable. Si su clase depende de los detalles de implementación de otra clase, debe ser refactorizada/abstraída hasta el punto de que las clases se puedan probar de forma aislada.

EDITAR: Menciona un bote de interfaces en el constructor. Aconsejaría utilizar setters/getters en su lugar. Me parece que hace las cosas mucho más fáciles de mantener a largo plazo.

2

Lo hago solo cuando ayuda con la separación de preocupaciones.

Como tal vez a través del proyecto que proporcionaría una interfaz para los implementadores en una de mi proyecto de la biblioteca y el proyecto de implementación de inyectaría cualquier aplicación específica que quieren en.

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

1

Incluso con todos los hechos y procesos en el mundo .. cada decisión se reduce a una cuestión de criterio - recuerdo donde leí que
creo que es más bien un tiempo de atención de la experiencia/vuelo. Básicamente, si ve la dependencia como un objeto candidato que puede ser reemplazado en el futuro cercano, use la inyección de dependencia. Si veo 'classA y sus dependencias' como un bloque para la sustitución, entonces probablemente no use DI para los deps.

1

El mayor beneficio es que lo ayudará a comprender o incluso a descubrir la arquitectura de su aplicación. Podrá ver muy claramente cómo funcionan sus cadenas de dependencia y podrá realizar cambios en las partes individuales sin que sea necesario cambiar las cosas que no están relacionadas. Usted terminará con una aplicación débilmente acoplada. Esto lo impulsará a un mejor diseño y se sorprenderá cuando pueda seguir mejorando 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.

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

0

Otro artículo con el que lucho es ¿dónde debo usar la inyección de dependencia? ¿De dónde toma su dependencia en StructureMap? ¿Solo en la aplicación de inicio? ¿Eso significa que todas las implementaciones se deben pasar desde la capa superior a la capa inferior?

22

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á haciendo es mover ese acoplamiento desde el tiempo de compilación al tiempo de ejecución, pero aún si la clase A necesita alguna interfaz B para funcionar, todavía falta proporcionar una instancia de una clase que implemente la interfaz B.

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

usos que he visto útil para una inversión del patrón de control:

  • Una arquitectura de plugins. Entonces, al hacer los puntos de entrada correctos, puede definir el contrato para el servicio que debe proporcionarse.
  • Arquitectura similar a un flujo de trabajo. Donde puede 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 usar la inyección de dependencia puede proporcionar fácilmente solo los componentes principales y algunos componentes "agregados" que proporcionan solo las características que el cliente ha pagado.
  • Traducción. Aunque esto no suele hacerse con fines de traducción, puede "inyectar" diferentes archivos de idioma según lo necesite la aplicación. Eso incluye interfaces de usuario RTL o LTR según sea necesario.
+1

Me he quedado sin votos hoy, así que no puedo votar, pero me gusta su respuesta. Tienes razón, solo porque usas DI no significa que tu código esté de hecho débilmente acoplado. –

+0

Creo que no estoy de acuerdo con esta respuesta. Que yo sepa, el mayor y más importante beneficio del código DInjected es la capacidad de prueba. Literalmente no puedes leer un solo libro sobre Dependency Injection ni Desarrollo basado en pruebas, sin que uno se refiera al otro. Van juntos como avena y pasas. – BTownTKD

+0

El código dinilado es más fácil de simular, lo que facilita la creación de pruebas para las cosas que usan ese código inyectado. Aún así, creo que las pruebas por sí solas no deberían ser una razón para usar la inyección de dependencia. La inyección de dependencia agrega complejidad (más interfaces, arquitectura menos directa) por lo que si no la reduce considerablemente de otras formas (aparte de las pruebas) o resuelve un problema específico que usted tiene, no vale la pena agregarlo. –

8

La inyección de dependencia sólo debe utilizarse para las partes de la aplicación que necesitan ser cambiado dinámicamente sin tener que recompilar el código base

DI se debe utilizar 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 prohibitivo en muchas compañías si está probando componentes que DEPENDAN de una base de datos.

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

0

Uso Castle Windsor/Microkernel, no tengo experiencia con ninguna otra cosa pero me gusta mucho.

¿Cómo decidir qué inyectar? Hasta ahora, la siguiente regla práctica me ha funcionado bien: si la clase es tan simple que no necesita pruebas unitarias, puede crear una instancia en clase, de lo contrario, probablemente desee tener una dependencia a través del constructor.

En cuanto a si se debe crear una interfaz vs acaba de hacer sus métodos y propiedades virtuales Creo que debería ir a la ruta de interfaz, ya sea si bien a) puede ver la clase tener cierto nivel de reutilización en una aplicación diferente (es decir, una logger) o b) ya sea debido a la cantidad de parámetros del constructor o porque hay una cantidad significativa de lógica en el constructor, la clase es de otra manera difícil de simular.

Cuestiones relacionadas