La inversión de control (IoC) puede ser bastante confusa cuando se encuentra por primera vez.
- ¿Qué es?
- ¿Qué problema resuelve?
- ¿Cuándo es apropiado usar y cuándo no?
La inversión de control (IoC) puede ser bastante confusa cuando se encuentra por primera vez.
Respuestas:
Los patrones de Inversión de control (IoC) e Inyección de dependencias (DI) tienen que ver con eliminar las dependencias de su código.
Por ejemplo, supongamos que su aplicación tiene un componente de editor de texto y desea proporcionar la corrección ortográfica. Su código estándar se vería así:
public class TextEditor {
private SpellChecker checker;
public TextEditor() {
this.checker = new SpellChecker();
}
}
Lo que hemos hecho aquí crea una dependencia entre el TextEditor
y el SpellChecker
. En un escenario de IoC, haríamos algo como esto:
public class TextEditor {
private IocSpellChecker checker;
public TextEditor(IocSpellChecker checker) {
this.checker = checker;
}
}
En el primer ejemplo de código estamos instanciando SpellChecker
( this.checker = new SpellChecker();
), lo que significa que la TextEditor
clase depende directamente de la SpellChecker
clase.
En el segundo ejemplo de código, estamos creando una abstracción al tener la SpellChecker
clase de dependencia en TextEditor
la firma del constructor (no inicializando la dependencia en la clase). Esto nos permite llamar a la dependencia y luego pasarla a la clase TextEditor así:
SpellChecker sc = new SpellChecker; // dependency
TextEditor textEditor = new TextEditor(sc);
Ahora el cliente que crea la TextEditor
clase tiene control sobre qué SpellChecker
implementación usar porque estamos inyectando la dependencia en la TextEditor
firma.
La inversión de control es lo que obtienes cuando las devoluciones de llamada de tu programa, por ejemplo, como un programa gui.
Por ejemplo, en un menú de la vieja escuela, podría tener:
print "enter your name"
read name
print "enter your address"
read address
etc...
store in database
controlando así el flujo de interacción del usuario.
En un programa GUI o somesuch, en su lugar decimos:
when the user types in field a, store it in NAME
when the user types in field b, store it in ADDRESS
when the user clicks the save button, call StoreInDatabase
Así que ahora el control está invertido ... en lugar de que la computadora acepte la entrada del usuario en un orden fijo, el usuario controla el orden en que se ingresan los datos y cuando los datos se guardan en la base de datos.
Básicamente, cualquier cosa con un bucle de eventos, devoluciones de llamada o disparadores de ejecución cae en esta categoría.
¿Qué es la inversión de control?
Si sigue estos dos simples pasos, ha realizado una inversión de control:
Existen varias técnicas posibles para cada uno de estos pasos en función de la tecnología / lenguaje que está utilizando para su implementación.
-
La parte de inversión de la Inversión de Control (IoC) es lo confuso; porque inversión es el término relativo. ¡La mejor manera de entender IoC es olvidarse de esa palabra!
-
Ejemplos
what-to-do
ywhen-to-do
La inversión de los controles se trata de separar las preocupaciones.
Sin IoC : tienes una computadora portátil y accidentalmente rompes la pantalla. Y maldita sea, usted encuentra que la misma pantalla del portátil modelo no está en ninguna parte del mercado. Entonces estás atrapado.
Con IoC : tienes un escritorio computadora de y accidentalmente rompes la pantalla. Descubres que puedes tomar casi cualquier monitor de escritorio del mercado, y funciona bien con tu escritorio.
Su escritorio implementa exitosamente IoC en este caso. Acepta una variedad de monitores, mientras que la computadora portátil no, necesita una pantalla específica para arreglarse.
Inversion of Control, (o IoC), se trata de obtener la libertad (te casas, pierdes la libertad y estás siendo controlado. Te divorciaste, acabas de implementar Inversion of Control. Eso es lo que llamamos "desacoplado". Buen sistema informático desalienta algunas relaciones muy cercanas.) más flexibilidad (la cocina en su oficina solo sirve agua limpia del grifo, esa es su única opción cuando quiere beber. Su jefe implementó la Inversión de control al configurar una nueva máquina de café. Ahora obtiene la flexibilidad para elegir agua del grifo o café) y menos dependencia (Su pareja tiene un trabajo, usted no tiene un trabajo, depende económicamente de su pareja, por lo que está controlado. Encuentra un trabajo, ha implementado la Inversión de control. Un buen sistema informático fomenta la dependencia).
Cuando usa una computadora de escritorio, ha esclavizado (o, por ejemplo, controlado). Tienes que sentarte ante una pantalla y mirarla. Usando el teclado para escribir y usando el mouse para navegar. Y un software mal escrito puede esclavizarte aún más. Si reemplaza su escritorio con una computadora portátil, entonces invirtió un poco el control. Puede tomarlo fácilmente y moverse. Así que ahora puedes controlar dónde estás con tu computadora, en lugar de que tu computadora lo controle.
Al implementar la Inversión de control, un consumidor de software / objeto obtiene más controles / opciones sobre el software / objetos, en lugar de ser controlado o tener menos opciones.
Con las ideas anteriores en mente. Todavía extrañamos una parte clave de IoC. En el escenario de IoC, el consumidor de software / objeto es un marco sofisticado. Eso significa que el código que creó no lo llama usted mismo. Ahora expliquemos por qué esta manera funciona mejor para una aplicación web.
Supongamos que su código es un grupo de trabajadores. Necesitan construir un auto. Estos trabajadores necesitan un lugar y herramientas (un marco de software) para construir el automóvil. Un marco de software tradicional será como un garaje con muchas herramientas. Por lo tanto, los trabajadores deben hacer un plan ellos mismos y usar las herramientas para construir el automóvil. Construir un automóvil no es un negocio fácil, será muy difícil para los trabajadores planificar y cooperar adecuadamente. Un modernoEl marco de software será como una fábrica de automóviles moderna con todas las instalaciones y gerentes en su lugar. Los trabajadores no tienen que hacer ningún plan, los gerentes (parte del marco, son las personas más inteligentes y elaboraron el plan más sofisticado) ayudarán a coordinar para que los trabajadores sepan cuándo hacer su trabajo (el marco llama a su código). Los trabajadores solo necesitan ser lo suficientemente flexibles como para usar cualquier herramienta que los gerentes les den (mediante el uso de la inyección de dependencia).
Aunque los trabajadores dan el control de la gestión del proyecto en el nivel superior a los gerentes (el marco). Pero es bueno contar con la ayuda de algunos profesionales. Este es realmente el concepto de IoC.
Las aplicaciones web modernas con una arquitectura MVC dependen del marco para realizar el enrutamiento de URL y poner los controladores en su lugar para que el marco llame.
La inyección de dependencia y la inversión de control están relacionadas. La inyección de dependencia está en el nivel micro y la inversión de control está en el nivel macro . Tienes que comer cada bocado (implementar DI) para terminar una comida (implementar IoC).
Antes de usar Inversion of Control, debe ser consciente del hecho de que tiene sus pros y sus contras, y debe saber por qué lo usa si lo hace.
Pros:
Contras:
Personalmente, veo los puntos fuertes de IoC y realmente me gustan, pero tiendo a evitar IoC siempre que sea posible porque convierte su software en una colección de clases que ya no constituyen un programa "real", sino simplemente algo que debe ser organizado por Configuración XML o metadatos de anotación y se desmoronarían (y se desmoronarían) sin él.
Artículo de Wikipedia . Para mí, la inversión de control es convertir su código escrito secuencialmente y convertirlo en una estructura de delegación. En lugar de que su programa controle explícitamente todo, su programa configura una clase o biblioteca con ciertas funciones a las que se llamará cuando sucedan ciertas cosas.
Resuelve la duplicación de código. Por ejemplo, en los viejos tiempos escribiría manualmente su propio bucle de eventos, sondeando las bibliotecas del sistema en busca de nuevos eventos. Hoy en día, en las API más modernas, simplemente le dice a las bibliotecas del sistema en qué eventos está interesado, y le informará cuándo suceden.
La inversión del control es una forma práctica de reducir la duplicación de código, y si te encuentras copiando un método completo y solo cambiando una pequeña parte del código, puedes considerar abordarlo con una inversión de control. La inversión del control se facilita en muchos idiomas mediante el concepto de delegados, interfaces o incluso punteros de función sin formato.
No es apropiado usarlo en todos los casos, porque el flujo de un programa puede ser más difícil de seguir cuando se escribe de esta manera. Es una forma útil de diseñar métodos al escribir una biblioteca que se reutilizará, pero debe usarse con moderación en el núcleo de su propio programa a menos que realmente resuelva un problema de duplicación de código.
Pero creo que debes tener mucho cuidado con eso. Si usa en exceso este patrón, hará un diseño muy complicado y un código aún más complicado.
Como en este ejemplo con TextEditor: si solo tiene un SpellChecker, ¿tal vez no sea realmente necesario usar IoC? A menos que necesite escribir pruebas unitarias o algo así ...
De todos modos: sea razonable. Los patrones de diseño son buenas prácticas, pero no se debe predicar la Biblia. No lo pegues en todas partes.
IoC / DI para mí está eliminando las dependencias de los objetos que llaman. Súper simple
La respuesta que no es técnica es poder cambiar el motor de un automóvil justo antes de encenderlo. Si todo se conecta correctamente (la interfaz), está bien.
Supongamos que eres un objeto. Y vas a un restaurante:
Sin IoC : pides "manzana", y siempre te sirven manzana cuando pides más.
Con IoC : puede pedir "fruta". Puedes obtener diferentes frutas cada vez que te sirven. por ejemplo, manzana, naranja o sandía.
Entonces, obviamente, IoC se prefiere cuando te gustan las variedades.
La inversión del control es un patrón utilizado para desacoplar componentes y capas en el sistema. El patrón se implementa mediante la inyección de dependencias en un componente cuando se construye. Estas dependencias generalmente se proporcionan como interfaces para un mayor desacoplamiento y para soportar la capacidad de prueba. Los contenedores IoC / DI como Castle Windsor, Unity son herramientas (bibliotecas) que se pueden usar para proporcionar IoC. Estas herramientas proporcionan características extendidas más allá de la simple administración de dependencias, que incluyen la vida útil, AOP / Intercepción, políticas, etc.
a. Alivia a un componente de ser responsable de administrar sus dependencias.
si. Proporciona la capacidad de intercambiar implementaciones de dependencia en diferentes entornos.
C. Permite probar un componente a través de la burla de las dependencias.
re. Proporciona un mecanismo para compartir recursos en una aplicación.
a. Crítico cuando se realiza un desarrollo basado en pruebas. Sin IoC puede ser difícil de probar, porque los componentes bajo prueba están altamente acoplados al resto del sistema.
si. Crítico al desarrollar sistemas modulares. Un sistema modular es un sistema cuyos componentes se pueden reemplazar sin necesidad de recompilación.
C. Es crítico si hay muchas preocupaciones transversales que deben abordarse, en particular en una aplicación empresarial.
Respondiendo solo la primera parte. ¿Qué es?
Inversion of Control (IoC) significa crear instancias de dependencias primero y última instancia de una clase (opcionalmente inyectándolas a través del constructor), en lugar de crear primero una instancia de la clase y luego la instancia de clase creando instancias de dependencias. Por lo tanto, la inversión de control invierte el flujo de control del programa. En lugar de que la persona que llama controle el flujo de control (mientras crea dependencias), la persona que llama controla el flujo de control del programa .
Escribiré mi simple comprensión de estos dos términos:
For quick understanding just read examples*
Inyección de dependencia (DI): la
inyección de dependencia generalmente significa pasar un objeto del cual depende el método, como parámetro a un método, en lugar de hacer que el método cree el objeto dependiente .
Lo que significa en la práctica es que el método no depende directamente de una implementación particular; cualquier implementación que cumpla con los requisitos se puede pasar como un parámetro.
Con esto los objetos cuentan sus dependencias. Y la primavera lo hace disponible.
Esto conduce al desarrollo de aplicaciones poco acopladas.
Quick Example:EMPLOYEE OBJECT WHEN CREATED,
IT WILL AUTOMATICALLY CREATE ADDRESS OBJECT
(if address is defines as dependency by Employee object)
Contenedor de Inversión de Control (IoC):
Esta es una característica común de los marcos, el COI gestiona objetos java
, desde la creación de instancias hasta la destrucción a través de su BeanFactory.
-Los componentes de Java que son instanciados por el contenedor de IoC se denominan beans, y el contenedor de IoC gestiona el alcance de un bean, los eventos del ciclo de vida y cualquier característica de AOP para la que se haya configurado y codificado.
QUICK EXAMPLE:Inversion of Control is about getting freedom, more flexibility, and less dependency. When you are using a desktop computer, you are slaved (or say, controlled). You have to sit before a screen and look at it. Using keyboard to type and using mouse to navigate. And a bad written software can slave you even more. If you replaced your desktop with a laptop, then you somewhat inverted control. You can easily take it and move around. So now you can control where you are with your computer, instead of computer controlling it
.
Al implementar Inversion of Control, un consumidor de software / objeto obtiene más controles / opciones sobre el software / objetos, en lugar de ser controlado o tener menos opciones.
La inversión del control como guía de diseño sirve para los siguientes propósitos:
Hay un desacoplamiento de la ejecución de una determinada tarea de la implementación.
Cada módulo puede centrarse en para qué está diseñado.
Los módulos no hacen suposiciones sobre lo que hacen otros sistemas, sino que dependen de sus contratos.
Reemplazar módulos no tiene ningún efecto secundario sobre otros módulos
. Aquí mantendré las cosas abstractas. Puede visitar los siguientes enlaces para obtener una comprensión detallada del tema.
Una buena lectura con ejemplo
Estoy de acuerdo con NilObject , pero me gustaría agregar a esto:
si te encuentras copiando un método completo y solo cambiando una pequeña parte del código, puedes considerar abordarlo con una inversión de control
Si te encuentras copiando y pegando código, casi siempre estás haciendo algo mal. Codificado como el principio de diseño Once and Only Once .
Por ejemplo, la tarea # 1 es crear un objeto. Sin el concepto IOC, la tarea n. ° 1 debe ser realizada por el Programador, pero con el concepto IOC, la tarea n. ° 1 se realizaría por contenedor.
En resumen, el control se invierte del programador al contenedor. Entonces, se llama inversión de control.
Encontré un buen ejemplo aquí .
Digamos que hacemos alguna reunión en algún hotel.
Mucha gente, muchas garrafas de agua, muchos vasos de plástico.
Cuando alguien quiere beber, ella llena la taza, bebe y tira la taza al suelo.
Después de una hora o algo así, tenemos un piso cubierto de vasos de plástico y agua.
Deje invertir el control.
La misma reunión en el mismo lugar, pero en lugar de vasos de plástico tenemos un camarero con un vaso de vidrio (Singleton)
y ella siempre ofrece bebidas a los invitados.
Cuando alguien quiere beber, ella toma del vaso de camarero, bebe y se lo devuelve al camarero.
Dejando a un lado la cuestión de la higiene, la última forma de control del proceso de bebida es mucho más efectiva y económica.
Y esto es exactamente lo que hace Spring (otro contenedor de IoC, por ejemplo: Guice). En lugar de dejar que la aplicación cree lo que necesita usando una nueva palabra clave (tomar un vaso de plástico), el contenedor Spring IoC ofrece a la aplicación la misma instancia (singleton) del objeto necesario (vaso de agua).
Piense en usted como organizador de dicha reunión. Necesita la forma de enviar un mensaje a la administración del hotel que
los miembros de la reunión necesitarán un vaso de agua pero no un pedazo de pastel.
Ejemplo:-
public class MeetingMember {
private GlassOfWater glassOfWater;
...
public void setGlassOfWater(GlassOfWater glassOfWater){
this.glassOfWater = glassOfWater;
}
//your glassOfWater object initialized and ready to use...
//spring IoC called setGlassOfWater method itself in order to
//offer to meetingMember glassOfWater instance
}
Enlaces útiles:-
Parece que lo más confuso de "IoC", el acrónimo y el nombre que representa, es que es un nombre demasiado glamoroso, casi un nombre ruidoso.
¿Realmente necesitamos un nombre para describir la diferencia entre la programación basada en procedimientos y la de eventos? De acuerdo, si es necesario, pero ¿debemos elegir un nuevo nombre "más grande que la vida" que confunda más de lo que resuelve?
Inversión de control es cuando vas al supermercado y tu esposa te da la lista de productos para comprar.
En términos de programación, pasó una función de devolución de llamada getProductList()
a la función que está ejecutando:doShopping()
.
Permite al usuario de la función definir algunas partes de la misma, haciéndola más flexible.
getProductList()
para encontrar la fuente de dinero, significa que el control está a su lado. En el caso de la inversión, ella controlará, significa el dinero que también proporcionará para comprar.
Encontré un ejemplo muy claro aquí que explica cómo se 'invierte el control'.
Código clásico (sin inyección de dependencia)
Así es como un código que no usa DI funcionará aproximadamente:
Usando inyección de dependencia
Así es como un código que usa DI funcionará aproximadamente:
El control de las dependencias se invierte de una llamada a la que llama.
¿Qué problemas resuelve?
La inyección de dependencia facilita el intercambio con la implementación diferente de las clases inyectadas. Mientras realiza las pruebas unitarias, puede inyectar una implementación ficticia, lo que hace que las pruebas sean mucho más fáciles.
Por ejemplo: suponga que su aplicación almacena el archivo subido por el usuario en Google Drive, con DI su código de controlador puede verse así:
class SomeController
{
private $storage;
function __construct(StorageServiceInterface $storage)
{
$this->storage = $storage;
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
class GoogleDriveService implements StorageServiceInterface
{
public function authenticate($user) {}
public function putFile($file) {}
public function getFile($file) {}
}
Cuando sus requisitos cambien, por ejemplo, en lugar de GoogleDrive, se le pedirá que use Dropbox. Solo necesita escribir una implementación de Dropbox para StorageServiceInterface. No debe realizar ningún cambio en el controlador siempre que la implementación de Dropbox se adhiera a StorageServiceInterface.
Durante la prueba, puede crear el simulacro para StorageServiceInterface con la implementación ficticia donde todos los métodos devuelven nulo (o cualquier valor predefinido según su requisito de prueba).
En cambio, si tuviera la clase de controlador para construir el objeto de almacenamiento con la new
palabra clave como esta:
class SomeController
{
private $storage;
function __construct()
{
$this->storage = new GoogleDriveService();
}
public function myFunction ()
{
return $this->storage->getFile($fileName);
}
}
Cuando desee cambiar con la implementación de Dropbox, debe reemplazar todas las líneas donde new
construye el objeto GoogleDriveService y usar DropboxService. Además, al probar la clase SomeController, el constructor siempre espera la clase GoogleDriveService y se activan los métodos reales de esta clase.
¿Cuándo es apropiado y cuándo no? En mi opinión, usas DI cuando crees que hay (o puede haber) implementaciones alternativas de una clase.
Una explicación escrita muy simple se puede encontrar aquí
http://binstock.blogspot.in/2008/01/excellent-explanation-of-dependency.html
Dice -
"Cualquier aplicación no trivial se compone de dos o más clases que colaboran entre sí para realizar una lógica empresarial. Tradicionalmente, cada objeto es responsable de obtener sus propias referencias a los objetos con los que colabora (sus dependencias). Al aplicar DI, el los objetos reciben sus dependencias en el momento de la creación por parte de una entidad externa que coordina cada objeto en el sistema. En otras palabras, las dependencias se inyectan en los objetos ".
La inversión de control es un principio genérico, mientras que la inyección de dependencia se da cuenta de este principio como un patrón de diseño para la construcción de gráficos de objetos (es decir, la configuración controla cómo los objetos se hacen referencia entre sí, en lugar de que el objeto mismo controle cómo obtener la referencia a otro objeto).
Mirando a la Inversión de Control como un patrón de diseño, tenemos que mirar lo que estamos invirtiendo. La inyección de dependencia invierte el control de construir un gráfico de objetos. Si se dice en términos simples, la inversión de control implica un cambio en el flujo de control en el programa. P.ej. En la aplicación independiente tradicional, tenemos el método principal, desde donde el control se pasa a otras bibliotecas de terceros (en caso de que hayamos utilizado la función de biblioteca de terceros), pero a través de la inversión del control de control se transfiere del código de la biblioteca de terceros a nuestro código , ya que estamos tomando el servicio de una biblioteca de terceros. Pero hay otros aspectos que deben invertirse dentro de un programa, por ejemplo, invocación de métodos y subprocesos para ejecutar el código.
Para aquellos interesados en profundizar en la Inversión de Control, se ha publicado un documento que describe una imagen más completa de la Inversión de Control como patrón de diseño (OfficeFloor: uso de patrones de oficina para mejorar el diseño del software http://doi.acm.org/10.1145/ 2739011.2739013 con una copia gratuita disponible para descargar desde http://www.officefloor.net/about.html ).
Lo que se identifica es la siguiente relación:
Inversión de control (para métodos) = Dependencia (estado) Inyección + Inyección de continuación + Inyección de hilo
Resumen de la relación anterior para la Inversión de control disponible: http://dzone.com/articles/inversion-of-coupling-control
IoC se trata de invertir la relación entre su código y el código de terceros (biblioteca / marco):
DI (Inyección de dependencias) trata sobre cómo fluye el control en la aplicación. La aplicación de escritorio tradicional tenía flujo de control desde su aplicación (método main ()) a otras llamadas a métodos de biblioteca, pero con el flujo de control DI invertido, ese marco se encarga de iniciar su aplicación, inicializarla e invocar sus métodos siempre que sea necesario.
Al final siempre ganas :)
Me gusta esta explicación: http://joelabrahamsson.com/inversion-of-control-an-introduction-with-examples-in-net/
Comienza simple y muestra ejemplos de código también.
El consumidor, X, necesita la clase consumida, Y, para lograr algo. Todo eso es bueno y natural, pero ¿X realmente necesita saber que usa Y?
¿No es suficiente que X sepa que usa algo que tiene el comportamiento, los métodos, las propiedades, etc. de Y sin saber quién implementa realmente el comportamiento?
Al extraer una definición abstracta del comportamiento utilizado por X en Y, ilustrado como I a continuación, y dejar que el consumidor X use una instancia de eso en lugar de Y, puede continuar haciendo lo que hace sin tener que conocer los detalles sobre Y.
En la ilustración anterior, Y implementa I y X usa una instancia de I. Si bien es bastante posible que X todavía use Y, lo interesante es que X no lo sabe. Simplemente sabe que usa algo que implementa I.
Lea el artículo para obtener más información y descripción de beneficios como:
...
Entiendo que la respuesta ya se ha dado aquí. Pero sigo pensando que algunos conceptos básicos sobre la inversión del control tienen que ser discutidos aquí en detalle para futuros lectores.
La Inversión de Control (IoC) se ha construido sobre un principio muy simple llamado Principio de Hollywood . Y dice que
No nos llames, te llamaremos
Lo que significa es que no vayas a Hollywood para cumplir tu sueño, sino que si eres digno, Hollywood te encontrará y hará que tu sueño se haga realidad. Bastante invertido, ¿eh?
Ahora, cuando discutimos sobre el principio de IoC, solemos olvidarnos de Hollywood. Para IoC, tiene que haber tres elementos, un Hollywood, usted y una tarea como cumplir su sueño.
En nuestro mundo de programación, Hollywood representa un marco genérico (puede ser escrito por usted u otra persona), usted representa el código de usuario que escribió y la tarea representa lo que desea lograr con su código. ¡Ahora nunca va a activar su tarea usted mismo, no en IoC! Por el contrario, ha diseñado todo de tal manera que su marco desencadenará su tarea por usted. Por lo tanto, ha creado un marco reutilizable que puede hacer que alguien sea un héroe u otro un villano. Pero ese marco siempre está a cargo, sabe cuándo elegir a alguien y que alguien solo sabe lo que quiere ser.
Aquí se daría un ejemplo de la vida real. Supongamos que desea desarrollar una aplicación web. Entonces, crea un marco que manejará todas las cosas comunes que una aplicación web debe manejar, como manejar la solicitud http, crear el menú de la aplicación, servir páginas, administrar cookies, desencadenar eventos, etc.
Y luego deja algunos enganches en su marco donde puede poner más códigos para generar menús personalizados, páginas, cookies o registrar algunos eventos del usuario, etc. En cada solicitud del navegador, su marco se ejecutará y ejecutará sus códigos personalizados si está enganchado y luego lo devolverá al navegador
Entonces, la idea es bastante simple. En lugar de crear una aplicación de usuario que controle todo, primero cree un marco reutilizable que controle todo, luego escriba sus códigos personalizados y conéctelos al marco para ejecutarlos a tiempo.
Laravel y EJB son ejemplos de tales marcos.
Referencia:
Programación hablando
IoC en términos sencillos: es el uso de la interfaz como una forma de algo específico (como un campo o un parámetro) como comodín que pueden usar algunas clases. Permite la reutilización del código.
Por ejemplo, digamos que tenemos dos clases: perro y gato . Ambos comparten las mismas cualidades / estados: edad, tamaño, peso. Entonces, en lugar de crear una clase de servicio llamada DogService y CatService , puedo crear una sola llamada AnimalService que permita usar Dog y Cat solo si usan la interfaz IAnimal .
Sin embargo, pragmáticamente hablando, tiene algo al revés.
a) La mayoría de los desarrolladores no saben cómo usarlo . Por ejemplo, puedo crear una clase llamada Cliente y puedo crear automáticamente (usando las herramientas del IDE) una interfaz llamada ICustomer . Por lo tanto, no es raro encontrar una carpeta llena de clases e interfaces, sin importar si las interfaces se reutilizarán o no. Se llama BLOATED. Algunas personas podrían argumentar que "puede ser en el futuro que podamos usarlo". : - |
b) Tiene algunos límites. Por ejemplo, hablemos del caso de Dog and Cat y quiero agregar un nuevo servicio (funcionalidad) solo para perros. Digamos que quiero calcular la cantidad de días que necesito para entrenar a un perro ( trainDays()
), para el gato es inútil, los gatos no pueden ser entrenados (estoy bromeando).
b.1) Si agrego trainDays()
al Servicio AnimalService , también funciona con gatos y no es válido en absoluto.
b.2) Puedo agregar una condición en la trainDays()
que evalúa qué clase se utiliza. Pero romperá completamente el IoC.
b.3) Puedo crear una nueva clase de servicio llamada DogService solo para la nueva funcionalidad. Pero aumentará la capacidad de mantenimiento del código porque tendremos dos clases de servicio (con una funcionalidad similar) para Dog y es malo.
He leído muchas respuestas para esto, pero si alguien todavía está confundido y necesita un "término laico" más ultra para explicar IoC, aquí está mi opinión:
Imagine a un padre y un niño hablando entre ellos.
Sin IoC:
* Padre : solo puedes hablar cuando te hago preguntas y solo puedes actuar cuando te doy permiso.
Padre : Esto significa que no puedes preguntarme si puedes comer, jugar, ir al baño o incluso dormir si no te pregunto.
Padre : ¿Quieres comer?
Niño : No.
Padre : Está bien, volveré. Espérame.
Niño : (Quiere jugar pero como no hay preguntas de los padres, el niño no puede hacer nada).
Después de 1 hora...
Padre : estoy de vuelta. ¿Quieres jugar?
Niño : si.
Padre : Permiso otorgado.
Niño : (finalmente puede jugar).
Este escenario simple explica que el control está centrado en el padre. La libertad del niño está restringida y depende en gran medida de la pregunta de los padres. El niño SOLO puede hablar cuando se le pide que hable, y SOLO puede actuar cuando se le concede permiso.
Con IoC:
El niño ahora tiene la capacidad de hacer preguntas y el padre puede responder con respuestas y permisos. ¡Simplemente significa que el control está invertido! El niño ahora es libre de hacer preguntas en cualquier momento y aunque todavía existe dependencia con el padre con respecto a los permisos, no depende de los medios para hablar / hacer preguntas.
En una forma tecnológica de explicar, esto es muy similar a la interacción consola / shell / cmd vs GUI. (Cuál es la respuesta de Mark Harrison arriba de la respuesta superior n. ° 2). En la consola, depende de lo que se le pide / muestra y no puede saltar a otros menús y funciones sin responder primero a su pregunta; siguiendo un flujo secuencial estricto. (programáticamente esto es como un método / bucle de función). Sin embargo, con la GUI, los menús y las funciones se presentan y el usuario puede seleccionar lo que necesite para tener más control y estar menos restringido. (mediante programación, los menús tienen devolución de llamada cuando se seleccionan y se lleva a cabo una acción).
La inversión del control se trata de transferir el control de la biblioteca al cliente. Tiene más sentido cuando hablamos de un cliente que inyecta (pasa) un valor de función (expresión lambda) en una función de orden superior (función de biblioteca) que controla (cambia) el comportamiento de la función de biblioteca. Un cliente o marco que inyecta dependencias de la biblioteca (que portan comportamiento) en las bibliotecas también puede considerarse IoC
Como ya hay muchas respuestas para la pregunta, pero ninguna de ellas muestra el desglose del término Control de inversión, veo la oportunidad de dar una respuesta más concisa y útil.
La inversión de control es un patrón que implementa el principio de inversión de dependencia (DIP). DIP establece lo siguiente: 1. Los módulos de alto nivel no deberían depender de módulos de bajo nivel. Ambos deberían depender de abstracciones (por ejemplo, interfaces). 2. Las abstracciones no deberían depender de los detalles. Los detalles (implementaciones concretas) deben depender de abstracciones.
Hay tres tipos de inversión de control:
Los proveedores de inversión de interfaz no deberían definir una interfaz. En cambio, el consumidor debe definir la interfaz y los proveedores deben implementarla. La inversión de interfaz permite eliminar la necesidad de modificar al consumidor cada vez que se agrega un nuevo proveedor.
Inversión de flujo Cambia el control del flujo. Por ejemplo, tiene una aplicación de consola en la que solicitó ingresar muchos parámetros y después de cada parámetro ingresado se ve obligado a presionar Enter. Puede aplicar Flow Inversion aquí e implementar una aplicación de escritorio donde el usuario puede elegir la secuencia de entrada de parámetros, el usuario puede editar parámetros y, en el paso final, el usuario necesita presionar Enter solo una vez.
Creación de inversión Se puede implementar mediante los siguientes patrones: Patrón de fábrica, Localizador de servicios e Inyección de dependencias. La inversión de creación ayuda a eliminar las dependencias entre tipos que mueven el proceso de creación de objetos de dependencia fuera del tipo que usa estos objetos de dependencia. ¿Por qué las dependencias son malas? Aquí hay un par de ejemplos: la creación directa de un nuevo objeto en su código dificulta las pruebas; es imposible cambiar las referencias en ensamblajes sin recompilación (violación del principio OCP); no puede reemplazar fácilmente una interfaz de usuario de escritorio por una interfaz de usuario web.
Entonces el número 1 arriba . ¿Qué es la inversión de control?
El mantenimiento es lo primero que me resuelve. Garantiza que estoy usando interfaces para que dos clases no sean íntimas entre sí.
Al usar un contenedor como Castle Windsor, resuelve los problemas de mantenimiento aún mejor. Poder cambiar un componente que va a una base de datos por uno que usa persistencia basada en archivos sin cambiar una línea de código es increíble (cambio de configuración, ya está).
Y una vez que entras en genéricos, se pone aún mejor. Imagine tener un editor de mensajes que recibe registros y publica mensajes. No le importa lo que publica, pero necesita un mapeador para llevar algo de un registro a un mensaje.
public class MessagePublisher<RECORD,MESSAGE>
{
public MessagePublisher(IMapper<RECORD,MESSAGE> mapper,IRemoteEndpoint endPointToSendTo)
{
//setup
}
}
Lo escribí una vez, pero ahora puedo inyectar muchos tipos en este conjunto de código si publico diferentes tipos de mensajes. También puedo escribir mapeadores que toman un registro del mismo tipo y los asignan a diferentes mensajes. Usar DI con genéricos me ha dado la capacidad de escribir muy poco código para realizar muchas tareas.
Ah, sí, hay problemas de comprobabilidad, pero son secundarios a los beneficios de IoC / DI.
Definitivamente estoy amando IoC / DI.
3) Se vuelve más apropiado en el momento en que tiene un proyecto de tamaño mediano y algo más complejo. Diría que se vuelve apropiado en el momento en que empiezas a sentir dolor.
La creación de un objeto dentro de la clase se denomina acoplamiento cerrado, Spring elimina esta dependencia siguiendo un patrón de diseño (DI / IOC). En qué objeto de clase se pasa en constructor en lugar de crear en clase. Además, damos una variable de referencia de superclase en el constructor para definir una estructura más general.