This is the post that discusses about how can python module designing be benefited from dependency injection. You have been given the following requirements:
You are the developer on Blipkart, an e-commerce website. You have been asked to build a reusable SMS module that other developers will use to send SMS’es. Watertel is a telecom company that provides a REST API for sending SMS’es, and your module needs to integrate with Watertel. Your module will be used by other modules such as logistics.py and orders.py.
The client modules have a dependency on our module to complete a portion of its work which is – sending an SMS. So our module’s object has to be injected in the client’s module though the respective modules do not know each other directly.
Why Dependency Injection?
The essence of dependency injection is that it allows the client to remove all knowledge of a concrete implementation that it needs to use. This helps isolate the client from the impact of design changes and defects. It promotes reusability, testability and maintainability.
Basically, instead of having your objects creating a dependency or asking a factory object to make one for them, you pass the needed dependencies in to the object externally, and you make it somebody else’s problem. This “someone” is either an object further up the dependency graph, or a dependency injector (framework) that builds the dependency graph. A dependency as I’m using it here is any other object the current object needs to hold a reference to.
The client modules ie. orders.py and logistics.py can import our module’s object and then inject it where it needs the module to perform its task.
This will explain how it should look like.
# In sms.py:
from django.conf import settings
def __init__(self, url, username, password):
self.username = username
self.password = password
def send_sms(phone_number, message):
# TODO - write code to send sms
sms_client = SmsClient(settings.sms_url, settings.sms_username, settings.sms_password)
and in orders.py:
from sms import sms_client
# when you need to send an sms
How does Dependecy Injection help us?
1.Dependency Injection decreases coupling between a class and its dependency.
2.Because dependency injection doesn’t require any change in code behavior it can be applied to legacy code as a refactoring. The result is clients that are more independent and that are easier to unit test in isolation using stubs or mock objects that simulate other objects not under test. This ease of testing is often the first benefit noticed when using dependency injection.
3.To free modules from assumptions about how other systems do what they do and instead rely on contract.
4.To prevent side effects when replacing a module.
So in all, dependency injection is a great practice to make our modules more testable, maintainable and scalable and we should use it more often to make our lives easier as developers.