Dependency Inversion Principle in Python

The Dependency Inversion Principle (DIP) is a fundamental principle of object-oriented design that promotes loose coupling between components and facilitates easier maintenance and extension of software systems. In this blog, we will discuss the Dependency Inversion Principle and provide an example in Python.

Understanding the Dependency Inversion Principle

The Dependency Inversion Principle is a part of the SOLID principles of object-oriented programming. It states that high-level modules should not depend on low-level modules, but both should depend on abstractions. In other words, classes should depend on interfaces or abstract classes rather than on concrete implementations.

The Dependency Inversion Principle can be summarized in the following statement: “Depend on abstractions, not on concretions.” This means that classes should depend on abstract types rather than on concrete types.

Example of the Dependency Inversion Principle in Python

Let’s consider an example to understand the Dependency Inversion Principle in Python. Suppose we have a class name Logger that is responsible for logging messages. The Logger class has a method called log, which takes a message and logs it to a file. We also have a class named Calculator that performs mathematical calculations. The Calculator class uses the Logger class to log messages.

Here is an example of how we can implement the Logger and Calculator classes in Python while violating the Dependency Inversion Principle:

class Logger:
    def log(self, message):
        with open('log.txt', 'a') as f:
            f.write(message + '\n')

class Calculator:

    def __init__(self):
        self.logger = Logger()

    def add(self, x, y):
        result = x + y
        self.logger.log(f"Added {x} and {y}, result = {result}")
        return result

In this example, the Calculator class depends on the Logger class, which is a concrete implementation. This violates the Dependency Inversion Principle since the Calculator class is dependent on a low-level module.

Here is an example of how we can implement the Logger and Calculator classes in Python while adhering to the Dependency Inversion Principle:

from abc import ABC, abstractmethod

class LoggerInterface(ABC):
    @abstractmethod
    def log(self, message):
        pass

class Logger(LoggerInterface):
    def log(self, message):
        with open('log.txt', 'a') as f:
            f.write(message + '\n')

class Calculator:
    def __init__(self, logger: LoggerInterface):
        self.logger = logger

    def add(self, x, y):
        result = x + y
        self.logger.log(f"Added {x} and {y}, result = {result}")
        return result

In this example, we have created an abstract class called LoggerInterface, which defines a log method. We have also modified the Calculator class to accept a LoggerInterface object as a dependency in its constructor. By doing this, the Calculator class depends on an abstraction rather than on a concrete implementation of the Logger class.

Conclusion

In conclusion, the Dependency Inversion Principle is a fundamental principle of object-oriented design that promotes loose coupling between components and facilitates easier maintenance and extension of software systems. By following to this principle, we can create software systems that are more flexible and maintainable.

0
Subscribe to my newsletter

Read articles from NonStop io Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

NonStop io Technologies
NonStop io Technologies

Product Development as an Expertise Since 2015 Founded in August 2015, we are a USA-based Bespoke Engineering Studio providing Product Development as an Expertise. With 80+ satisfied clients worldwide, we serve startups and enterprises across San Francisco, Seattle, New York, London, Pune, Bangalore, Tokyo and other prominent technology hubs.