HomeAbout

IoC and Container

Context

Inversify is a lightweight inversion of control (IoC) container.

IoC Container

IoC container uses a class constructor to identify and inject its dependencies.

What is Dependency

When you need another piece of code to run the current code.

A relies on B to work

class A uses methods from class B = class A is dependent of class B

class A needs to have instance or copy of B inside of A to work

What is Common dependency

  • User model needs to talk to a database
    • Database used in User model is MySQL
      • persist method is called to store data into MySQL

User model needs Database's persist method.

// before inversion public class User { MySqlDatabase database; public User() { database = new MySqlDatabase(); } public void() add(String data) { database.persist(data); } }

Inversion of Control (IoC)

IoC is flipping of dependency.

  • It's inverse in regards to procedural programming flow of control.

Instead of defining the type of database used in the User class directly as concrete implementation, you instantiate the User class and pass a Database type to it.

  • More precisely - Database type to be implemented as part of User.
// previously user = container.new User(); public class User { database = MySqlDatabase(); } // dependency inversion user = container.new User(MySql()); public class User { this.database = database }

What did this inversion accomplish

Allows more abstraction over concrete implementation

  • loosely coupled architecture, plug-ability, flexibility
  • allows for handling of things like changing parameter or database types from specific implementation

Benefit - Not solidifying concrete implementation choice now which will become harder to rip out or change when the codebase grows large and requirements change

Injection

Injection is when you pass something into the code instead of reference/using it directly.

  • you inject a code you need into another code

Passing the concrete decision as a parameter

Remove direct dependencies between components by injecting their dependencies from external sources

// Using Constructor class UserService { constructor(database) { this.database = database; } // ... } const database = new Database(); const userService = new UserService(database);

Why does IoC use interfaces?

The concrete implementations of the interfaces are not meant to be exported from the projects, which means they are not available to clients, and you have to use the interface.

This decouples our function implementations from the interfaces, and allows us to maintain the functions and different implementations without affecting the interface footprint in the rest of the system.

Callsites become a million times easier to maintain, and teams can refactor their internal project code without worrying about where and how the concrete function implementations are defined.

Can also use setter

Illustration skipped as it is not a recommended pattern.

AboutContact