0

This is a conceptual problem I'm having general difficulty with, and I'd like to look at an example that can hopefully help clarify this: using a map to represent an alterable game world. For simplicity, this map can just be a two dimensional array of ints. I'm approaching this from C# within Unity, if that changes anything.

Global State being bad, or at least far from ideal, is addressed here: Why is Global State so Evil? I conceptually understand these issues it poses, but I do not see how the proposed alternatives actually solve this. The largest issue seems to be mutability, and changes creating instability in the code.

Looking at my map example, there are a number of systems that might need to access the map: rendering needs to look at the data and determine what sprites to draw, input needs to check the data to determine if certain inputs are valid, the data of the map may need to be changed if a tile is destroyed or built upon, etc. My most instinctual approach is to create the map as a singleton that can then be easily referenced from wherever it's needed. This, however, obviously creates Global State and thus becomes a problem.

Dependency injection seems to be the most commonly referenced way of preventing global state, but I do not see how this reduces or eliminates Global State. From my understanding, instead of getting a reference to my map by creating a singleton, I instead pass in the reference through the constructors. This seems functionally identical to me - in both cases, everything ends up with a reference to the same Global State, except DI has what seems to be a downside because it requires extra passing of parameters.

Is DI supposed to use only copied state? In which case are there not relatively significant performance/memory impacts in the duplication of so much data? Obviously since I'm learning, I can probably ignore performance unless it really becomes an issue, but this just seems incredibly clunky and inefficient to me.

So, what am I missing about DI that makes it a viable solution to this problem? What alternative solutions exist that actually address this problem?

  • 2
    FYI: a lot of the 'rules' and 'best practices' are oriented towards internal enterprisey softwares, and the rules don't necessarily apply in all areas. Games are one area where many of the usual rules are not helpful. Keep that in mind. – whatsisname May 18 '18 at 4:14
  • I think you misunderstand the point of using DI: now the user of the singleton doesn't know or care whether the thing even is a singleton. Where did it come from/Where dose it live? Don't care. Who else has access to it? Don't know/shouldn't care. – Jared Smith May 18 '18 at 16:01
3

If you only have the one map and pass it into everything, then yes this is functionally equivalent to a global variable.

But there is a very important difference. You are not forced to only have a single instance.

For example, lets say you have a behaviour which shows a high level map view of your world.

MapViewBehaviour_Global
{
    OnDraw()
    {
        draw(Game.Map) //static global variable
    }
}

or

MapViewBehaviour_DependencyInjection
{
    OnDraw()
    {
        draw(this.Map) //injected local variable
    }
}

So to begin with you inject Game.Map into the DI version and wonder why you are bothering. But then you make a 'load game' screen where you want to display a map over view for each saved game.

Your DI version copes easily where as your global version falls over.

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.