@@ -11,24 +11,24 @@ Dependency injection and inversion of control in Python
1111 feature for testing or configuring project in different environments and explains
1212 why it's better than monkey-patching.
1313
14- Originally dependency injection pattern got popular in the languages with a static typing,
15- like Java. Dependency injection is a principle that helps to achieve an inversion of control.
16- Dependency injection framework can significantly improve a flexibility of the language
17- with a static typing. Implementation of a dependency injection framework for a language
18- with a static typing is not something that one can do quickly. It will be a quite complex thing
14+ Originally dependency injection pattern got popular in languages with static typing like Java.
15+ Dependency injection is a principle that helps to achieve an inversion of control. A
16+ dependency injection framework can significantly improve the flexibility of a language
17+ with static typing. Implementation of a dependency injection framework for a language
18+ with static typing is not something that one can do quickly. It will be a quite complex thing
1919to be done well. And will take time.
2020
21- Python is an interpreted language with a dynamic typing. There is an opinion that dependency
21+ Python is an interpreted language with dynamic typing. There is an opinion that dependency
2222injection doesn't work for it as well as it does for Java. A lot of the flexibility is already
23- built in. Also there is an opinion that a dependency injection framework is something that
23+ built- in. Also, there is an opinion that a dependency injection framework is something that
2424Python developer rarely needs. Python developers say that dependency injection can be implemented
2525easily using language fundamentals.
2626
27- This page describes the advantages of the dependency injection usage in Python. It
28- contains Python examples that show how to implement dependency injection. It demonstrates a usage
29- of the dependency injection framework ``Dependency Injector ``, its container, ``Factory ``,
30- `` Singleton `` and ``Configuration `` providers. The example shows how to use `` Dependency Injector ``
31- providers overriding feature for testing or configuring project in different environments and
27+ This page describes the advantages of applying dependency injection in Python. It
28+ contains Python examples that show how to implement dependency injection. It demonstrates the usage
29+ of the ``Dependency Injector `` framework , its container, ``Factory ``, `` Singleton ``,
30+ and ``Configuration `` providers. The example shows how to use providers' overriding feature
31+ of `` Dependency Injector `` for testing or re- configuring a project in different environments and
3232explains why it's better than monkey-patching.
3333
3434What is dependency injection?
@@ -44,15 +44,14 @@ What is coupling and cohesion?
4444
4545Coupling and cohesion are about how tough the components are tied.
4646
47- - **High coupling **. If the coupling is high it's like using a superglue or welding. No easy way
47+ - **High coupling **. If the coupling is high it's like using superglue or welding. No easy way
4848 to disassemble.
49- - **High cohesion **. High cohesion is like using the screws. Very easy to disassemble and
50- assemble back or assemble a different way. It is an opposite to high coupling.
49+ - **High cohesion **. High cohesion is like using screws. Quite easy to disassemble and
50+ re- assemble in a different way. It is an opposite to high coupling.
5151
52- Cohesion often correlates with coupling. Higher cohesion usually leads to lower coupling, and vice
53- versa.
52+ Cohesion often correlates with coupling. Higher cohesion usually leads to lower coupling and vice versa.
5453
55- Low coupling brings a flexibility. Your code becomes easier to change and test.
54+ Low coupling brings flexibility. Your code becomes easier to change and test.
5655
5756How to implement the dependency injection?
5857
@@ -150,14 +149,14 @@ Here comes the ``Dependency Injector``.
150149What does the Dependency Injector do?
151150-------------------------------------
152151
153- With the dependency injection pattern objects loose the responsibility of assembling
152+ With the dependency injection pattern, objects lose the responsibility of assembling
154153the dependencies. The ``Dependency Injector `` absorbs that responsibility.
155154
156155``Dependency Injector `` helps to assemble and inject the dependencies.
157156
158157It provides a container and providers that help you with the objects assembly.
159158When you need an object you place a ``Provide `` marker as a default value of a
160- function argument. When you call this function framework assembles and injects
159+ function argument. When you call this function, framework assembles and injects
161160the dependency.
162161
163162.. code-block :: python
@@ -198,79 +197,79 @@ the dependency.
198197 with container.api_client.override(mock.Mock()):
199198 main() # <-- overridden dependency is injected automatically
200199
201- When you call ``main() `` function the ``Service `` dependency is assembled and injected automatically.
200+ When you call the ``main() `` function the ``Service `` dependency is assembled and injected automatically.
202201
203- When doing a testing you call the ``container.api_client.override() `` to replace the real API
204- client with a mock. When you call ``main() `` the mock is injected.
202+ When you do testing, you call the ``container.api_client.override() `` method to replace the real API
203+ client with a mock. When you call ``main() ``, the mock is injected.
205204
206205You can override any provider with another provider.
207206
208- It also helps you in configuring project for the different environments: replace an API client
207+ It also helps you in a re- configuring project for different environments: replace an API client
209208with a stub on the dev or stage.
210209
211- Objects assembling is consolidated in the container. Dependency injections are defined explicitly.
212- This makes easier to understand and change how application works.
210+ Objects assembling is consolidated in a container. Dependency injections are defined explicitly.
211+ This makes it easier to understand and change how an application works.
213212
214213Testing, Monkey-patching and dependency injection
215214-------------------------------------------------
216215
217- The testability benefit is opposed to a monkey-patching.
216+ The testability benefit is opposed to monkey-patching.
218217
219- In Python you can monkey-patch
220- anything, anytime . The problem with a monkey-patching is that it's too fragile. The reason is that
221- when you monkey-patch you do something that wasn't intended to be done. You monkey-patch the
222- implementation details. When implementation changes the monkey-patching is broken.
218+ In Python, you can monkey-patch anything, anytime. The problem with monkey-patching is
219+ that it's too fragile . The cause of it is that when you monkey-patch you do something that
220+ wasn't intended to be done. You monkey-patch the implementation details. When implementation
221+ changes the monkey-patching is broken.
223222
224- With a dependency injection you patch the interface, not an implementation. This is a way more
223+ With dependency injection, you patch the interface, not an implementation. This is a way more
225224stable approach.
226225
227- Also monkey-patching is a way too dirty to be used outside of the testing code for
228- reconfiguring the project for the different environments.
226+ Also, monkey-patching is way too dirty to be used outside of the testing code for
227+ re-configuring the project for the different environments.
229228
230229Conclusion
231230----------
232231
233- Dependency injection brings you 3 advantages:
232+ Dependency injection provides you with three advantages:
234233
235- - **Flexibility **. The components are loosely coupled. You can easily extend or change a
236- functionality of the system by combining the components different way. You even can do it on
234+ - **Flexibility **. The components are loosely coupled. You can easily extend or change the
235+ functionality of a system by combining the components in a different way. You even can do it on
237236 the fly.
238- - **Testability **. Testing is easy because you can easily inject mocks instead of real objects
237+ - **Testability **. Testing is easier because you can easily inject mocks instead of real objects
239238 that use API or database, etc.
240239- **Clearness and maintainability **. Dependency injection helps you reveal the dependencies.
241240 Implicit becomes explicit. And "Explicit is better than implicit" (PEP 20 - The Zen of Python).
242- You have all the components and dependencies defined explicitly in the container. This
243- provides an overview and control on the application structure. It is easy to understand and
241+ You have all the components and dependencies defined explicitly in a container. This
242+ provides an overview and control of the application structure. It is easier to understand and
244243 change it.
245244
246- Is it worth to use a dependency injection in Python?
245+ Is it worth applying dependency injection in Python?
247246
248247It depends on what you build. The advantages above are not too important if you use Python as a
249248scripting language. The picture is different when you use Python to create an application. The
250- larger the application the more significant is the benefit .
249+ larger the application the more significant the benefits .
251250
252- Is it worth to use a framework for the dependency injection?
251+ Is it worth using a framework for applying dependency injection?
253252
254253The complexity of the dependency injection pattern implementation in Python is
255- lower than in the other languages but it's still in place. It doesn't mean you have to use a
254+ lower than in other languages but it's still in place. It doesn't mean you have to use a
256255framework but using a framework is beneficial because the framework is:
257256
258257- Already implemented
259258- Tested on all platforms and versions of Python
260259- Documented
261260- Supported
262- - Known to the other engineers
261+ - Other engineers are familiar with it
263262
264- Few advices at last:
263+ An advice at last:
265264
266265- **Give it a try **. Dependency injection is counter-intuitive. Our nature is that
267266 when we need something the first thought that comes to our mind is to go and get it. Dependency
268- injection is just like "Wait, I need to state a need instead of getting something right now ".
267+ injection is just like "Wait, I need to state a need instead of getting something right away ".
269268 It's like a little investment that will pay-off later. The advice is to just give it a try for
270269 two weeks. This time will be enough for getting your own impression. If you don't like it you
271270 won't lose too much.
272- - **Common sense first **. Use a common sense when apply dependency injection. It is a good
273- principle, but not a silver bullet. If you do it too much you will reveal too much of the
271+ - **Common sense first **. Use common sense when applying dependency injection. It is a good
272+ principle, but not a silver bullet. If you do it too much you will reveal too many of the
274273 implementation details. Experience comes with practice and time.
275274
276275What's next?
@@ -304,8 +303,7 @@ Choose one of the following as a next step:
304303Useful links
305304------------
306305
307- There are some useful links related to dependency injection design pattern
308- that could be used for further reading:
306+ A few useful links related to a dependency injection design pattern for further reading:
309307
310308+ https://en.wikipedia.org/wiki/Dependency_injection
311309+ https://martinfowler.com/articles/injection.html
0 commit comments