Blueprint for a Dependency Injection (DI) pattern in Python based on container mixins.
The pattern models the dependency order in object instantiation by an invocation chain of provider methods. Provider methods are resolved in a top level container that is composed from individual containers that are provided by the implementation modules as mixins.
The following diagram visualizes this pattern with a component who's implementation depends on a
service. Instances of service are provided by the ServiceImplContainer, instances of
component in turn are provided by the ComponentImplContainer, which injects a service
instance into the component. The top level ApplicationContainer is composed of both of these
two implementation containers. Different implementations of the service can be injected into the
component by replacing the ServiceImplContainer in the ApplicationContainer with any other
container that provides a service. Application code uses the ApplicationContainer as entry
point to retrieve a component (or service) instance.
The red parts in the diagram and the respective api modules in code are not needed in Python.
They have no functional impact and can be (fully or partially) left out. They serve only the
purpose of clarity.
This is a very basic approach and comes with some shortcomings:
- You need to write quite some boilerplate code
- Dependencies are resolved purely by their method name in the container mixins, therefore you need to be careful not to run into name conflicts between different containers. In other words, method names in the container mixins need to be globally unique.
