Inversion of control

Last updated

In software engineering, inversion of control (IoC) is a design principle in which custom-written portions of a computer program receive the flow of control from a generic framework. The term "inversion" is historical: a software architecture with this design "inverts" control as compared to procedural programming. In procedural programming, a program's custom code calls reusable libraries to take care of generic tasks, but with inversion of control, it is the framework that calls the custom code.

Contents

Inversion of control has been widely used by application development frameworks since the rise of GUI environments [1] [2] and continues to be used both in GUI environments and in web server application frameworks. Inversion of control makes the framework extensible by the methods defined by the application programmer. [3]

Event-driven programming is often implemented using IoC so that the custom code need only be concerned with the handling of events, while the event loop and dispatch of events/messages is handled by the framework or the runtime environment. In web server application frameworks, dispatch is usually called routing, and handlers may be called endpoints.

The phrase "inversion of control" has separately also come to be used in the community of Java programmers to refer specifically to the patterns of injecting objects' dependencies that occur with "IoC containers" in Java frameworks such as the Spring framework. [4] In this different sense, "inversion of control" refers to granting the framework control over the implementations of dependencies that are used by application objects [5] rather than to the original meaning of granting the framework control flow (control over the time of execution of application code e.g. callbacks).

Overview

As an example, with traditional programming, the main function of an application might make function calls into a menu library to display a list of available commands and query the user to select one. [6] The library thus would return the chosen option as the value of the function call, and the main function uses this value to execute the associated command. This style was common in text-based interfaces. For example, an email client may show a screen with commands to load new mail, answer the current mail, create new mail, etc., and the program execution would block until the user presses a key to select a command.

With inversion of control, on the other hand, the program would be written using a software framework that knows common behavioral and graphical elements, such as windowing systems, menus, controlling the mouse, and so on. The custom code "fills in the blanks" for the framework, such as supplying a table of menu items and registering a code subroutine for each item, but it is the framework that monitors the user's actions and invokes the subroutine when a menu item is selected. In the mail client example, the framework could follow both the keyboard and mouse inputs and call the command invoked by the user by either means and at the same time monitor the network interface to find out if new messages arrive and refresh the screen when some network activity is detected. The same framework could be used as the skeleton for a spreadsheet program or a text editor. Conversely, the framework knows nothing about Web browsers, spreadsheets, or text editors; implementing their functionality takes custom code.

Inversion of control carries the strong connotation that the reusable code and the problem-specific code are developed independently even though they operate together in an application. Callbacks, schedulers, event loops, and the template method are examples of design patterns that follow the inversion of control principle, although the term is most commonly used in the context of object-oriented programming. (Dependency injection is an example of the separate, specific idea of "inverting control over the implementations of dependencies" popularised by Java frameworks.) [4]

Inversion of control is sometimes referred to as the "Hollywood Principle: Don't call us, we'll call you". [1]

Background

Inversion of control is not a new term in computer science. Martin Fowler traces the etymology of the phrase back to 1988, [7] but it is closely related to the concept of program inversion described by Michael Jackson in his Jackson Structured Programming methodology in the 1970s. [8] A bottom-up parser can be seen as an inversion of a top-down parser: in the one case, the control lies with the parser, while in the other case, it lies with the receiving application.

The term was used by Michael Mattsson in a thesis (with its original meaning of a framework calling application code instead of vice versa) [9] and was then taken from there [10] by Stefano Mazzocchi and popularized by him in 1999 in a defunct Apache Software Foundation project, Avalon, in which it referred to a parent object passing in a child object's dependencies in addition to controlling execution flow. [11] The phrase was further popularized in 2004 by Robert C. Martin and Martin Fowler, the latter of whom traces the term's origins to the 1980s. [7]

Description

In traditional programming, the flow of the business logic is determined by objects that are statically bound to one another. With inversion of control, the flow depends on the object graph that is built up during program execution. Such a dynamic flow is made possible by object interactions that are defined through abstractions. This run-time binding is achieved by mechanisms such as dependency injection or a service locator. In IoC, the code could also be linked statically during compilation, but finding the code to execute by reading its description from external configuration instead of with a direct reference in the code itself.

