Problem Statement
When high-level modules depend directly on low-level modules, changes in low-level details force changes in high-level logic. This tight coupling makes the system fragile and hard to maintain or extend.
This diagram shows both high-level and low-level modules depending on a shared abstraction, which decouples their implementations.
### Before applying Dependency Inversion Principle (tightly coupled) class MySQLDatabase: def connect(self): print("Connecting to MySQL database") class UserService: def __init__(self): self.db = MySQLDatabase() # Direct dependency def get_user(self, user_id): self.db.connect() print(f"Fetching user {user_id}") ### After applying Dependency Inversion Principle (depends on abstraction) from abc import ABC, abstractmethod class Database(ABC): @abstractmethod def connect(self): pass class MySQLDatabase(Database): def connect(self): print("Connecting to MySQL database") class UserService: def __init__(self, db: Database): self.db = db # Depends on abstraction def get_user(self, user_id): self.db.connect() print(f"Fetching user {user_id}") # Usage mysql_db = MySQLDatabase() service = UserService(mysql_db) service.get_user(42)