Articulo de referencia

Inversión del control

En el diseño de software , la inversión de control ( IoC ) es un principio de diseño en el que las partes personalizadas de un programa informático reciben el control de una fue...

En el diseño de software , la inversión de control ( IoC ) es un principio de diseño en el que las partes personalizadas de un programa informático reciben el control de una fuente externa (por ejemplo, un framework ). El término "inversión" es histórico: una arquitectura de software con este diseño "invierte" el control en comparación con la programación procedimental . En la programación procedimental, el código personalizado de un programa llama a bibliotecas reutilizables para realizar tareas genéricas, pero con la inversión de control, es el código externo o el framework el que controla y llama al código personalizado.

La inversión de control ha sido ampliamente utilizada por los marcos de desarrollo de aplicaciones desde el auge de los entornos GUI [ 1 ] [ 2 ] y continúa utilizándose tanto en entornos GUI como en marcos de aplicaciones de servidor web . La inversión de control hace que el marco sea extensible mediante los métodos definidos por el programador de la aplicación. [ 3 ]

La programación orientada a eventos se implementa a menudo mediante IoC (Inversión de Control), de modo que el código personalizado solo necesita ocuparse del manejo de eventos, mientras que el entorno de ejecución o el bucle de eventos se encargan del envío de eventos/mensajes. En los entornos de aplicaciones de servidor web, el envío se suele denominar enrutamiento, y los manejadores pueden denominarse puntos finales.

Significado alternativo

La frase "inversión de control" también se ha utilizado en la comunidad de programadores Java para referirse específicamente a los patrones de inyección de dependencias (pasar servicios a los objetos que los necesitan) que ocurren con los "contenedores IoC" en los frameworks Java como Spring Framework . [ 4 ] En este sentido diferente, "inversión de control" se refiere a otorgar al framework el control sobre las implementaciones de las dependencias que utilizan los objetos de la aplicación [ 5 ] en lugar del significado original de otorgar al framework el control del flujo (control sobre el tiempo de ejecución del código de la aplicación, por ejemplo, las devoluciones de llamada).

Descripción general

Por ejemplo, en la programación tradicional, la función principal de una aplicación podría realizar llamadas a una biblioteca de menús para mostrar una lista de comandos disponibles y solicitar al usuario que seleccione uno. [ 6 ] La biblioteca devolvería la opción elegida como valor de la llamada a la función, y la función principal usaría este valor para ejecutar el comando asociado. Este estilo era común en las interfaces basadas en texto . Por ejemplo, un cliente de correo electrónico podría mostrar una pantalla con comandos para cargar correo nuevo, responder al correo actual, crear un nuevo correo, etc., y la ejecución del programa se bloquearía hasta que el usuario presionara una tecla para seleccionar un comando.

Por otro lado, con la inversión de control, el programa se escribiría utilizando un marco de software que conoce elementos gráficos y de comportamiento comunes, como sistemas de ventanas , menús, control del ratón y barras de herramientas. El código personalizado "completa los huecos" para el marco, como proporcionar una tabla de elementos de menú y registrar una subrutina de código para cada elemento, pero es el marco el que supervisa las acciones del usuario e invoca la subrutina cuando se selecciona un elemento del menú. En el ejemplo del cliente de correo, el marco podría seguir tanto las entradas del teclado como del ratón y llamar al comando invocado por el usuario por cualquiera de los dos medios, y al mismo tiempo supervisar la interfaz de red para detectar la llegada de nuevos mensajes y actualizar la pantalla cuando se detecte alguna actividad de red. El mismo marco podría utilizarse como esqueleto para un programa de hoja de cálculo o un editor de texto. Por el contrario, el marco no sabe nada sobre navegadores web, hojas de cálculo o editores de texto; implementar su funcionalidad requiere código personalizado.

