Search code examples
pythonpython-3.xoopdependency-injectionsolid-principles

Dependency Inversion in Python


I've started to apply SOLID principles to my projects. All of them are clear for me, except dependency inversion, because in Python we have no change to define variable in type of some class inside another class (or maybe just I don't know). So I've realized Dependency Inversion principle in two forms, and want to know which of them is true, how can I correct them. Here are my codes:

d1.py:

class IFood:
    def bake(self, isTendir: bool): pass
    
class Production:
    def __init__(self):
        self.food = IFood()
    
    def produce(self):
        self.food.bake(True)
        
class Bread(IFood):
    def bake(self, isTendir:bool):
        print("Bread was baked")

d2.py:

from abc import ABC, abstractmethod
class Food(ABC):
    @abstractmethod
    def bake(self, isTendir): pass
    
class Production():
    def __init__(self):
        self.bread = Bread()
    
    def produce(self):
        self.bread.bake(True)
        
class Bread(Food):
    def bake(self, isTendir:bool):
        print("Bread was baked")

Solution

  • # define a common interface any food should have and implement
    class IFood:
        def bake(self): pass
        def eat(self): pass
    
    class Bread(IFood):
        def bake(self):
            print("Bread was baked")
        def eat(self):
            print("Bread was eaten")
    
    class Pastry(IFood):
        def bake(self):
            print("Pastry was baked")
        def eat(self):
            print("Pastry was eaten")
    
    class Production:
        def __init__(self, food): # food now is any concrete implementation of IFood
            self.food = food # this is also dependency injection, as it is a parameter not hardcoded
    
        def produce(self):
            self.food.bake()  # uses only the common interface
    
        def consume(self):
            self.food.eat()  # uses only the common interface
    

    Use it:

    ProduceBread = Production(Bread())
    ProducePastry = Production(Pastry())