Understanding Inversion of Control (IoC)

Understanding Inversion of Control (IoC)

In my previous post, we had a look at Dependency Injection. That is a kind of inversion of control, but what is Inversion of Control exactly?

sugarloaf.jfif The band Sugarloaf. What are they doing here?! Read on, young grasshopper.

In this post, I will

  • define what IoC is
  • explain why we need it
  • provide some examples from the wild

What is Inversion of Control?

The term suggests that there is a flow of control that is inverted. We therefore expect one flow of control context that gets altered to invert the flow of control within another context. Fair enough, so how does this work?

In Martin Fowler's blog post on IoC, he contrasts the flow of control between a command line context, and a windowing toolkit context.

In the beginning was the command line

With a read-eval-print-loop (REPL) situation, the problem exists in the chair, not in the computer. The flow of control is entirely within the control of the user. I'm convinced that users are always capable, competent, confident and successful when it comes to working with computers, so there is nothing wrong with giving users root access and a terminal and letting them shoot their own legs off with glee.

Or maybe this situation isn't always ideal and sometimes users need to hand control over to some other part of the code, sometimes with a visual aid.

And then there were GUIs

doomer.jpg This doomer hates GUIs. But sometimes, they are a necessary evil.

In a windowing toolkit context, the user usually hands over control to a generic part of code. This generic code can then be customised depending on the context. Is this a Windows machine? Bind it to Windows toolkits. Is this a Linux machine? Let's see what windowing toolkits are available to handle the user's input.

That's fair enough as a contrasting example, but it still doesn't capture what is going on to me. Armed with nothing but a terminal and a GUI, we hop, skip and jump to:

The Hollywood Principle: Don't call us, we'll call you!

This makes it slightly more clear, strangely enough.

  • In the terminal context, the user is calling commands directly. The user is in control of the flow
  • In the GUI context, control is handed over to the GUI and it calls back when it is ready. The user is not directly in control of the flow, as the GUI does some bindings and deep magic before it calls back to the user

An old hippie band called Sugarloaf also has a song called Don't call us, we'll call you. Groovy, baby.

Why do we need IoC?

  • To decouple the execution of a task from implementation
  • To ensure that a module has a single responsibility, to focus a module on the task it is designed for
  • To free modules from assumptions about how other systems do what they do and instead rely on contracts - that is programming to an interface, not to an implementation
  • To prevent side effects that may occur when replacing a module

Examples from the wild - show me some code!

There is a myriad of IoC containers out there. I will only list two, from my further reading section:

Summary

In this post, I went over the basics of IoC. I provided a working definition, and I went over Martin Fowler's examples. Next, I went over the purpose of IoC to point out why it is necessary. Then I linked to some examples of IoC in the wild. Lastly, there's a further reading section for the curious.

Further reading