Software Design Principle: Inversion of Control(IOC) and Dependency Injection
Tags: java, angular, software, ai
Published: 2024-04-26 09:51:29

---
title: Software Design Principle: Inversion of Control(IOC) and Dependency Injection
published: true
description: Eight Electrical Metric Meters
tags: java, angular, software, AI
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j8zw994os57apjvwdyo0.jpg
# Use a ratio of 100:42 for best results.
# published_at: 2024-04-15 07:50 +0000
---

Software engineering is an established discipline within the broader field of Computer Science. It is a discipline that has made great strides and impressive breakthroughs. Strides relating to powering spacecraft, advances in computer hardware, creating billion-dollar products and platforms, and more recently breakthroughs in AI. 

It has also granted individuals skilled in the software-making craft a means to taste freedom from remote work, make a global impact, experience great career opportunities, and more. 

Coming into software, some things we hear a lot are the sayings: "Do not reinvent the wheel" and "Standing on the shoulders of giants". These sayings aren't mere statements, they are enduring principles that have stood the test of time. 

Software engineering has numerous principles that help make your code maintainable and easy to test. Some popular ones include Separation of Concerns, KISS, SOLID, and Design Patterns. There are also less popular ones and controversial ones as well. Some are now being regarded as bad practices. Though there are a lot, the rest of this article will zoom in on the **Inversion of Control**, one of the popular ones.


## Inversion of Control

**Inversion of Control** is a software engineering principle that discourages a Developer from creating the object and dependencies his program needs to run directly. Rather he outsources it to a framework or an external entity. Inversion of control (IoC) is where control is inverted, rather than the programmer controls the flow of the program, the framework takes control instead.

In procedural programming, a program's custom code calls reusable libraries to take care of generic tasks, but with inversion of control, it is a framework that calls the custom code. The principle is popular with Java's Spring framework and Javascript's Angular. 

## Dependency Injection
**Dependency Injection** is related to the Inversion of Control in the sense that it is the pattern through which Inversion of Control is achieved. In DI, instead of a `Class` creating its dependencies, the dependencies are provided to the class from the outside. This helps to decouple **classes** and make them more testable, maintainable, and flexible.

There are three common types of dependency injection:

1.**Constructor Injection**: Dependencies are provided to a class through its constructor. It is the most common form of DI and ensures a **Class** has all its dependencies when created.
```java
public class MyClass {
    private final MyDependency dependency;

    public MyClass(MyDependency dependency) {
        this.dependency = dependency;
    }

    // Class methods using the dependency
}
``` 

2.**Setter Injection**: Dependencies are provided to a class through setter methods. This allows for more flexibility, as dependencies can be changed after the class is created.
```java
public class MyClass {
    private MyDependency dependency;

    public void setDependency(MyDependency dependency) {
        this.dependency = dependency;
    }

    // Class methods using the dependency
}
```

3.**Method Injection**: Dependencies are provided to individual methods when called. This is less common than constructor or setter injection and is often used in specific cases.
```java
public class MyClass {
    public void doSomething(MyDependency dependency) {
        // Method logic using the dependency
    }
}
```
This is also the case in Javascript's Angular, DI is a core concept used to provide services, components, and other objects to classes that need them. Angular's DI system is built into the framework and is used extensively throughout Angular applications. Below is a simple example to demonstrate how dependency injection works in Angular:

First, we create a service that we'd like to inject into a component:

```ts
// my.service.ts
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class MyService {
  getMessage(): string {
    return 'Hello from MyService!';
  }
}
```
Next, we create a component that will consume the service:
```ts
// my.component.ts
import { Component } from '@angular/core';
import { MyService } from './my.service';

@Component({
  selector: 'app-my',
  template: `
    <h1>{{ message }}</h1>
  `,
})
export class MyComponent {
  message: string;

  constructor(private myService: MyService) {
    this.message = this.myService.getMessage();
  }
}
```
In the above code, the `MyComponent` class has a `constructor` parameter of type `MyService`. Angular's DI system will automatically inject an instance of `MyService` into the `MyComponent` class when created.

Finally, we add `MyService` and `MyComponent` to the list of providers in the Angular module:

```ts
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { MyComponent } from './my.component';
import { MyService } from './my.service';

@NgModule({
  declarations: [MyComponent],
  imports: [BrowserModule],
  providers: [MyService],
  bootstrap: [MyComponent],
})
export class AppModule {}
```
In this example, `MyService` is provided at the root level, meaning a single instance of `MyService` is shared across the entire application. This allows flexibility in making future changes as the components are loosely coupled.

## Some Advantages
1. There is loose coupling between components 
2. You can easily change dependencies without compromising on quality.
3. You can leverage code usability and achieve System stability.
4. Minimal code to maintain.
5. You can easily replace components without affecting others.

## Conclusion
In conclusion, we discussed **SE** principles and why they are necessary. We focused on **IoC** and **DI**, a design pattern through which **IoC** is achieved. We also mentioned the different types of DI using code samples where appropriate. We mentioned some advantages of IoC and DI. Finally, **DI** is a powerful design pattern that makes managing complex dependencies in large applications easier.

Thanks for reading, you can follow me on [LinkedIn](https://www.linkedin.com/in/ridwan-abiola/)