Dependency Injection
Steven D'Aprano
steve+comp.lang.python at pearwood.info
Sat Apr 11 06:33:36 EDT 2015
On Sat, 11 Apr 2015 04:50 pm, Palpandi wrote:
> Hi all,
>
> Can anyone explain about the dependency injection concept in python?
>
> I have a class A. A is used in all other classes(B, C, D, ..). Is it good
> to use dependency injection concept in this situation or else any other
> suggestions?
The best description of Dependency Injection is this one from James Shore:
"Dependency Injection" is a 25-dollar term for a 5-cent
concept. ... Dependency injection means giving an object
its instance variables.
http://www.jamesshore.com/Blog/Dependency-Injection-Demystified.html
Suppose we have a class like this:
class Car:
def __init__(self):
self.engine = Engine('4L', 'automatic')
def accelerate(self):
...
def brake(self):
...
Our Car class depends on the Engine class. Now, suppose we want a car with
an electric engine. We could subclass:
class ElectricCar(Car):
def __init__(self):
self.engine = ElectricMotor()
and for some problems that's fine. But *dependency injection* is another
solution. We change the Car class to take the engine as an argument:
# With dependency injection.
class Car:
def __init__(self, engine):
self.engine = engine
Now preparing the engine is the responsibility of the caller, not the Car
class. But that gives us lots more flexibility that we otherwise didn't
have:
grandmothers_car = Car(Engine('6L', 'manual')
dads_car = Car(ElectricMotor())
my_car = Car(LawnmowerEngine())
funnycar = Car(NitroBurningSupercharger())
This can make (for example) testing easier and less fragile:
# Without dependency injection, we have to monkey-patch on the fly.
save_engine = Engine # Save.
Engine = MockEngine # Replace.
test = Car()
Engine = save_engine # Restore.
# With dependency injection, things are easy.
test = Car(MockEngine())
but the cost is that the caller now is responsible for the Car's internals.
We can have the best of both worlds by using a default value:
class Car:
def __init__(self, engine=None):
if engine is None:
engine = Engine('4L', 'automatic')
self.engine = engine
# I don't care what sort of engine I get
car = Car()
# Now I want to test.
test = Car(MockEngine())
Another related strategy is to pass the engine type, not the engine itself:
class Car:
def __init__(self, engine_type):
self.engine = engine_type('4L', 'automatic')
--
Steven
More information about the Python-list
mailing list