In dependency injection, a dependent object or module is coupled to the object it needs at run time. Which particular object will satisfy the dependency during program execution typically cannot be known at compile time using static analysis. While described in terms of object interaction here, the principle can apply to other programming methodologies besides object-oriented programming.

In order for the running program to bind objects to one another, the objects must possess compatible interfaces. For example, class A may delegate behavior to interface I which is implemented by class B; the program instantiates A and B, and then injects B into A.

Use

Example Code

HTML DOM events

Web browsers implement inversion of control for DOM events in HTML. The application developer uses document.addEventListener() to register a callback.

<!doctype html><htmllang="en"><head><metacharset="utf-8"><title>DOM Level 2</title></head><body><h1>DOM Level 2 Event handler</h1><p><large><spanid="output"></span></large></p><script>varregisteredListener=function(){document.getElementById("output").innerHTML="<large>The registered listener was called.</large>";}document.addEventListener("click",registeredListener,true);document.getElementById("output").innerHTML="<large>The event handler has been registered. If you click the page, your web browser will call the event handler.</large>"</script></body></html>

Web application frameworks

This example code for an Asp.NetCore web application creates a web application host, registers an endpoint, and then passes control to the framework: [12]

varbuilder=WebApplication.CreateBuilder(args);varapp=builder.Build();app.MapGet("/",()=>"Hello World!");app.Run();

See also

Related Research Articles

<span class="mw-page-title-main">Martin Fowler (software engineer)</span> American software developer, author and public speaker

Martin Fowler is a British software developer, author and international public speaker on software development, specialising in object-oriented analysis and design, UML, patterns, and agile software development methodologies, including extreme programming.

In computer programming, event-driven programming is a programming paradigm in which the flow of the program is determined by external events. Typical event can be UI events from mice, keyboards, touchpads and touchscreens, or external sensor inputs, or be programmatically generated from other programs or threads, or network events.

<span class="mw-page-title-main">Swing (Java)</span> Java-based GUI toolkit

Swing is a GUI widget toolkit for Java. It is part of Oracle's Java Foundation Classes (JFC) – an API for providing a graphical user interface (GUI) for Java programs.

In computer programming, a callback is a function that is stored as data and designed to be called by another function – often back to the original abstraction layer.

<span class="mw-page-title-main">Dependency injection</span> Software programming technique

In software engineering, dependency injection is a programming technique in which an object or function receives other objects or functions that it requires, as opposed to creating them internally. Dependency injection aims to separate the concerns of constructing objects and using them, leading to loosely coupled programs. The pattern ensures that an object or function that wants to use a given service should not have to know how to construct those services. Instead, the receiving 'client' is provided with its dependencies by external code, which it is not aware of. Dependency injection makes implicit dependencies explicit and helps solve the following problems:

In computer science, asynchronous I/O is a form of input/output processing that permits other processing to continue before the I/O operation has finished. A name used for asynchronous I/O in the Windows API is overlapped I/O.

<span class="mw-page-title-main">Apache Tapestry</span> Open-source web application framework

Apache Tapestry is an open-source component-oriented Java web application framework conceptually similar to JavaServer Faces and Apache Wicket. Tapestry was created by Howard Lewis Ship, and was adopted by the Apache Software Foundation as a top-level project in 2006.

A web framework (WF) or web application framework (WAF) is a software framework that is designed to support the development of web applications including web services, web resources, and web APIs. Web frameworks provide a standard way to build and deploy web applications on the World Wide Web. Web frameworks aim to automate the overhead associated with common activities performed in web development. For example, many web frameworks provide libraries for database access, templating frameworks, and session management, and they often promote code reuse. Although they often target development of dynamic web sites, they are also applicable to static websites.

In object-oriented design, the dependency inversion principle is a specific methodology for loosely coupled software modules. When following this principle, the conventional dependency relationships established from high-level, policy-setting modules to low-level, dependency modules are reversed, thus rendering high-level modules independent of the low-level module implementation details. The principle states:

The Spring Framework is an application framework and inversion of control container for the Java platform. The framework's core features can be used by any Java application, but there are extensions for building web applications on top of the Java EE platform. The framework does not impose any specific programming model.. The framework has become popular in the Java community as an addition to the Enterprise JavaBeans (EJB) model. The Spring Framework is free and open source software.

