Probably the most understandable explanation of Dependency Injection I ever read.

Just found this recent (March 2017) paper (Bachelor’s thesis)by Niko Parviainen on Dependency Injection and Inversion of Control in Unity. It is probably the most sensible, simple, and easy to understand explanation I’ve ever read (And I’ve read a lot of them over that last two years).

The author refers to Zenject a lot and also to Adic. It ends with a game example.
Dependency Injection in Unity3D
Also here is the game project (MirrorPuzzle) on Github.

1 Like

Dependency injection has always struck me as going a heck of a long way to avoid a GetComponent call. Its a Red Queen’s race, running really fast just to stay where you are.

2 Likes

I don’t know. After I added multiplayer and online networking my last game got so hard to work on because of all the things that DI is intended to solve. If you think that DI is just to avoid GetComponent than you don’t really know what DI is about. It is to keep things from depending on things that depend on things to the point that later modifying just a simple thing becomes a nightmare or it breaks something so far away that you have no idea how or why one affects the other.

But yes, some DI frameworks can be so involved and complicated that it is almost impossible to understand (the implementation, not the concept) And it kind of kills whats good about Unity. That’s why I like Adic which seems to be very lightweight.

Sure. I get the point of it. But DI isn’t the only way to manage dependencies.

That is one of my big issues with the article you linked, and most articles on DI in Unity. They generally start with ‘Find is bad, Singletons are bad, I hate the inspector’. And end with ‘Therefore DI’.

I can manage dependency for much less effort then it takes to force a dependency injection framework into Unity.

2 Likes

My beef with Dependency Injection is that if you don’t worship it (cause hey, I’ve used it… it’s got its uses)… but if you don’t worship it. People come out of the wood work and say thing like “you don’t really know what DI is about”.

I always like the phrase from James Shore:
“dependency injection is a 25-dollar term for a 5-cent concept”
http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
(and this was back in 2006! The year I started programming professionally)

And honestly… his explanation is perfect. DI is just that the creator (usually a factory) gives an object the fields it uses, rather than letting the object create it.

The various DI frameworks out there create a… a superfluous syntax through which to do this. Which always feel like some variation on the composite pattern (or component pattern at that).

It’s interesting because you might notice I’m tossing around very well known patterns here… factory, composite. DI to me has always just been a ‘step’ in those patterns.

Like DI is this amalgamation pattern that introduces people to the concept of interfaces/contracts.

Do I use DI?

ALL THE FREAKING TIME!

Do I use a DI framework?

NOPE!

In the end… DI to me sounds like in the early oughts, when Java was at its peak, and .Net was gaining traction in the Enterprise realm. The old engineers, the old school procedural, still write Cobol on the regular, engineers were sitting around grumbling about these new-fangle concepts. And some marketing savy young engineer came up with a real fancy term to wow the CTO/manager, but really just showing off a basic principal of OO design and contract design… and it took off.

A 25 dollar word, for a 5 cent concept.

6 Likes

Now that qualifies as the most understandable explanation of dependency injection ever.

(And one can’t help but notice that the Unity inspector itself is a dependency injection system.)

1 Like

I made this point a couple days ago in another thread. And of course, the wood work came out to tell me why there’s so much more to it, since it enables the same ability on none unity classes.

Which yeah… it does. By facilitating another framework that you have to create dependencies against.

Which is the humorous part of it all… DI frameworks, an attempt at decoupling dependencies… create an entire framework you’re to depend on!

Really, my beef isn’t with DI (I use it…), it’s with DI frameworks.

Not to say I think frameworks are terribad, hell I have an entire framework of code I carry from project to project with me as well (which is also showing quite a bit of bloat… need to trim that bastard). It’s just, you know… I think the irony of it is funny.

2 Likes

How do you do it? If there is a better way I’d like to use it.

Well, saying “going a heck of a long way to avoid a GetComponent call” does imply a shallow understanding of what it’s about. And I don’t worship it. Actually I hate it. But I hate the way my last game ended up more. So much that I haven’'t coded anything for the last 2.5 years. Instead I’ve been on a quest to find something that will keep me from ending up in that nightmare of highly coupled and brittle code again. I still haven’t found it. At least not one that solves my problem without being overly complicated (seemingly just to make code monkeys feel smarter than others), or that destroys or takes away everything that is good about Unity.

The only reason DI is in any way controversial here is because we don’t have access to any constructor, or consistent parameterized initialization method for MonoBehaviors or ScriptableObjects. So, to get the niceness of injected dependencies, we have to rely on frameworks that add complexity, or do without. If we could AddComponent(parameter1, parameter2, …) and have this be the only way to create an instance of that component, enforced by the compiler, life would be good. Instead, all we have is extension methods, naming conventions, runtime exceptions, and public-shaming to enforce good code. Sad.

It is very strange that this concept has a political air on these forums. You’re either Pro-DI or Anti-DI, and you must hate the other side with a passion!

3 Likes

One general issue with DI is it doesn’t actually enforce a good dependency structure. It just moves the dependency structure outside of your code and into a framework. But a poor dependency structure is still poor, no matter where it lives.

So focus on getting your dependency structure right, and most of the problems will go away.

I tend to use a layered system approach. A system is a group of classes that are inherently closely coupled. Within a system I tend to just use interfaces for separation. I then wrap each system in its own namespace, which is a convienient way of documenting dependencies between systems.

