¿Por qué se denomina Inversión de control de esa manera?

93

Las palabras invert o control no se usan en absoluto para definir Inversión de control en las definiciones que he visto.

Definiciones

Wikipedia

  

la inversión de control (IoC) es una técnica de programación, expresada aquí   en términos de programación orientada a objetos, en la que el acoplamiento de objetos es   enlazado en tiempo de ejecución por un objeto ensamblador y normalmente no se conoce en   Tiempo de compilación utilizando análisis estático. ~ enlace

Martin Fowler

  

La inversión de control es un patrón común en la comunidad Java que ayuda a cablear o ensamblar contenedores livianos   Componentes de diferentes proyectos en una aplicación cohesiva. ~ basado en enlace (reformulado)

Entonces, ¿por qué se llama Inversión de control Inversión de control? ¿Qué control se está invirtiendo y por qué? ¿Hay alguna manera de definir la Inversión de control utilizando la terminología: invert y control ?

    
pregunta Korey Hinton 22.07.2013 - 18:36
fuente

7 respuestas

65

Supongamos que tiene algún tipo de clase de "repositorio" y que el repositorio es responsable de entregarle los datos desde una fuente de datos.

El repositorio podría establecer una conexión al origen de datos por sí mismo. Pero, ¿y si le permitiera pasar una conexión al origen de datos a través del constructor del repositorio?

Al permitir que la persona que llama proporcione la conexión, se ha desacoplado la dependencia de conexión de la fuente de datos de la clase de repositorio, permitiendo que la fuente de datos de cualquier funcione con el repositorio, no solo la que el repositorio especifica .

Usted tiene control invertido al asignar la responsabilidad de crear la conexión de la clase de repositorio a la persona que llama.

Martin Fowler sugiere usar el término "Inyección de dependencia" para describir este tipo de Inversión de control, ya que la Inversión de control como un concepto puede aplicarse más ampliamente que simplemente inyectar dependencias en un método de construcción.

    
respondido por el Robert Harvey 22.07.2013 - 18:50
fuente
76

No creo que nadie pueda explicarlo mejor que Martin Fowler, más abajo el artículo al que enlazó .

  

Para esta nueva generación de contenedores, la inversión consiste en cómo buscar una implementación de complemento. En mi ingenuo ejemplo, el lister buscó la implementación del buscador mediante una instanciación directa. Esto evita que el buscador sea un complemento. El enfoque que utilizan estos contenedores es garantizar que cualquier usuario de un complemento siga alguna convención que permita que un módulo de ensamblador independiente inyecte la implementación en el lister.

Como explica en los párrafos anteriores, esto no es lo mismo que la razón por la cual se originó el término "Inversión de control".

  

Cuando estos contenedores hablan de cómo son tan útiles porque implementan la "Inversión de control", termino muy desconcertado. La inversión de control es una característica común de los marcos, por lo que decir que estos contenedores livianos son especiales porque utilizan la inversión de control es como decir que mi auto es especial porque tiene ruedas.

     

La pregunta, ¿qué aspecto del control están invirtiendo? Cuando me topé con la inversión de control, estaba en el control principal de una interfaz de usuario. Las primeras interfaces de usuario fueron controladas por el programa de aplicación. Tendría una secuencia de comandos como "Ingresar nombre", "ingresar dirección"; su programa guiará las indicaciones y responderá a cada una. Con las IU gráficas (o incluso basadas en pantalla), el marco de la interfaz de usuario contendría este bucle principal y su programa proporcionó en su lugar controladores de eventos para los diversos campos en la pantalla. El control principal del programa se invirtió, se alejó de usted al marco.

Es por eso que continúa acuñando el término "inyección de dependencia" para cubrir esta implementación específica de Inversión de control.

  

Como resultado, creo que necesitamos un nombre más específico para este patrón. Inversión de control es un término demasiado genérico, y por eso la gente lo encuentra confuso. Como resultado de una gran cantidad de discusión con varios defensores de la IoC, nos decidimos por el nombre de inyección de dependencia.

