The truth behind Inversion of Control – Part IV – Dependency Inversion Principle

The Dependency Inversion Principle is part of the SOLID principles. If you want a formal definition of DIP, please read the articles written by Martin[1] and Schuchert[2].

We explained that, in order to invert the control of the flow, our specialized code must never call directly methods of more abstracted classes. The methods of the classes of our framework are not explicitly used, but it is the framework to control the flow of our less abstracted code. This is also called (sarcastically) the Hollywood principle, stated as “don’t call us, we’ll call you.”.

Although the framework code must take control of less abstracted code, it would not make any sense to couple our framework with less abstracted implementations. A generic framework doesn’t have the faintest idea of what our game needs to do and, therefore, wouldn’t understand anything declared outside its scope.

Hence, the only way our framework can use objects defined in the game layer, is through the use of interfaces, but this is not enough. The framework cannot know interfaces defined in a less abstracted layer of our application, this would not make any sense as well.

The Dependency Inversion Principle introduces a new rule: our less abstracted objects must implement interfaces declared in the higher abstracted layers. In other words, the framework layer defines the interfaces that the game entities must implement .

In a practical example, RendererSystem handles a list of IRendering “Nodes”. The IRendering node is an interface that declares, as properties, all the components needed to render the Entities, such as GetWorldMatrix, GetMaterial and so on. Both the RendererSystem class and the IRendering interface are declared inside the framework layer. Our specialised code needs to implement IRendering in order to be usable by the framework.


Designing layered code

So far I used the word “framework” to identify the most abstracted code and “game” to identify the least abstracted code. However framework and game don’t mean much. Limiting our layers to just “the game layer” and “the framework layer” would be a mistake. Let’s say we have systems that handle very generic problems that can be found in every game, like the rendering of the entities, and we want to enclose this layer in to a namespace. We have defined a layer that can be even compiled in a DLL and be shipped with whatever game.

Now, let’s say we have to implement the logic that is closer to the game domain. Let’s say that we want to create a HealthSystem that handles the health of the game entities with health. Is HealthSystem part of a very generic framework? Surely not. However while HealthSystem will handle the common logic of the IHaveHealth entities, not all the game entities will have the same behaviors. Hence HealthSystem is more abstracted than more specialized behavior implementations. While this abstraction wouldn’t probably justify the creation of another framework, I believe that thinking in terms of layered code helps designing better systems and nodes.


Putting ECS, IoC and DIP all together

As we have seen, the flow is not inverted when, in order to find a solution, a bottom up design approach is used to break down the problem, that is when the specialized behaviors of the entities are modeled before the generic ones. Or also when the systems are designed as result of the specialized entity problems.

In my vision of Inversion of Control, it’s needed to break down the solutions using a top down approach. We should think of the problems starting from the most abstracted classes. What are the common behaviors of the game entities? What are the most abstracted systems we should write? What once would have been solved specializing classes through inheritance, it should be now solved layering our systems within different levels of code abstraction and declaring the relative interfaces to be used by the less abstracted code. Generic systems should be written before the specialized ones.

I believe that in this way we could benefit from the following:

  • We will be sure that our systems will have just one responsibility, modeling just one behavior
  • We will basically never break the Open/Close principle, since new behaviors means creating new systems
  • We will inject way less dependencies, avoiding using a IoC container as a Singleton alternative
  • It will be simpler to write reusable code
  • We could potentially achieve real encapsulation

In the next article I will explain how I would put all these concepts together in practice

References:

  1. http://www.objectmentor.com/resources/articles/dip.pdf
  2. http://martinfowler.com/articles/dipInTheWild.html

I strongly suggest to read all my articles on the topic:

7 thoughts on “The truth behind Inversion of Control – Part IV – Dependency Inversion Principle

      1. If there’s any way I could help, I’ll gladly spare some time. I’m preparing a “Best practices in Unity” small training in our company for the games department soon and part of it is inspired by your posts.

  1. I’m reading a lot about game architects in Unity lately and this series are really good. I’m have a really good experience using IoC and MVC in other projects, but I feel that MVC play really great on UI based apps but not in games (simulations at the end of the day), and the other way around with ECS. I really will like to see the next post. IMHO a combination of both systems, using MVC for the UI bit (popups, handling complex UI components, etc) and ECS (for the game itself) is the winner combo, but I need to do some hands on project to test my ideas. The other thing I would like to find is a way to use all this concepts without missing the convenience of using Unity editor inspector for fast iteration and tweaking.

    1. I have already started to write the new article. I reckon it will be quite long, maybe I have to split it in two parts. I spent most of the time to write the first draft of the framework, that is already available on github with an example included. The example is the unity survival demo that I rewrote with the framework. However it’s better to wait for the article to understand what I did.

  2. May I just say that you are confusing Inversion of Control to be only Dependency Injection. A paper recently published identifies a bottom up approach to Inversion of Control, which goes beyond Dependency (State) Injection to include Continuation Injection (inversion of behaviour) and Thread Injection (inversion of performance). The paper is available at http://doi.acm.org/10.1145/2739011.2739013 (or for a free download a link off http://www.officefloor.net/mission.html ). I hope this helps you realise your vision of a bottom up approach is actually available now 🙂

    1. Thanks for the feedback! I will read those articles asap! I am not sure if it’s related, but I do continuously talk about Inversion of Creation Control and Inversion of Flow Control, so I actually do not think Inversion of Control is Dependency Injection.

Leave a Reply