La inversión de control conlleva la fuerte connotación de que el código reutilizable y el código específico del problema se desarrollan de forma independiente, aunque operen juntos en una aplicación. Las funciones de devolución de llamada , los planificadores , los bucles de eventos y el método de plantilla son ejemplos de patrones de diseño que siguen el principio de inversión de control, si bien el término se utiliza con mayor frecuencia en el contexto de la programación orientada a objetos . ( La inyección de dependencias es un ejemplo de la idea específica e independiente de "invertir el control sobre las implementaciones de dependencias", popularizada por los frameworks de Java). [ 4 ]

La inversión de control a veces se denomina "Principio de Hollywood: No nos llames, nosotros te llamaremos", lo que refleja cómo los marcos de trabajo dictan el flujo de ejecución. [ 1 ]

Fondo

La etimología de la frase se remonta a 1988, [ 7 ] pero está estrechamente relacionada con el concepto de inversión de programa descrito por Michael Jackson en su metodología de Programación Estructurada de Jackson en la década de 1970. [ 8 ] Un analizador sintáctico ascendente puede verse como una inversión de un analizador sintáctico descendente : en un caso, el control reside en el analizador sintáctico, mientras que en el otro caso, reside en la aplicación receptora.

El término fue utilizado por Michael Mattsson en una tesis (con su significado original de un marco de trabajo que llama al código de la aplicación en lugar de viceversa) [ 9 ] y luego fue tomado de allí [ 10 ] por Stefano Mazzocchi y popularizado por él en 1999 en un proyecto desaparecido de la Apache Software Foundation, Avalon, en el que se refería a un objeto padre que pasa las dependencias de un objeto hijo además de controlar el flujo de ejecución. [ 11 ] La frase fue popularizada aún más en 2004 por Robert C. Martin y Martin Fowler , este último de los cuales remonta los orígenes del término a la década de 1980. [ 7 ]

Descripción

En la programación tradicional, el flujo de la lógica de negocio está determinado por objetos vinculados estáticamente entre sí. Con la inversión de control, el flujo depende del grafo de objetos que se construye durante la ejecución del programa. Este flujo dinámico es posible gracias a las interacciones entre objetos definidas mediante abstracciones. Esta vinculación en tiempo de ejecución se logra mediante mecanismos como la inyección de dependencias o un localizador de servicios . En IoC, el código también puede vincularse estáticamente durante la compilación, pero se encuentra el código a ejecutar leyendo su descripción desde una configuración externa en lugar de mediante una referencia directa en el propio código.

En la inyección de dependencias, un objeto o módulo dependiente se acopla al objeto que necesita en tiempo de ejecución . Normalmente, no es posible determinar en tiempo de compilación , mediante análisis estático , qué objeto específico satisfará la dependencia durante la ejecución del programa . Si bien aquí se describe en términos de interacción entre objetos, este principio puede aplicarse a otras metodologías de programación además de la programación orientada a objetos .

Para que el programa en ejecución pueda vincular objetos entre sí, los objetos deben poseer interfaces compatibles . Por ejemplo, una clase Apuede delegar comportamiento a una interfaz Iimplementada por otra clase B; el programa instancia Ay B, y luego inyecta Ben otra clase A.

Usar

Código de ejemplo

Infraestructura del marco

Este es un ejemplo de infraestructura de framework en Java , que define el ciclo de vida y ejecuta el bucle de ejecución.

import java.util.ArrayList ; import java.util.List ;interface PluginCommand { void execute (); }clase ApplicationEngine { private final List < PluginCommand > plugins ;private ApplicationEngine ( Builder builder ) { this . plugins = new ArrayList <> ( builder . plugins ); }public void run () { for ( PluginCommand plugin : plugins ) { plugin . execute (); } }public static class Builder { private final List < PluginCommand > plugins = new ArrayList <> ();public Builder registerPlugin ( PluginCommand plugin ) { this . plugins . add ( plugin ); return this ; }public ApplicationEngine build () { return new ApplicationEngine ( this ); } } }

Este es el código de la aplicación en sí, el cual está controlado.

class DatabaseBackupPlugin implements PluginCommand { @Override public void execute () { System . out . println ( " -> [Código personalizado] DatabaseBackupPlugin: Exportando volcado SQL..." ); } }class EmailNotificationPlugin implements PluginCommand { @Override public void execute () { System . out . println ( " -> [Código personalizado] EmailNotificationPlugin: Enviando correo electrónico de estado del sistema..." ); } }

