Hacker News new | ask | show | jobs
by wmanley 702 days ago
Dependency injection means that the caller explicitly provides dependencies to functions/classes rather than having the classes/function getting their dependencies from the environment.

Taking an example like the article. Lets say you have a game with a ghost which randomly moves left or right. This would NOT be dependency injected:

    class Ghost:
        def __init__(self):
            self.pos = 5

        def move(self):
            match random.randint(0, 1):
                case 0:
                    self.pos -= 1
                case 1:
                    self.pos += 1
It's constructed like this:

    ghost = Ghost()
Ghost's behaviour depends on the state of the global RNG, but that isn't obvious from the perspective of the user of this class.

So instead we apply DI, and pass a random number generator in:

    class Ghost:
        def __init__(self, rng):
            self.pos = 5
            self.rng = rng

        def move(self):
            match self.rng.randint(0, 1):
                case 0:
                    self.pos -= 1
                case 1:
                    self.pos += 1
It's constructed like:

    ghost = Ghost(rng=random)
Now the fact that the class uses random numbers is explicit, and you can pass in an alternative RNG for testing purposes.

DI is a very useful technique that can make the construction of your system understandable, and make it easy to mock out dependencies. Much like mocking however - it shouldn't be over-used. If you use DI too much your code will become opaque as you'll never know what the concrete type of code you're calling is. Python's progressive typing can help here to some extent.

-----------

Dependency injection is not to be confused with dependency injection systems, which are complicated beasts that obscure what dependencies are actually constructed or provided. They make DI implicit again with the argument that it's better because you don't have to pass parameters manually. I would argue that if you need a dependency injection system, maybe you've over-used dependency injection.

-----------

I like to think of it as being related to capability based security[1], where you have to explicitly provide your dependencies, otherwise you won't be able to access them.

[1]: https://en.wikipedia.org/wiki/Capability-based_security