In as few words as possible, I am going to explain to you how and why to use dependency injection in Python.
What does dependency injection look like?
Imagine you had written a class in python to insert data into a database. It might have a method that looked something like this:
def add(self, username, password):
db = sqlite(USER_DB)
...
db.commit()
return True
In this method we can see that the use of sqlite is hardcoded. But it doesn’t have to be this way! That’s what dependency injection is all about. Instead of hardcoding our db provider, we can inject whatever db provider we wish, into the class itself.
class UserModifier:
def __init__(self, db):
self.db = db
def add(self, username, password):
db = self.db(USER_DB)
...
db.commit()
return True
In the above example, we ‘inject’ the database into the class when an instance is ‘instantiated’. Here’s how we might ‘inject’ sqlite as the db…
user_modifier = UserModifier(db=sqlite)
That’s it, that’s what dependency injection looks like!
Note: Please remember that when we type ClassName(params) that automatically translates to ClassName.__init__(params). |
So why use dependency injection?
The whole point of dependency injection is to enable more flexibility in the future for the users of your code. You might think that users would only ever want to use ‘sqlite’. But what if they need to write unittests which utilize a mock db? What if they need to use your code to write to a db other than sqlite?
Using dependency injection will allow those who import your code to have control over the implementation specifics of your code.
When should I use dependency injection?
You should use this in all of your code which you expect will be used by others. You should use it to enable injection for all resources which access, the filesystem, the network, or which should otherwise be mocked during unittests.
Note: Python can sometimes complicate dependency injection by not being strongly typed. When injecting please ensure that what is injected has all the methods depended upon by the class into which the object is injected. |