Dependency injection and abstractions

May 7, 2014 in Technology

Testability is an important feature of any software product – game development is not an exception. To enable testability, all the components should be independent and testable in isolation.

When we want to test something in isolation it means that we want to decouple it. Loose coupling is what we need. It is so easy to embed hidden dependencies into your game and it is so hard to break them. This article will help you understand loose coupling and dependency injection within a project in Unity, using the example project on github.

Lets take handling input as an example.


public class SpaceshipMotor : MonoBehaviour
{
void MoveHorizontally ()
{
var horizontal = Input.GetAxis ("Horizontal");
// ...
}
}

MoveHorizontally method uses static Unity API (Input class) without telling you. It considers this call to be his private business and you can’t control or influence the situation. It makes SpaceshipMotor class tightly coupled with Unity static API, and you can’t verify the behaviour of the SpaceshipMotor class unless you physically press the key on the keyboard. It’s annoying.

Now lets take this situation under control. You are in charge here.

The SpaceshipMotor class is using only horizontal axis, so we can define a short description what kind of functionality it expects from user input.


public interface IUserInputProxy
{
float GetAxis(string axisName);
}

Then you can substitute the call to real Input with the call to our abstraction.


public class SpaceshipMotor : MonoBehaviour
{
public IUserInputProxy UserInputProxy {get;set;}

void MoveHorizontally ()
{
var horizontal = UserInputProxy.GetAxis (“Horizontal”);
// …
}
}

Now you are in charge of the situation! The class can’t operate unless you provide it IUserInputProxy implementation.

This is called Dependency Injection (DI). When the dependency (Input in our case) is passed to the dependant object(SpaceshipMotor class) and it becomes part of it’s state (a field in our case).

There are several options of passing a dependency: constructor injection, property injection, method injection.

Constructor injection is considered to be the most popular and the most robust approach as when the dependency is passed in the construction phase our chances to have object in uninitialized state is minimal.

public class SpaceshipMotor : MonoBehaviour
{
private readonly IUserInputProxy userInputProxy;

public SpaceshipMotor (IUserInputProxy userInputProxy)
{
this.userInputProxy = userInputProxy;
}
}

But Unity engine is calling the constructors for MonoBehaviours and we can’t control this process.

 Still, property and method injection are both usable in this case.

 The easiest approach for manual Dependency Injection (DI) would be to use the script that will inject the dependencies.

In “Growing Games Guided by Tests” we are using an interface to expose property dependency.


public interface IRequireUserInput
{
IUserInputProxy InputProxy { get; set;}
}

And a script that allows us to set the parameters of fake input in the scene and inject it when the tests start.


public class ArrangeFakeUserInput : MonoBehaviour
{
public GameObject Spaceship;
public FakeUserInput FakeInput;

void Start () {
var components = Spaceship.GetComponents<MonoBehaviour> ();
var dependents = components.Where(c=>c is IRequireUserInput)
.Cast<IRequireUserInput>();
foreach(var dependent in dependents)
dependents.InputProxy = FakeInput;
}
}

How does this contribute to testability?

 

We have lots of examples in “Growing Games Guided by Tests” where fake user input is injected with helper script and it lets us test the behaviour.

On the other hand we can write unit tests for classes that depend on abstractions.


[Test]
public void ChangesStateToIsFiringOnFire1ButtnPressed()
{
// Arrange
// Setting test double for user input
IUserInputProxy userInput = Substitute.For<IUserInputProxy> ();
// Telling GetButton method of test double to return true
// if state of “Fire1” was requested
userInput.GetButton(Arg.Is("Fire1")).Returns (true);
// Passing the dependency to Gun object on creation
Gun gun = new Gun(userInput);
// Act
gun.ProcessInput ();
// Assert
Assert.That(gun.IsFiring, Is.True);
}

Now you see that there is no magic to dependency injection. It is the process of substitution of concrete dependencies with the abstractions and making them external to the dependant object.

