Transcription of Python Dependency Injection
1 Copyright 2008, Google Inc Python Dependency InjectionAlex Martelli "levels" of this talk2 ShuHaRiPyDP("Retain")("Detach")("Transce nd") 3 The novice goes astray and says, "The Art failed me."The master goes astray and says,"I failed the Art." Dependency Injection DP4 Name: " Dependency Injection "Forces: an object depends on other concrete objects which it instantiates (or accesses as singletons, ..)we may want to control dependencies for all the usual good reasonsin particular, unit-testing may require mocking otherwise-concrete objectswe'll see examples & alternative solutions throughout the rest of this talkA simple schedulerclass ss(object): def __init__(self): = ().next = () def AddEvent(self, when, c, *a, **k): ((when, (), c, a, k)) def Run(self): while : when, n, c, a, k = () (when - ()) c(*a, **k) 5(A "side note")class PriorityQueue(object): def __init__(self): = [] def __len__(self): return len( ) def push(self, obj): ( , obj) def pop(self): return ( )6 Fine, do you test ss without long waits?
2 How do you integrate it with other subsystems' event loops/simulations?The core issue is that ss "concretely depends" on some specific objects (here, callables and ).We'll discuss 3 approaches to solve :1. the Template Method DP2. "Monkey Patching"3. the Dependency Injection DP7 The Template Method DPOne classic answer ("Template Method" DP): .. when, n, c, a, k = () (when) c(*a, **k) .. def WaitFor(self, when): (when - ())(to customize: subclass ss, override WaitFor)8TM DP exampleclass sq(ss): def __init__(self): (self) = () def WaitFor(self, when): try: while when> (): c, a, k = (true, () - when) c(*a, **k) except : return9 Some issues with TM inheritance gives strong, inflexible couplinga customized-scheduler has complex, specialized extra logicfar from ideal for either unit-testing or simulated-time system : if another subsystem makes a scheduler, how does it know to make a test-scheduler instance vs a simple-scheduler one?
3 (shades of )multiple integrations even harder than need be (but, there's no magic bullet for those!-) ssclass faker(object): passfake = faker() = = .. = ..11extremely handy in emergencies, often abused for NON-emergencies!"gives dynamic languages a bad name"!-)subtle, hidden "communication" via secret, obscure pathways (explicit is better!-)The general DI ideaclass ss(object): def __init__(self, tm= , sl= ): = tm = sl .. (when - ())12a known use: standard library sched module!DI makes it easy to mockclass faketime(object): def __init__(self, t= ): = t def time(self): return def sleep(self, t): += tf = faketime()s = ss( , )..13DI/TM orthogonalityNot at all mutually :class ss(object): def __init__(self, tm= , sl= ): .. def WaitFor(self, when): ( ())then may use either Injection , or subclassing and overriding, (or both!-), for testing, integration, &c 14DI design-choice detailsinject by constructor (as shown)with, or without, default dep.
4 Values?ensure just-made instance is consistentchoose how "visible" to make the by setterautomatic in Python (use non-_ names)very flexible (sometimes too much;-)"inject by interface" (AKA "IoC type 1")not very relevant to PythonDI: by code or by config-file/flags?15DI and factoriesclass ts(object): .. def Delegate(self, c, a, k): q = () def f(): (c(*a,**k)) t = (target=f) () return qeach call to Delegate needs a new Queue and a new Thread; how do we DI these solution: inject factories for them!16DI and factoriesclass ts(object): def __init__(self, q= , t= ): = q = t .. def Delegate(self, c, a, k): q = () .. t = (target=f)pretty obvious/trivial solution when each class is a factory for its instances, of course;-)17 Questions & Answers18Q?A!