mirror of
https://github.com/ets-labs/python-dependency-injector.git
synced 2025-02-16 19:40:59 +03:00
Update README
This commit is contained in:
parent
39368591b9
commit
9ee4959f76
149
README.rst
149
README.rst
|
@ -54,103 +54,23 @@ What is ``Dependency Injector``?
|
||||||
|
|
||||||
It helps implementing the dependency injection principle.
|
It helps implementing the dependency injection principle.
|
||||||
|
|
||||||
What is dependency injection?
|
Key features of the ``Dependency Injector``:
|
||||||
-----------------------------
|
|
||||||
|
|
||||||
Dependency injection is a principle that helps to decrease coupling and increase cohesion.
|
- **Providers**. Provides ``Factory``, ``Singleton``, ``Callable``, ``Coroutine``, ``Object``,
|
||||||
|
``List``, ``Configuration``, ``Dependency`` and ``Selector`` providers that help assembling your
|
||||||
What is coupling and cohesion?
|
objects. See `Providers <http://python-dependency-injector.ets-labs.org/providers/index.html>`_.
|
||||||
|
- **Overriding**. Can override any provider by another provider on the fly. This helps in testing
|
||||||
Coupling and cohesion are about how tough the components are tied.
|
and configuring dev / stage environment to replace API clients with stubs etc. See
|
||||||
|
`Provider overriding <http://python-dependency-injector.ets-labs.org/providers/overriding.html>`_.
|
||||||
- **High coupling**. If the coupling is high it's like using a superglue or welding. No easy way
|
- **Configuration**. Read configuration from ``yaml`` & ``ini`` files, environment variables
|
||||||
to disassemble.
|
and dictionaries.
|
||||||
- **High cohesion**. High cohesion is like using the screws. Very easy to disassemble and
|
See `Configuration provider <http://python-dependency-injector.ets-labs.org/providers/configuration.html>`_.
|
||||||
assemble back or assemble a different way. It is an opposite to high coupling.
|
- **Containers**. Provides declarative and dynamic containers.
|
||||||
|
See `Containers <http://python-dependency-injector.ets-labs.org/containers/index.html>`_.
|
||||||
When the cohesion is high the coupling is low.
|
- **Performance**. Fast. Written in ``Cython``.
|
||||||
|
- **Typing**. Provides typing stubs, ``mypy``-friendly.
|
||||||
Low coupling brings a flexibility. Your code becomes easier to change and test.
|
See `Typing and mypy <http://python-dependency-injector.ets-labs.org/providers/typing_mypy.html>`_.
|
||||||
|
- **Maturity**. Mature and production-ready. Well-tested, documented and supported.
|
||||||
How to implement dependency injection?
|
|
||||||
--------------------------------------
|
|
||||||
|
|
||||||
Objects do not create each other anymore. They provide a way to inject the dependencies instead.
|
|
||||||
|
|
||||||
Before:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_key = os.getenv('API_KEY') # <-- the dependency
|
|
||||||
self.timeout = os.getenv('TIMEOUT') # <-- the dependency
|
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.api_client = ApiClient() # <-- the dependency
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
service = Service()
|
|
||||||
|
|
||||||
|
|
||||||
After:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
|
|
||||||
class ApiClient:
|
|
||||||
|
|
||||||
def __init__(self, api_key: str, timeout: int):
|
|
||||||
self.api_key = api_key # <-- the dependency is injected
|
|
||||||
self.timeout = timeout # <-- the dependency is injected
|
|
||||||
|
|
||||||
|
|
||||||
class Service:
|
|
||||||
|
|
||||||
def __init__(self, api_client: ApiClient):
|
|
||||||
self.api_client = api_client # <-- the dependency is injected
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT')))
|
|
||||||
|
|
||||||
``ApiClient`` is decoupled from knowing where the options come from. You can read a key and a
|
|
||||||
timeout from a configuration file or even get them from a database.
|
|
||||||
|
|
||||||
``Service`` is decoupled from the ``ApiClient``. It does not create it anymore. You can provide a
|
|
||||||
stub or other compatible object.
|
|
||||||
|
|
||||||
Flexibility comes with a price.
|
|
||||||
|
|
||||||
Now you need to assemble the objects like this::
|
|
||||||
|
|
||||||
service = Service(ApiClient(os.getenv('API_KEY'), os.getenv('TIMEOUT')))
|
|
||||||
|
|
||||||
The assembly code might get duplicated and it'll become harder to change the application structure.
|
|
||||||
|
|
||||||
Here comes the ``Dependency Injector``.
|
|
||||||
|
|
||||||
What does the Dependency Injector do?
|
|
||||||
-------------------------------------
|
|
||||||
|
|
||||||
With the dependency injection pattern objects loose the responsibility of assembling the
|
|
||||||
dependencies. The ``Dependency Injector`` absorbs that responsibility.
|
|
||||||
|
|
||||||
``Dependency Injector`` helps to assemble the objects.
|
|
||||||
|
|
||||||
It provides a container and providers that help you with the objects assembly. When you
|
|
||||||
need an object you get it from the container. The rest of the assembly work is done by the
|
|
||||||
framework:
|
|
||||||
|
|
||||||
.. code-block:: python
|
.. code-block:: python
|
||||||
|
|
||||||
|
@ -180,28 +100,18 @@ framework:
|
||||||
|
|
||||||
service = container.service()
|
service = container.service()
|
||||||
|
|
||||||
Retrieving of the ``Service`` instance now is done like this::
|
With the ``Dependency Injector`` you keep **application structure in one place**.
|
||||||
|
This place is called **the container**. You use the container to manage all the components of the
|
||||||
|
application. All the component dependencies are defined explicitly. This provides the control on
|
||||||
|
the application structure. It is **easy to understand and change** it.
|
||||||
|
|
||||||
service = container.service()
|
.. figure:: https://raw.githubusercontent.com/wiki/ets-labs/python-dependency-injector/img/di-map.svg
|
||||||
|
:target: https://github.com/ets-labs/python-dependency-injector
|
||||||
|
|
||||||
Objects assembling is consolidated in the container. When you need to make a change you do it in
|
*The container is like a map of your application. You always know what depends on what.*
|
||||||
one place.
|
|
||||||
|
|
||||||
When doing a testing you call the ``container.api_client.override()`` to replace the real API
|
Visit the docs to know more about the
|
||||||
client with a mock:
|
`Dependency injection and inversion of control in Python <http://python-dependency-injector.ets-labs.org/introduction/di_in_python.html>`_.
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from unittest import mock
|
|
||||||
|
|
||||||
|
|
||||||
with container.api_client.override(mock.Mock()):
|
|
||||||
service = container.service()
|
|
||||||
|
|
||||||
You can override any provider with another provider.
|
|
||||||
|
|
||||||
It also helps you in configuring project for the different environments: replace an API client
|
|
||||||
with a stub on the dev or stage.
|
|
||||||
|
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
@ -215,6 +125,15 @@ Documentation
|
||||||
|
|
||||||
The documentation is available on the `Read The Docs <http://python-dependency-injector.ets-labs.org/>`_
|
The documentation is available on the `Read The Docs <http://python-dependency-injector.ets-labs.org/>`_
|
||||||
|
|
||||||
|
Examples
|
||||||
|
--------
|
||||||
|
|
||||||
|
Choose one of the following:
|
||||||
|
|
||||||
|
- `Application example (single container) <http://python-dependency-injector.ets-labs.org/examples/application-single-container.html>`_
|
||||||
|
- `Application example (multiple containers) <http://python-dependency-injector.ets-labs.org/examples/application-multiple-containers.html>`_
|
||||||
|
- `Decoupled packages example (multiple containers) <http://python-dependency-injector.ets-labs.org/examples/decoupled-packages.html>`_
|
||||||
|
|
||||||
Tutorials
|
Tutorials
|
||||||
---------
|
---------
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user