I then arrange my systems into layers, with each system only allowed dependencies on previous layers. Each system has a well defined entry and exit point. Disparate systems that have nothing to do with each other communicate through events or messages.

1 Like

I don’t know. I hang out on a lot of programming forums, many enterprise oriented (as most of my programming history is enterprise). And DI is just as controversial a topic.

I wouldn’t agree with this either. For example, both Kiwasi and I aren’t Anti-DI, nor are we Pro-DI (correct me if I’m wrong Kiwasi, don’t mean to presume, but that’s the gauge I’ve read).

I more or less see myself, to continue the political analogy, a moderate. I’ll criticize a conservative for going full moron, but when the liberal cheers at my back, I turn around say “now wait a second, you’re not that bright either ya know.”

I will say in a setting of unity, I personally find the component based approach fitting for most dependency injection. I obey the interface/contract rules that DI often totes around, because yes, that works very well. I don’t depend on (have a field for) a “MobTypeAWalkingAnimatorController”, I have a IWalkingAnimatorController that all walking animation controllers implement. And then attach the necessary one to my GameObject.

The one thing I find immensely useful from DI frameworks is the way it approaches singletons/global services. And this most heavily noticeable, just like Kiwasi pointed out in another thread, that most DI frameworks used in Unity boil down to some sort of Service Locator.

But injector (factory) part of the DI pattern… I don’t create a lot of that in code. Not all team mates write code (well), nor understand those concepts. They do understand GameObjects with components (which is arguably a form of dependency injection). I don’t find heavy need for it in game design… aside from the service locator.

Procedural generation stuff maybe could benefit for it… but not everyone does procedural generation.

I don’t know… DI is just such an enterprisey need to me. The ease of changing dependency on the fly to meet a clients needs. A product that is ever evolving as time moves forward, and is maintained primarily by engineers and their lackies.

Games are so much more collaborative in those who work on it, from artist to coder, I find it so much overkill. Like you brought a 150 foot crane to help install a family pool in the back yard. Sure… you COULD use it… but why?

1 Like

Heya, Woodwork here. :stuck_out_tongue: I feel like you’re misusing the word “dependency” here. In “dependency injection” it means a class that depends on another class. It doesn’t mean “don’t use any plugins; write everything yourself”. Using an asset doesn’t make it a “dependency” in that sense. Zenject doesn’t require adding new dependencies into your classes. You could always delete it and just call constructors or initializers manually if you wanted to.

It was a humorous joke. I was purposely twisting it.

But yeah… that fact you don’t NEED its dependencies, and just call constructors or initializers is my point. DI frameworks vs DI…

It’s not so much as being anti-DI.

It’s that over my career, I’ve seen “paradigm shifting” frameworks come and go, with similar (sometimes hyperbolic) statements being made each time.

So when yet another one comes along, I do my best not to roll my eyes before I learn more about what it’s supposed to offer. In the case of DI, my reaction was pretty much the same as James Shore: “Oh… that’s all it is?”

Honestly, the most valuable thing I’ve got going is experience. I take a look at a new thing, gauge the pros and cons, and sometimes take the best it offers and incorporate it into my own code, leaving behind the worst of it (or at least minimize the worst of it where I can).

If you were to ask me to name a pattern I found most useful in my career, I’d probably name the MVC (or MVVM) pattern. Being able to completely replace the UI without touching the logic is a good place to be. Funnily enough, a lot of that is done using DI.

3 Likes

Right, a good tool for the right job doesn’t make the right tool for all the jobs.

2 Likes

Well, the I is for “inject” which is what you get out of a framework. The biggest benefit to me is unit testing. I kept hitting walls trying to implement unit tests in Unity because most of my code used GetComponent<> or depended on certain things all being in a scene in play mode. Being able to easily substitute mocks for things that would otherwise be components is pretty nice. Zenject’s made unit testing like fifty times easier.

1 Like

I could definitely see that.

I’m not Anti-DI specifically. I just fail to see how it would be useful for me and my projects. I keep participating in these threads is just in case I’m wrong. Its still possible that someone posts something that gives me a decent use case for it.

Perhaps that’s my problem, I’m not a big fan of unit testing either. I tried it once on a project, and found that I was basically writing the same code twice. Once to do the job, and a second time in the unit test to make sure the job was done properly. Trouble was most of the time the only way to make sure the job was done properly was to do the job again. Which means if I had a mistake in my logic with the class, I would probably make the same mistake writing my unit test.

After that experience I just went back to hitting play mode in the editor, with the occasional debug.log statement. I’ll admit I’ve only used unit testing once, I may be missing the point of it.

I just mock up the components themselves. If you are using interfaces, its pretty easy to do. I find this especially useful for procedural generation. I’ll plug in a component with an IRandom interface that actually generates sequential numbers. Then once the generation code works, I’ll replace it with appropriate noise.

Mockups is an ‘advantage’ of DI frameworks that gets thrown around that isn’t really true. You can do mockups without using a DI framework just fine.

One case where I find unit testing really useful is if you’re developing a server as a service. Especially if it uses some sort of a database. Saves time on re-deploying a server if you’re able to test each API call rather than running the client and trying to hit them all.

Another case is multiplayer testing. It’s nice to have an early out before you spend the time updating the client on each machine, setting up a network session, etc…

Of course, this is just on the subject of unit testing. Nothing really to do with DI frameworks.

1 Like