Inverse of Control

High level modules should not depend upon low level modules. Both should depend upon abstractions.

As the statement suggest dependencies should be architectural flow from high level models to low level models. But in some of the application the flow will be typically be that high level module is dependant on what low level module behavior/code.

This is highly discouraged and the dependencies are to be swapped. Hence this dependence inverting is achieved through Inverse of Control. Now adays Inverse of Control is used in large enterprise application while avoiding tight coupling.

Inverse of Control

Simply Inverse of Control is such method to handle decoupling described. Here consider following example:

Pseudo code with tight coupling

In this example apiController simply creates the instance of MySQLConnection and use it to access the database. Simply apiController depends on concrete implementation of MySQLConncetion. Contrary to Dependency Inversion, here high level module is dependent on low level module and is coupled with concrete implementation.

What if MySQLConnection implementation is altered? Wouldn’t apiController be affected as well? Huge mess is created such that with this tight coupling.

What if MySQLConnection is singleton implementation. apiController would be handling only available instance. Here if another apiController2 want to use MySQLConnection, it would just have to wait for apiController. There is no session management and single point failure at instance creation. (This is actually the reason that singleton is often considered as an anti-pattern)

Here comes the savior: Inverse of Control

UML diagram of decoupling

In the code, apiController simply depends on the abstraction not the implementation. It would rely on IDatabaseConnection abstraction rather than concrete implementation of MySQLConnection. Here IDatabaseConnection is equipped with all necessary method signatures all implementations such satisfy, either MySQLConnection or MongoDBConnection.

Here if MongoDBConnection is passed instead of MySQLConnection, there wouldn’t be much change in apiController since it’s dependent on any kind of IDatabaseConnection.

Another important thing to notice here is that apiController doesn’t actually know the type of concrete implementation but rather received through the constructor. In IoC this is known as: Hollywood Principle as in:

Don’t call us, we’ll call you

As conveying buy this quote apiController would just wait for an implementation of IDatabaseConnection to be inherited through constructor rather than checking or creating instance. This is simply Inverse of Control where control is not with apiController anymore, but its rather waiting. Waiting for implementation is even through constructors or set. Managing and injecting of concrete implementation of needed abstractions are simply done by IoC containers.

IoC containers will be responsible for managing initiating concrete implementations, injecting/setting to needed abstraction type & managing sessions.

There are multiple ways to achieve Inverse of Control, but primarily Dependency Injection and Service Locator. We will be focusing more on DI here.

Dependency Injection

Dependency Injection (DI) is a way of achieving Inverse of Control (IoC). As shown in above code apiController is expecting IDatabaseConnection typed instance to be passed through the constructor. This dependency of is fulfilled by injecting instance of type IDatabaseConnection. This injecting part is handled by 3rd party and isn’t handled in apiController,MySQLConnection nor in IDatabaseConnection.

This DI implementation was evident in AngularJS 1.x since this had in built DI implemented.

AngularJS 1.x Controller

Here CalcService is registered as follows. This is injected to needed dependencies with in built DI.

AngularJS 1.x Service

Here myController have a dependency on CalcService and it’s being given through constructor. It’s called as constructor injection.

Another way of DI is through set method rather than through constructor. It is called property injection. The class is initiated without the dependency and dependency is passed through set property lately.

Service Locator

Service Locator pattern is also considered as possible solution for achieving IoC. Here central class known as ‘service locator’ will be used and all the controllers will typically be dependent of this central class, which is somewhat tight coupling.

Moreover this is considered as an anti-pattern by many experts and will not be discussed in this article.

IoC container and DI

IoC containers are the easiest way to implement DI & manage dependencies. The IoC container will create objects for dependency, manage complete life cycle of these created objects from creation to destruction.

Considering .NET eco-system there are notable IoC containers such as Autofac, Ninject. However considering ASP.NET Core or .NET Core, it’s equipped with in-built IoC container to manage dependencies with DI.

ASP.NET Core : Startup.cs

By simply registering dependency in Startup.cs in ASP.NET Core MVC with in-built IoC container, dependencies will be managed accordingly. (Look into my article ‘Introduction to .NET Core’ for the basics)

Whenever there is a dependency on IDatabaseConnection, IoC container will provide with MySQLConnection. Any controller such as apiController in above examples will just be injected with concrete implementation regardless of number of controllers.

Moreover what if we want to switch from MySQL to MongoDB. It’s just simple as replacing previous with above commented out line. What’s cool here is that you wouldn’t have to change any controller code since they are dependent only on abstraction. The controller code would notice any change in data storage if all goes well.

When registering abstraction (Ex: IDatabaseConnection) with concrete implementation (Ex: MySQLConnection) there can be different ways according to behavior. Few examples as in .NET Core IoC container are .AddTransient, .AddSingleton, .AddInstance and some more.

Simply if some concrete implementation is required to act as singleton just register as .AddSingleton. This would avoid creating singleton concrete implementation which is considered as an anti pattern. Here IoC container will be responsible in managing singleton instance and its session. So this would rule out the possibility of some controller holding on to the singleton instance and starving all other controllers due to code mistake or failure. IoC container will manage singleton instead without handing control to each controllers.

Inverse of Control with Dependency Injection provides efficient way to manage dependencies in large enterprise applications. Here as shown in the examples it is clearly seen that dependencies are easily inverted and manageable this way.

So I believe you got idea about IoC and DI through this article, and comment for any clarification.

Full Stack Developer | BiBi

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store