In software development, a leaky abstraction is an abstraction that leaks details that it is supposed to abstract away.

In programming and software design, an event is an action or occurrence recognized by software, often originating asynchronously from the external environment, that may be handled by the software. Computer events can be generated or triggered by the system, by the user, or in other ways. Typically, events are handled synchronously with the program flow; that is, the software may have one or more dedicated places where events are handled, frequently an event loop.

In computing, reactive programming is a declarative programming paradigm concerned with data streams and the propagation of change. With this paradigm, it is possible to express static or dynamic data streams with ease, and also communicate that an inferred dependency within the associated execution model exists, which facilitates the automatic propagation of the changed data flow.

The reactor software design pattern is an event handling strategy that can respond to many potential service requests concurrently. The pattern's key component is an event loop, running in a single thread or process, which demultiplexes incoming requests and dispatches them to the correct request handler.

The front controller software design pattern is listed in several pattern catalogs and is related to the design of web applications. It is "a controller that handles all requests for a website," which is a useful structure for web application developers to achieve flexibility and reuse without code redundancy.


The service locator pattern is a design pattern used in software development to encapsulate the processes involved in obtaining a service with a strong abstraction layer. This pattern uses a central registry known as the "service locator", which on request returns the information necessary to perform a certain task. Proponents of the pattern say the approach simplifies component-based applications where all dependencies are cleanly listed at the beginning of the whole application design, consequently making traditional dependency injection a more complex way of connecting objects. Critics of the pattern argue that it is an anti-pattern which obscures dependencies and makes software harder to test.

<span class="mw-page-title-main">ColdBox Platform</span> Web application framework

ColdBox is a free, open-source, conventions-based, modular web application framework intended for building enterprise applications with ColdFusion (CFML) using a Hierarchical MVC approach.

<span class="mw-page-title-main">Ember.js</span>

Ember.js is an open-source JavaScript web framework that utilizes a component-service pattern. It is designed with the aim of allowing developers to create scalable single-page web applications by incorporating common idioms, best practices, and patterns from other single-page-app ecosystem patterns into the framework.

Smart Pascal is a Object Pascal programming language that is derived from Delphi Web Script, its adapted for Smart Mobile Studio, commercial development JavaScript, machine code.

Whiteboard Design Pattern is an OSGi service model, which influences the OSGi framework's service registry. Whiteboard pattern came into existence because of complicated and error prone nature of traditional model: The Listener Pattern.

References

  1. 1 2 3 Sweet, Richard (25 June 1985). "The Mesa Programming Environment". ACM SIGPLAN Notices. 20 (7): 216–229. doi:10.1145/17919.806843.
  2. Visual_Basic_(classic)
  3. Johnson, Ralph E.; Foote, Brian (June–July 1988). "Designing Reusable Classes". Journal of Object-Oriented Programming. 1 (2): 22–35. CiteSeerX   10.1.1.101.8594 . Retrieved 29 April 2014.
  4. 1 2 Fowler, Martin. "Inversion of Control Containers and the Dependency Injection pattern". MartinFowler.com. Retrieved 4 June 2023.
  5. 1 2 "Spring Framework The IoC container". docs.spring.io. Retrieved 25 May 2023.
  6. Dependency Injection.
  7. 1 2 Inversion of Control on Martin Fowler's Bliki
  8. "Introduction to Jackson Design Method" (PDF).
  9. Mattsson, Michael (February 1996). "Object-Oriented Frameworks, A survey of methodological issues". Department of Computer Science, Lund University. CiteSeerX   10.1.1.36.1424 . LU-CS-TR: 96-167.
  10. Stefano Mazzocchi (22 January 2004). "On Inversion of Control". Archived from the original on 2 February 2004.
  11. "IOC Patterns - Avalon Framework". The Apache Avalon Project. Retrieved 8 June 2023.
  12. 1 2 Ryan Nowak, Kirk Larkin, Rick Anderson. ""Routing in ASP.Net Core"". learn.microsoft.com. microsoft. Retrieved 25 May 2023. Routing is responsible for matching incoming HTTP requests and dispatching those requests to the app's executable endpoints. Endpoints are the app's units of executable request-handling code. Endpoints are defined in the app and configured when the app starts.{{cite web}}: CS1 maint: multiple names: authors list (link)