Para aclarar un poco: Inversión de control significa cualquier cosa que invierta la estructura de control de un programa desde el diseño de procedimiento clásico.

En días de antaño, un ejemplo clave de esto fue permitir que un marco maneja la comunicación entre una UI y su código, en lugar de dejar su código para generar la UI directamente.

En tiempos más recientes (cuando tales marcos dominaban bastante, por lo que la pregunta ya no era relevante), un ejemplo fue invertir el control sobre la creación de instancias de objetos.

Fowler y otros decidieron que el término Inversión de control cubría demasiadas técnicas y que necesitábamos un nuevo término para el ejemplo específico de creación de instancias de objetos (inyección de dependencia), pero en el momento en que se llegó a un acuerdo, la frase "IoC Container" había despegado.

Esto confunde mucho el agua, porque un contenedor IoC es un tipo específico de inyección de dependencia, pero la inyección de dependencia es un tipo específico de inversión de control. Esta es la razón por la que obtienes respuestas tan confusas, sin importar dónde mires.

    
respondido por el pdr 22.07.2013 - 18:50
fuente
30

Estos son los programas de flujo de control "regulares" que usualmente se siguen:

  • Ejecutar comandos secuencialmente
  • Usted mantiene el control sobre el flujo de control del programa

La inversión de control "invierte" ese flujo de control, lo que significa que lo voltea sobre su cabeza:

  • Tu programa ya no controla el flujo. En lugar de llamar a los comandos como mejor le parezca, espera a que otra persona lo llame .

Esa última línea es la importante. En lugar de llamar a alguien más cuando te da la gana, alguien te llama cuando le da la gana.

Un ejemplo común de esto son los marcos web como Rails. Usted define los Controladores, pero en realidad no decide cuándo se llaman esos. Rails los llama cuando decide que hay una necesidad.

    
respondido por el dsw88 22.07.2013 - 19:33
fuente
12

Se trata de quién controla la instanciación de dependencias.

Tradicionalmente, cuando una clase / método necesita usar otra clase (dependencia), es instanciada por la clase / método directamente. Controla sus dependencias.

Con Inversión de control (IoC), el llamante pasado en la dependencia, por lo tanto, crea una instancia de la dependencia. La persona que llama controla las dependencias.

El control de dónde se crea una instancia de una dependencia se ha invertido, en lugar de estar en el "fondo", donde está el código que lo necesita, se crea una instancia en la "parte superior", donde se llama el código que lo necesita .

    
respondido por el Oded 22.07.2013 - 18:40
fuente
2

Por lo general, las llamadas de código de nivel superior (es decir, los controles) del código de nivel inferior. Main () llama a function (), function () llama a libraryFunction ().

Eso se puede invertir, por lo que la función de biblioteca de bajo nivel en la parte inferior llama funciones de nivel superior.

¿Por qué harías eso? Middleware A veces, quieres controlar el nivel superior y el nivel inferior, pero hay mucho trabajo en el medio que simplemente no quieres hacer. Tome la implementación de quicksort en C stdlib . Usted llama Quicksort en el nivel superior. Le das a qsort () un puntero de función a tu propia función que implementa un comparador en lo que quieras. Cuando se llama a qsort (), llama a esta función de comparación. qsort () está controlando / llamando / conduciendo su función de alto nivel.

    
respondido por el Philip 22.07.2013 - 20:23
fuente
1

Aquí hay una simple descripción:

  1. El control se refiere a lo que el programa hace a continuación
  2. En el nivel superior, generalmente hay dos cosas que controlan el control: la aplicación en sí misma y el usuario

En los días anteriores, el control era propiedad de la aplicación primero y el usuario en segundo lugar. Si la aplicación necesitaba algo del usuario, se detendría y preguntaría y luego continuaría con su próxima tarea. La interacción del usuario proporcionó principalmente datos en lugar de controlar lo que la aplicación hizo a continuación. Esto es un poco extraño para nosotros hoy en día ya que no vemos este tipo de comportamiento muy a menudo.

