Término técnico para denotar opuesto de inyección de dependencia?

12

Esto es más una nomenclatura (escritura técnica) que una pregunta puramente técnica. Estoy tratando de escribir una propuesta de refactorización (y asignarla a mí mismo) centrada en expandir la inyección de dependencia en nuestra aplicación. Si bien utilizamos Spring para autoabastecer beans, todavía hay instancias que crean instancias de beans MyClass obj = new MyClass(...)que podrían inyectarse por completo. Me gustaría hacer que mi propuesta use una nomenclatura elegante y referirme al patrón de diseño opuesto a DI con un término apropiado.

¿Es "acoplamiento apretado" un término adecuado que se erige como un antónimo de DI?

anfibio
fuente
1
Sí, el acoplamiento describe tanto el acto de usar nombres de clase explícitos en otras clases como el estado resultante de una base de código.
Kilian Foth
11
No, el acoplamiento estrecho solo describe la propiedad del código resultante, no lo contrario de DI. Puede usar DI y aún tener un acoplamiento apretado por razones completamente diferentes.
Doc Brown
1
Convino en que la DI y el acoplamiento hermético no son opuestos .
Eric King
@EricKing presumir. +1 por cierto.
candied_orange
1
"Succión de dependencia" .
SeldomNeedy

Respuestas:

30

No. El acoplamiento apretado es mucho más de lo que trata la inyección de dependencia.

La inyección de dependencia externaliza una decisión de implementación. Esto va muy lejos para desacoplar, pero el acoplamiento es más que solo esto.

Un buen antónimo para la inyección de dependencias es codificar una dependencia . Cuando construyes (usa uno nuevo o usa directamente una fábrica) dentro de un objeto de comportamiento, has eliminado dos preocupaciones diferentes. Un localizador de servicios ayuda a desacoplar pero lo deja acoplado al localizador de servicios en sí.

El acoplamiento es más que solo separar la construcción y el comportamiento. Si tengo 101 métodos que deben llamarse en un orden particular de clase A a clase B, estoy estrechamente acoplado. No importa cuán maravillosamente separadas estén la construcción y el comportamiento.

El acoplamiento es una medida de la interdependencia de los dos objetos. Cualquier cosa que contribuya a dificultar hacer cambios en uno sin afectar al otro está contribuyendo al acoplamiento. La inyección de dependencia ayuda con esto, pero no es todo esto.

naranja confitada
fuente
Sí, la codificación rígida (una dependencia), en lugar de inyectarla (en tiempo de ejecución) es exactamente lo que iba a sugerir, también, usted era un poco más rápido que yo.
Doc Brown
77
@DocBrown A veces desearía que este lugar no pusiera tanto énfasis en ser rápido. Me gustaría saber cómo lo pondrías.
candied_orange
Buena respuesta: la inyección de dependencia no implica desacoplamiento. Creer lo contrario conduce por un mal camino
Ant P
1
@CandiedOrange Quizás alguien debería sugerir en meta que las respuestas permanezcan ocultas por un período de tiempo. Y / o que los votos se oculten de la vista del público durante Nhoras ... O hasta que se seleccione una respuesta. ¡Sé que no soy completamente objetivo cuando una respuesta ya tiene 10 votos y las otras 5 respuestas no tienen ninguno!
svidgen
1
@svidgen busca "arma más rápida en el oeste" en meta. El problema ya tiene una larga historia.
candied_orange
6

Estrictamente hablando, la Inyección de dependencias solo se opone realmente a NO la Inyección de dependencias y, por lo tanto, a cualquier estrategia de administración de dependencias que no sea Inyección de dependencias.

El acoplamiento [no deseado], aunque no es exactamente un problema ortogonal, puede ocurrir o mitigarse de cualquier manera. Ambos están acoplados a DependencyClass:

public DependencyInjectedConstructor(DependencyClass dep) {
  dep.do();
}

public DependencyLookupConstructor() {
  var dep = new DependencyClass();
  dep.do();
}

DependencyLookupConstructorestá acoplado a un particular DependencyClassen este caso. Sin embargo, son ambos acoplados a DependencyClass. El verdadero mal, si hay uno aquí, no es necesariamente el acoplamiento, es que DependencyLookupConstructordebe cambiar si de DependencyClassrepente necesita inyectar sus propias dependencias 1 .

Sin embargo, este constructor / clase está aún más débilmente acoplado:

public DependencyLocatingConstructor() {
  var dep = ServiceLocator.GetMyDoer();
  dep.do();
}

