Does it make sense to apply dependency inversion if it requires instantiating a dependency with default values to update them later?

24 views Asked by At

In this example a Database gets a get_image method which returns an Image. To respect the DIP the example include all the necessary interfaces.


import abc


class ImageInterface(abc.ABC):
    """Represent and manipulate images"""


class ImageParserInterface(abc.ABC):
    """Image parser"""

    @abc.abstractmethod
    def decode(self, data: str) -> ImageInterface:
        """Parse string to Image"""


class DatabaseInterface(abc.ABC):
    """Communicate with a database"""

    @abc.abstractmethod
    def get_image(self, image_id: str) -> ImageInterface:
        """Get an image stored in the database from it's id"""


class ImageRGB(ImageInterface):
    """Represent and manipulate RGB images"""


class ImageParserMongoDBToRGB(ImageParserInterface):
    """Convert result from MongoDB query to ImageRGB"""

    def decode(self, data: str) -> ImageInterface:
        """Parse string to Image"""
        return ImageRGB()


class DatabaseMongoDB(DatabaseInterface):
    """Communicate with a MongoDB database"""

    def __init__(self, image_parser: ImageParserInterface):
        self._image_parser = image_parser

    @abc.abstractmethod
    def fetch_image_data(self, image_id: str) -> str:
        ...

    def get_image(self, image_id: str) -> ImageInterface:
        image_data = self.fetch_image_data(image_id)
        return self._image_parser.decode(image_data)
   

The Dependency Inversion Principle states:

  • A1: High-level modules should not import anything from low-level modules
  • A2: Both should depend on abstractions (e.g., interfaces).
  • B1: Abstractions should not depend on details.
  • B2: Details (concrete implementations) should depend on abstractions.

A1 and B1 are respected, since all interfaces depend only on interfaces.
A2 and B2 are not, since ImageParserMongoDBToRGB depends on ImageRGB which is not an interface.

In this case would it make sense to initialize ImageParserMongoDBToRGB with an empty ImageRGB as below simply to respect the dependency inversion principle ?

class ImageParserMongoDBToRGB(ImageParserInterface):
    """Convert result from MongoDB query to ImageRGB"""

   def __init__(self, image: ImageInterface):
      self.image = image

    def decode(self, data: str) -> ImageInterface:
        """Parse string to Image"""
        self.image.data = image_data
        return self.image
1

There are 1 answers

2
David Guida On

my guess is that you are confusing dependencies with data. A dependency in your case is your MongoDB persistence layer. Actually, since you are serializing the image in a specific format, tied to your MongoDB, your DatabaseMongoDB class should take care of loading the data and mapping it to a class implementing ImageInterface.