Dependency Injection for Games — Appendix: Dependency Inversion
Tags: gamedev, architecture, cpp, tutorial
Published: 2023-09-11 11:50:11


In the main [Dependency Injection for Games](https://dev.to/filippoceffa/dependency-injection-for-games-4dhb) article, we used a dummy game application as an example to explain how **Dependency Injection** can help you organize your **game** or **game engine** architecture.

For the sake of simplicity, the example intentionally omitted a technique commonly adopted in real-world applications: **Dependency Inversion**.

The goal of this appendix is to expand our problem to include Dependency Inversion, and prove that Dependency Injection remains the ideal solution.

We will start by introducing Dependency Inversion through a **practical example**, by modifying our dummy game application to make use of it.

## Problem (re)definition

First, let’s recap the dependency graph of our dummy game application:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/zht9t50o6clxldhvhq1u.jpg)

Rendering uses the `OpenGL` graphics API, but as the requirements of our project grow, we may want `Rendering` to work with multiple graphics APIs. The following scenarios are common:

* We wish `Rendering` to support both `Vulkan` and `OpenGL`, and select the appropriate API at runtime, based on a command-line argument.

* We wish to test `Rendering` using a `Mock` graphics API, in order to make test results independent of graphics API details.

We can provide this flexibility by making `Rendering` depend on the `IGraphics` interface, and make `OpenGL`, `Vulkan` and `Mock` implement it:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/w106jnfrfzsx118hbguh.jpg)

This solution follows the **Dependency Inversion** principle, which states that systems should depend on interfaces instead of implementations:


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r22oq2o1jkbw28u6b19p.jpg)

The introduction of Dependency Inversion slightly changes the nature of our problem — we are not dealing anymore with a dependency graph of systems, but with a **dependency graph of systems and interfaces**.

In the next section we will see how Dependency Injection comfortably supports these new requirements, and remains the ideal solution to organize your game architecture.

## Problem solution

Dependency Inversion shields a system from the implementation details of its dependencies, including their **constructors**.

Consequently, when adopting Dependency Inversion, a system cannot be responsible for creating its own dependencies. They must be created somewhere else, and shared with the system through their interface.

An application that adopts **Dependency Injection** creates all systems in `main()`, and forwards them to their dependent systems. This provides the perfect framework to support Dependency Inversion:
```c++
int main()
{
    OpenGL openGL{};             // dependency created outside system
    Rendering rendering{openGL}; // dependency passed to system
}
```
The only step necessary to adopt Dependency Inversion is to change a system’s dependency from a concrete implementation to an interface:
```c++
class OpenGL : IGraphics {...};

Rendering::Rendering(OpenGL&){}    // Injection, but not Inversion
Rendering::Rendering(IGraphics&){} // Injection and Inversion
```
## Conclusions

Dependency Injection can effortlessly support Dependency Inversion.

Dependency Inversion is a powerful tool in your toolbox — it has **benefits** in modularity and testability, and it has **drawbacks** in complexity and performance. Like every tool, it should be used when appropriate.

Dependency Injection grants you full control in deciding if and where to adopt Dependency Inversion, allowing you to design your game or game engine architecture in complete flexibility.

## Next steps

* Check out the accompanying [**GitHub repository**](https://github.com/Ceffa93/dependency_injection_for_games), which contains an **implementation** of the dummy game application.

* If you haven’t yet, read the appendix on [**Injection Container**](https://dev.to/filippoceffa/dependency-injection-for-games-appendix-injection-container-5ebd).