Si está trabajando en C #, lo anterior permitan que el ServiceLocatorregresar nada cuando GetMyDoer()se invoca, con tal de que tiene puede do()lo que DependencyLocatingConstructorlo tiene do(). Obtiene el beneficio de la validación de firma en tiempo de compilación sin siquiera estar acoplado a una interfaz completa 2 .

Entonces, elige tu veneno.

Pero, básicamente, si hay un "opuesto" concreto de la Inyección de dependencias, sería algo más en el ámbito de las "Estrategias de gestión de dependencias". Entre otros, si utilizó alguno de los siguientes en la conversación, lo reconocería como NO una inyección de dependencia:

  • Patrón de localizador de servicio
  • Localizador de dependencia / ubicación
  • Construcción directa de objeto / dependencia
  • Dependencia oculta
  • "No inyección de dependencia"

1. Irónicamente, algunos de los problemas que DI resuelve en niveles más altos son el resultado de [sobre-] usar DI en los niveles más bajos. He tenido el placer de trabajar en bases de código con una complejidad innecesaria en todas partes como resultado de acomodar el puñado de lugares donde esa complejidad realmente ayudó ... Estoy ciertamente predispuesto por la mala exposición.

2. El uso de la ubicación del servicio también le permite especificar fácilmente diferentes dependencias del mismo tipo por su función funcional del código de invocación , mientras sigue siendo en gran medida agnóstico sobre cómo se construye la dependencia. Suponga que necesita resolver Usero IUserpara diferentes propósitos: por ejemplo, Locator.GetAdministrator()versus Locator.GetAuthor(), o lo que sea. Mi código puede preguntar qué necesita funcionalmente sin siquiera saber qué interfaces admite.

svidgen
fuente
2
La salvación DependencyInjectedConstructor(DependencyClass dep)es que DependencyClass podría ser una interfaz o una clase abstracta. Es por eso que me entristece que los codificadores de C # usen un prefijo de interfaz, como en IDependency. Como cliente, realmente no es asunto mío lo que es esta cuestión de dependencia. Mientras no lo construya, todo lo que tengo que saber es cómo hablar con él. Lo que es es el problema de otra persona.
candied_orange
Los puntos son, DI todavía lo conecta a esa interfaz, y no requiere que DependencyClasssea ​​una interfaz abstracta en absoluto. Que sólo se requiere que la lógica de la construcción / configuración / ubicación existente "en otro lugar." ... Bueno, y más pertinente a la pregunta, el punto es que DI no es "lo opuesto al acoplamiento apretado" :)
svidgen
En realidad ... puedo estar un poco fuera de límites al decir que DI necesariamente te conecta a una interfaz, incluso en C #. Sin embargo, los he evitado en C #, tengo la impresión de que también podría aceptar dynamicparámetros. (Pero no varparámetros, si la memoria sirve). Entonces, con DI en C #, creo que tengo que codificar contra una interfaz, o tengo que renunciar totalmente a la validación en tiempo de compilación.
svidgen
Los objetos están acoplados a las interfaces. Si usa la palabra clave de interfaz o no. Eso es lo que es una interfaz adecuada. Todo a lo que TIENES que estar unido. Lo que elimina son detalles de implementación y cosas adicionales que no necesita. Podemos formalizar esto usando la palabra clave de interfaz para permitir que el cliente le diga al mundo: "Todo lo que necesito es esto". Pero no tenemos que hacerlo. Diablos, podemos escribir pato, bueno en algunos idiomas.
candied_orange
No estoy seguro de que estemos en total desacuerdo. Pero, para aclarar ... Los objetos están acoplados internamente a sus propias interfaces, sí. Pero, la interfaz en sí solo impone el acoplamiento de dependencias si la interfaz se nombra explícitamente. En C #, usar dynamico vary obtener un objeto de un localizador le permite ignorar la interfaz y usar cualquier clase que pueda do()lo que necesita, independientemente de si esa clase implementa alguna IDoerinterfaz. En otras palabras, si tenemos A-> B <-C, DI desacopla A de C, pero requiere que A y C estén acoplados a B, y evita el uso de D, incluso si D lo hará do().
svidgen
2

No sé si existe una terminología específica de la industria ampliamente aceptada, pero las alternativas que se me ocurren incluyen la creación de instancias internas , la creación de dependencias internas , las dependencias locales o las dependencias de ámbito local .

mcknz
fuente
2
me gusta instance creationpero no es lo suficientemente específico. DI crea instancias pero por medio del controlador y no a nivel de aplicación. tal vezinternal instance creation
anfibio
1

Yo iría con la encapsulación de dependencia . Esto expresa que la dependencia está bloqueada en lugar de visitar y salir nuevamente.

Martin Maat
fuente