To use DI on a large scale you need a tool to automate it . This will be the topic for our next blogpost.

 

Comments (29)

Subscribe to comments
  1. vitamin d

    June 26, 2014 at 7:10 pm / 

    Hey I am so glad I found your web site, I really found you
    by error, while I was searching on Aol for something else, Anyhow I am here now and would just like to say many
    thanks for a tremendous post and a all round thrilling blog (I also love the theme/design), I don’t
    have time to look over it all at the moment but I have bookmarked it and also included
    your RSS feeds, so when I have time I will be back to read more,
    Please do keep up the excellent b.

  2. Steve Vermeulen

    June 4, 2014 at 4:41 am / 

    Zenject was added to the Asset store this week to address this problem: http://u3d.as/content/modest-tree-media/zenject-dependency-injection/7ER

  3. Alan

    May 9, 2014 at 5:36 pm / 

    @DIMITRY:

    Nice to know that there will be another article about this topic!

    I’ve had an idea lately, thinking about DI and Unity. Do you think it would be possible to integrate a DI framework directly into the Unity Engine? The reason for that is simple: each and every MonoDevelop is instantiated by Unity. If the engine would have control over the application context (or DI Container, depending on your background), then the ENGINE itself could do the injecting of [Inject]-Attributed fields in MonoBehaviours!

  4. Nicholas

    May 9, 2014 at 3:15 am / 

    IOC and messenger come standard with unity foundation

    Avariceonline.com/foundation

  5. serpin

    May 8, 2014 at 4:53 pm / 

    Please, help me understand why this would be better, then just having a separate SpaceShipInput class with methods for making the ship say, move and a public master ProcessInput() method and a separate SpaceShipLogic class which would have a single reference to SpaceShipInput instance and call its ProcessInput() method every frame?

    In this case within SpaceShipInput you have a bool “isFakeInput” attribute which determines which input each method processes – real GetAxis or a value from some attribute in the SpaceShipInput class itself, say, public int horisFakeInput which is exposed in the inspector.

    Granted, you will have to basically have a condition in each internal method to switch between real or fake input base on the “isFakeInput”, but you won’t depend on external interfaces and can go live by just setting isFakeInput = false.

    But surely if Unity API supported DI you wouldn’t need all this bull**t.

  6. Dmitriy Mindra

    May 8, 2014 at 2:24 pm / 

    @ALAN, “universal cure” doesn’t exist. The purpose of the article was to give an introduction to DI. I’ve already promised to write another one about DI frameworks. DI is good for building both simple and complex systems. When you are using a framework, wiring complex hierarchies is not a problem. While loose coupling makes testing and reuse of your classes easier. Circular references in constructors do make problems which are easily solved in Java but might be an issue in C#. If you depend on interfaces they are quite resolvable, though.

    http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/

  7. Dmitriy Mindra

    May 8, 2014 at 2:04 pm / 

    @Nico, you are right regarding the shorter version. And yes blog engine eats this > < :)

  8. Nico de Poel

    May 8, 2014 at 12:52 pm / 

    Okay I give up. >_<

  9. Nico de Poel

    May 8, 2014 at 12:51 pm / 

    ^ … aaand the generic arguments in those code snippets got interpreted as HTML and filtered out. Let’s try that again:

    var dependents = components.Where(c=>c is IRequireUserInput)
    .Cast ();

    is the same as:

    var dependents = components.OfType ();

  10. Nico de Poel

    May 8, 2014 at 12:47 pm / 

    Minor LINQ-related nitpick, but this:

    var dependents = components.Where(c=>c is IRequireUserInput)
    .Cast();

    can be written shorter and simpler as this:

    var dependents = components.OfType();

  11. Alan

    May 8, 2014 at 10:53 am / 

    Nice article, but imho it doesn’t go far enough. Doing dependency wiring “by hand” is really an awful and error-prone task. Normally, you would employ a framework here. Examples include Zenject, Ninject and Spring4Net.

    Also, what you didn’t mention are the shortcomings of DI. DI works perfectly when wiring up singleton classes (e.g. UnityEngine.Input would be very nice, but since it only offers static methods, you need to do this artificial proxy thing as shown above), however DI really runs into problems when wiring non-static objects, ESPECIALLY if they have constructor arguments and cyclic dependencies.

    DI is great. But it’s not the “universal cure” for all architecture problems, as it appears to be from reading the article.

  12. Freezx

    May 8, 2014 at 9:01 am / 

    I am using Zenject for dependency injection because it’s simple and you can make things quickly.

  13. Chris

    May 7, 2014 at 10:05 pm / 

    @DMITRIY MINDRA
    I find that this way of thinking scales for my uses. The move script is a component that can be reused by anything that needs to move that particular way. The actual call to move may come from a Unity Input component script, from some AI component script or via a test class. In all cases move works the same without dependancy, although in this example move would depend on a Transform or Rigidbody to actually move. I guess I just don’t see where an interface fits into the Unity component way of doing things.

  14. Dmitriy Mindra

    May 7, 2014 at 10:01 pm / 

    @RICHARD, you are absolutely right. The component is not usable without wiring code. I like the mechanism that is implemented in ASP.NET MVC, where you can provide your implementation of IDependencyResolver that would resolve dependencies for your application. Maybe we need something similar for Unity?

  15. Richard Fine

    May 7, 2014 at 8:57 pm / 

    This is great right up until the point that SpaceshipMotor is now unusable without some other code to wire it up. It’s not even the case that we can just wire it up to a RealUserInput component in the Inspector and forget about it, because interface references aren’t serialised…

  16. Dmitriy Mindra

    May 7, 2014 at 6:16 pm / 

    @JOSEPH, thank you for the link to Suice DI framework! It would be very useful for my next blogpost.
    @CHRIS, your approach is easy, but does it scale?

  17. Danyal

    May 7, 2014 at 6:16 pm / 

    Probably the best description of DI I’ve ever read.

  18. Chris

    May 7, 2014 at 5:58 pm / 

    My approach has been to make the function that moves public, then send in values using arguments from some other class.
    // Input managing class
    void HandleInput ()
    {
    var horizontalValue = Input.GetAxis (“Horizontal”);
    moveInstance.MoveHorizontally(horizontalValue);
    }
    // Then in the move class
    public void MoveHorizontally (float hInput)
    {
    var horizontal = hInput;
    }
    This seems much easier than juggling interfaces?

  19. Joseph

    May 7, 2014 at 5:55 pm / 

    We are stuck with an API with tons of static references.

    Resources.Load —
    Input.GetAxis —
    Screen

    The list goes on.

    Although, Unit tests is something that greatly benefits teams in creating clean, efficient, and less bug prone software.

    I have been wrapping all of Unity’s static classes so they can be testable, although – I follow one rule because about 2 years ago when I attempted DI for my first time in Dueling Blades, it is waaaayyy too inefficient to inject dependencies into a scene with tons of MonoBehaviours.

    So my rule is to Have MonoBehaviours be responsible for one thing: Managing Game Objects. There is 0 logic to my mono behaviours other than creating an API to doing specific tasks in regards to manipulating game objects/monobehaviours.

    I use Controllers and Services (Usually singletons) to instantiate, destroy and manage Mono Behaviours/Unity3d Objects.

    Following this rule and wrapping some of Unity’s APIs for unit testing has made life amazing with Unity.

    Feel free to check out the dependency injection framework I use (works on Unity 4.2+ for ios/android/pc) without any issues:

    http://forum.unity3d.com/threads/207102-Dependency-Injection-Unity

  20. Dmitriy Mindra

    May 7, 2014 at 5:48 pm / 

    @MAT, thanks for the reference to StrangeIoC. Next blogpost would be about DI frameworks.
    @MARTIJN, I would be glad to see your refactoring and discuss it.
    @LIOR, I definitely agree with you that making Engine API mockable would make life easier.

  21. Peter Dwyer

    May 7, 2014 at 4:27 pm / 

    Agree with Dmitriy here. Mocking is simply a way to mask the issues that actually exist in the code. While this allows you to test the code. If someone else comes along and doesn’t have your mocking suite they’re stuffed.

  22. Matt

    May 7, 2014 at 4:20 pm / 

    Check out StrangeIoC. Great DI framework with a MVCS inversion of control system as well.

  23. Martijn Zandvliet

    May 7, 2014 at 4:13 pm / 

    @VICTOR N.

    Having the input system as an object instance would allow you to switch it out with another one, as long as they adhere to the same interface. Kind of like the following:

    IInputDevice device = new UnityInputDevice(); // Use actual user input
    // IInputDevice device = new TestInputDevice(); // Use automated test input.

    float horizontal = device.GetAxis(“Horizontal”);

    Speaking of interfaces, and being a little pedantic, I’d refactor the example from the article to let SpaceshipMotor expose an interface for its functions and handling user input external to it.

    public interface ISpaceshipMotor {
    float ThrustInput { get; set; }
    }

    That way it is entirely decoupled from the input system, and can work with user input, test input, AI logic, or no logic at all.

  24. Lior Tal

    May 7, 2014 at 4:13 pm / 

    @Dmitriy – I Agree, that’s exactly what i said. I only added that the API Unity provides for Input could’ve been one that allows easier injection by not being a static class in the first place. In this article you “simulate” an input API that is interface based that hides Unity’s static class to allow replacing those calls with fake calls. That could’ve been easier to do if (like i said above) the API was provided as some singleton or something like that. Then, You could’be substituted the returned instance with a fake one. If there are .NET tools that allow mocking calls on static classes. Then you could just fake Input.GetAxis(…) or any other static call. I am not sure NSubstitute could do that (although i think other .NET tools can, but are probably not compatible with Unity)

  25. Dmitriy Mindra

    May 7, 2014 at 3:58 pm / 

    @Lior, mocking static classes is possible in .NET using proprietary libraries like Typemock Isolator or Microsoft Fakes. I don’t know any tools for Mono. In my opinion refactoring to abstractions is much better option. “Mocking static” lets you ignore your design issues while refactoring to abstractions solves them.

  26. Dmitriy Mindra

    May 7, 2014 at 3:53 pm / 

    @Lior, @Victor – there are many situations where you depend on something you can’t control. Input is just one example of static class that can’t be inherited from and you can’t test the behavior of classes that depend on it. But when you create an abstraction for Input, the situation changes and you can pass any class that implement interface including wrapper that calls “real” system API. Depending on abstractions means that object knows nothing about concrete implementation of it’s dependency and should be able to work with any object that implements the interface (Barbara Liskov substitution principle).

  27. Lior Tal

    May 7, 2014 at 3:24 pm / 

    @Victor – For example, instead of having a static Input class with static methods, e.g: Input.GetAxis(….)

    You would have a “singleton” like approach:

    var inputManager = Input.Instance;

    // As usual
    inputManager.GetAxis(…);

    When you test, you could fake the singleton instance using a mocking/fake framework such as NSubstitute to inject the instance you need for testing.

    In this article he presented a similar approach, but he had to define the interface for input himself so he could swap the implementation for testing purposes.

    Having the Input class already ready for substitution would’ve eased up on the process.

    * There may be mocking frameworks that allow mocking static classes (i can’t remember if .NET allows that or not).

  28. victor n.

    May 7, 2014 at 3:13 pm / 

    @LIOR TAL

    how changing the API would solve the tight coupling issue ? can you elaborate ?

  29. Lior Tal

    May 7, 2014 at 2:54 pm / 

    I think the problem is the Input API is a static class. The API should’be been built differently to support DI and testability.

Comments are closed.