I Made Peace with ServiceLocator
I won’t needlessly go deep here into why dependency injection through the constructor is usually the best way. In short, it’s beautifully explicit and local (that is, not global), you don’t contaminate your class with some framework or library, testability is the bomb, it’s just divine. Anything else isn’t as clean and straightforward.
And I won’t go much into why Singleton, or its marginally better little brother ServiceLocator, are villains in principle. Global state, whether mutable, immutable or configurable in all sorts of ways, that’s accessible at any time from any part of the code, has a rather explosive character. And we can call it whatever we want, but it’s just chicken manure. You can’t paint it pink and make it better.
But. Even chicken manure is the best fertilizer for strawberries, if you get rid of the ammonia.
I created several classes that could potentially create other classes, which created other classes. Game components (think of a component from Unity), inside them a state pattern, which could potentially create further components. And so on. A -> B -> C -> D -> C. The flow sounded fine and natural, it’s just that the problem was a bit… problematic. And these things had dependencies. So when D gets created, A already has to know how to pass those dependencies along.
Of course, a factory class can help. Alas, the complexity and readability of this whole solution sadly go straight down the crapper. Suddenly I’m dragging dependencies and factories everywhere, constructors look like an overcrowded transfer station, things bloat.
It’s clean, sure. But it’s also terribly ugly. And all that just because of silly things that really are always part of the application. And we’re talking about a small application, not a library. Not a framework used by a million people. Hell, this code will probably only ever be seen by my future self.
And so I made peace with ServiceLocator, but only for those game components and their henchmen. The services around them strictly use dependency injection through the constructor, and Autofac conducts it all. Either way, it’s there. And the strawberries are growing.