Entonces, esto se ejecuta de la siguiente manera:

ApplicationEngine engine = new ApplicationEngine . Builder () . registerPlugin ( new DatabaseBackupPlugin ()) . registerPlugin ( new EmailNotificationPlugin ()) . build ();motor.ejecutar ( ) ;

Eventos DOM de HTML

Los navegadores web implementan la inversión de control para los eventos DOM en HTML. El desarrollador de la aplicación utiliza esto document.addEventListener()para registrar una función de devolución de llamada.

<!doctype html> < html lang = "en" > < head > < meta charset = "utf-8" > < title > DOM Nivel 2 </ title > </ head > < body > < h1 > Controlador de eventos DOM Nivel 2 </ h1 > < div id = "output" ></ div ><script> var listener = function ( ) { document.getElementById ( "output" ) . innerHTML = " <p> Se llamó al oyente registrado.</p>" ; } document.addEventListener ( " click" , listener , true );document.getElementById ( "output" ) . innerHTML = " <p> El controlador de eventos se ha registrado . Si hace clic en la página, su navegador web llamará al controlador de eventos.</p> " </script> </body> </html>

marcos de aplicaciones web

Este código de ejemplo para una aplicación web ASP.NET Core crea un host de aplicación web, registra un punto final y luego pasa el control al marco: [ 12 ]

usando Microsoft.AspNetCore.Builder ;WebApplicationBuilder builder = WebApplication.CreateBuilder ( args ); WebApplication app = builder.Build ( ) ; app.MapGet ( " /" , () = > " Hello World!" ) ; app.Run ( ) ;

Véase también

Referencias

  1. 1 2 3 Sweet, Richard (25 de junio de 1985). "El entorno de programación Mesa" . ACM SIGPLAN Notices . 20 (7): 216– 229. doi : 10.1145/17919.806843 .
  2. Visual Basic (clásico)
  3. Johnson, Ralph E.; Foote, Brian (junio-julio de 1988). "Diseño de clases reutilizables" . Journal of Object-Oriented Programming . 1 (2): 22– 35. CiteSeerX 10.1.1.101.8594 . Recuperado el 29 de abril de 2014 . 
  4. 1 2 Fowler, Martin. "Inversión de control: contenedores y el patrón de inyección de dependencias" . MartinFowler.com . Consultado el 4 de junio de 2023 .
  5. 1 2 "Spring Framework El contenedor IoC" . docs.spring.io . Consultado el 25 de mayo de 2023 .
  6. Inyección de dependencias .
  7. 1 2 Inversión de control en Bliki de Martin Fowler
  8. "Introducción al método de diseño Jackson" (PDF) .
  9. ^ Mattsson, Michael (febrero de 1996). "Marcos orientados a objetos, un estudio de cuestiones metodológicas" . Departamento de Ciencias de la Computación, Universidad de Lund. CiteSeerX 10.1.1.36.1424 . LU-CS-TR: 96-167. 
  10. Stefano Mazzocchi (22 de enero de 2004). "Sobre la inversión de control" . Archivado del original el 2 de febrero de 2004.
  11. "Patrones IOC - Marco Avalon" . El proyecto Apache Avalon . Consultado el 8 de junio de 2023 .
  12. 1 2 Ryan Nowak, Kirk Larkin, Rick Anderson ."Enrutamiento en ASP.Net Core"" . learn.microsoft.com . microsoft . Consultado el 25 de mayo de 2023 . El enrutamiento se encarga de hacer coincidir las solicitudes HTTP entrantes y distribuirlas a los puntos finales ejecutables de la aplicación. Los puntos finales son las unidades de código ejecutable de la aplicación para el manejo de solicitudes. Los puntos finales se definen en la aplicación y se configuran cuando esta se inicia.{{cite web}}: CS1 maint: varios nombres: lista de autores ( enlace )
  • Explicación e implementación de la inversión de control. Ejemplo práctico.
  • Inversión de control