Dependency Inversion

You,application patterns

Dependency Inversion is a no-brainer for fixing tight coupling issues, but why is it named "Dependency Inversion".

Instead of high-level classes depending directly on low-level ones, they depend on interfaces which the low-level classes then implement and thus the “inversion” isn’t about how you pass around the interface - it’s about flipping the usual dependency flow, making everything more flexible and easier to manage.

The key here is the dependency is being flipped from the injected interface/implementer, not the class that performing the composition.

What is Dependency Inversion?

Dependency Inversion is a principle in software design that addresses the direction of dependency within an application. It is part of the SOLID principles and aims to reduce coupling between high-level modules and low-level modules.

Key Concept:

Why is it Called Dependency Inversion?

The term "Dependency Inversion" reflects the change in dependency direction:

This inversion means that instead of high-level modules depending on low-level modules, both depend on abstractions. This inversion enhances modularity, flexibility, and testability.

Example of Dependency Inversion

Without Dependency Inversion:

public class LowLevelService
{
    public void DoWork() { /* Implementation */ }
}
 
public class HighLevelController
{
    private LowLevelService _service;
 
    public HighLevelController()
    {
        _service = new LowLevelService();
    }
 
    public void PerformAction()
    {
        _service.DoWork();
    }
}

In this example, HighLevelController directly depends on LowLevelService. This direct dependency makes HighLevelController tightly coupled to LowLevelService.

With Dependency Inversion:

public interface IService
{
    void DoWork();
}
 
public class LowLevelService : IService
{
    public void DoWork() { /* Implementation */ }
}
 
public class HighLevelController
{
    private readonly IService _service;
 
    public HighLevelController(IService service)
    {
        _service = service;
    }
 
    public void PerformAction()
    {
        _service.DoWork();
    }
}

In this refactored example:

Just don't be that person who generates interfaces anytime, everywhere and then every class has another with eyes.

© Jason Song.