Si cambiamos eso y le damos el control primario al usuario, entonces hemos invertido el control. Esto significa que en lugar de que el usuario espere a que la aplicación le dé algo que hacer, la aplicación espera a que el usuario le dé algo que hacer. Las GUI son un gran ejemplo de esto y casi cualquier cosa con un bucle de eventos tiene control invertido.

Tenga en cuenta que mi ejemplo está en el nivel superior y que este concepto de inversión de control puede resumirse en diferentes capas de control dentro de la aplicación (es decir, inyección de dependencia). Esta puede ser la razón por la que es tan difícil obtener una respuesta directa.

    
respondido por el Loren 11.05.2015 - 17:26
fuente
0

Intentemos entenderlo a través de los dos ejemplos.

Ejemplo 1

En días anteriores, las aplicaciones utilizadas para generar solicitudes de comando para aceptar entradas de usuario una tras otra. Hoy en día, los marcos de UI crean una instancia de varios elementos de la interfaz de usuario, recorren varios eventos de esos elementos de la interfaz de usuario (como el mouse del mouse, el clic, etc.) y los programas de usuario / principal proporcionan enlaces (por ejemplo, los escuchas de eventos de la interfaz de usuario en Java) para escuchar esos eventos. Por lo tanto, el "control" principal del flujo de elementos de la interfaz de usuario se mueve del programa del usuario al marco de la interfaz de usuario. En días anteriores, estaba en el programa de usuario.

Ejemplo 2

Considere la clase CustomerProcessor a continuación:

class CustomerProcessor
{
    SqlCustRepo custRepo = new SqlCustRepo(); 
    private void processCustomers()
    {
            Customers[] custs = custRepo.getAllCusts();
    }
}

Si quiero que processCustomer() sea independiente de cualquier implementación de getAllCusts() , no solo la proporcionada por SqlCustRepo , tendré que deshacerme de la línea: SqlCustRepo custRepo = new SqlCustRepo() y reemplazarla con algo más genérico, capaz de aceptar diversos tipos de implementación, de manera que processCustomers() simplemente funcionará para cualquier implementación provista. El código anterior (instanciar la clase requerida SqlCustRepo por la lógica del programa principal) es una forma tradicional y no logra este objetivo de desacoplar processCustomers() de la implementación de getAllCusts() . En la inversión de control, el contenedor crea una instancia de la clase de implementación requerida (según lo especificado por, digamos, configuración xml), lo inyecta en la lógica del programa principal que se enlaza según los ganchos especificados (por ejemplo, por @Autowired anotación o getBean() método en primavera marco).

Veamos cómo se puede hacer esto. Considera el siguiente código.

Config.xml

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
    <bean id="custRepo" class="JsonCustRepo" />
</beans>

CustRepo.java

interface ICustRepo 
{ ... }

JsonCustRepo.java

class JsonCustRepo implements CustRepo
{ ... }

App.java

class App
{
    public static void main(String[] args) 
    {
        ApplicationContext context = new ClassPathXmlApplicationContext("Config.xml");
        ICustRepo custRepo = (JsonCustRepo) context.getBean("custRepo");
    }
}

También podemos tener

class GraphCustRepo implements ICustRepo { ... }   

y

<bean id="custRepo" class="GraphCustRepo">

y no necesitaremos cambiar App.java.

Sobre el contenedor (que es el marco de Spring) tiene la responsabilidad de escanear un archivo xml, crear una instancia del bean de un tipo específico e inyectarlo en el programa del usuario. El programa de usuario no tiene control sobre qué clase se crea una instancia.

PS: IoC es un concepto genérico y se logra de muchas maneras. Los ejemplos anteriores lo consiguen mediante la inyección de dependencia.

Referencia: artículo de Martin Fowler .

    
respondido por el Mahesha999 03.08.2018 - 11:50
fuente

Lea otras preguntas en las etiquetas