What Is The Dependency Inversion Principle?
Tags: oop, solid, cleancode
Published: 2020-09-01 12:09:44

---
title: What Is The Dependency Inversion Principle?
published: true
date: 2019-04-30 00:00:00 UTC
tags: 
canonical_url: https://ellehallal.dev/blog/2019/04/2019-04-30-what-is-the-dependency-inversion-principle/
cover_image: https://dev-to-uploads.s3.amazonaws.com/i/iz1bmruzeoa8c7r2jg7h.png
tags: #oop, #SOLID, #cleancode
---

<center><h3>Originally posted at <a href="https://ellehallal.dev" target="_blank">ellehallal.dev</a>👩🏽‍💻</h3></center>

---

This is a quick blog on my understanding of the dependency inversion principle. There are still elements I am unsure about, so please feel free to leave feedback.

## What is the Dependency Inversion Principle?

> High-level modules should not depend on low-level modules. Both should depend on abstractions.Abstractions should not depend on details. Details should depend on abstractions.

_— Robert C. Martin_

That’s great, but what does it mean? 🤷🏽‍♀️ I’ll demonstrate my understanding by using a class in my [Tic Tac Toe application](https://github.com/ellehallal/ruby-tic-tac-toe) as an example.

## Dependency Inversion in Tic Tac Toe

In the application, there’s a class called `GameFactory`. The purpose of `GameFactory` is to create an instance of the `Game` class with the specified players and a board.

Here’s a condensed version of the class:

```java
class GameFactory
    def initialize(player_factory)
    @player_factory = player_factory
    end

    def new_game(squares)
    board = Board.new(squares)
    player1 = @player_factory.create_player('x', 1)
    player2 = @player_factory.create_player('o', 2)
    Game.new(board, player1, player2)
    end
end
```

In the `new_game` method, new instances of the `Board` and `Game` classes are created within it. However, this violates the Dependency Inversion Principle.

### What’s wrong with it?

The high-level class `GameFactory` is dependent on the low level classes `Board` and `Game`. As a result, they are tightly coupled. A change in a low-level class will affect the high-level class.

If the name of the `Board` or `Game` class was changed, the `new_game` method within `GameFactory` wouldn’t work. As a result, it would need to be amended to accommodate the renamed classes.

If sub classes of `Board` and `Game` were to be used to create a new game, (for example, `BestBoard` and `FunGame`) the `new_game` method would need to be changed again to accommodate this.

A method to resolve the above issues is to pass the classes into `GameFactory`'s constructor:

```java
class GameFactory
    def initialize(player_factory, board, game)
    @player_factory = player_factory
    @board = board
    @game = game
    end

    def new_game(squares)
    board = @board.new(squares)
    player1 = @player_factory.create_player('x', 1)
    player2 = @player_factory.create_player('o', 2)
    @game.new(board, player1, player2)
    end
end
```

Whatever is passed in as board and game during initialisation, becomes `@board` and `@game` within `GameFactory.`

If the names of the `Board` and `Game` classes were to change, initialising `GameFactory` with the renamed classes would not affect `GameFactory`.

If subclasses of `Board` and `Game` (for example, `BestBoard` and `FunGame`) were used to initialise an instance of `GameFactory`, this would not affect how `new_game` functions.

In conclusion, my understanding is initialising a specific class, or classes within another results in tight coupling. Being able to inject the classes via the constructor, helps to make the classes loosely coupled.

* * *

## Resources

- [Dependency Inversion Principle in Ruby](http://www.getlaura.com/dependency-inversion-principle-in-ruby/)[SOLID Principles #5 - Dependency Inversion Principle](https://www.netguru.com/codestories/solid-5-dip)