Dependency Inversion

You,application patterns

Dependency Inversion is a no-brainer for fixing tight coupling issues, but why is it named "Dependency Inversion" and not just "the better way to do abstraction" TM Pending?

The twist is that 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. This is a summary for you that definitely wasn't created by chat-gippity or related AI summarisation tools.

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 "just because SOLID".

© Jason Song.