Cum Să Implementezi Dependency Injection — Inversarea Controlului
In this tutorial, you'll learn about Cum Să Implementezi Dependency Injection. We cover key concepts, practical examples, and best practices.
Vei învăța cum să implementezi Dependency Injection (DI) și Inversion of Control (IoC) pentru a crea cod decuplat, testabil și ușor de întreținut.
Problema
Clasele care creează direct dependințele interne sunt greu de testat și de modificat. Orice schimbare într-o dependință necesită modificarea clasei părinte.
Abordarea Greșită
Crearea directă a dependințelor în constructor.
// Greșit: cuplare strânsă
class UserService {
private Database database;
public UserService() {
this.database = new Database(); // greu de testat
}
}
Abordarea Corectă
Injectarea dependințelor prin constructor.
// Corect: dependințe injectate
class UserService {
private final Database database;
private final EmailService emailService;
public UserService(Database database, EmailService emailService) {
this.database = database;
this.emailService = emailService;
}
}
Rezolvare Pas cu Pas
1. Identifică dependințele
Separă logica de business de crearea obiectelor.
from abc import ABC, abstractmethod
class UserRepository(ABC):
@abstractmethod
def find_by_id(self, user_id: int):
pass
class EmailSender(ABC):
@abstractmethod
def send(self, to: str, subject: str, body: str):
pass
2. Injectează prin constructor
class UserService:
def __init__(self, repo: UserRepository, email: EmailSender):
self._repo = repo
self._email = email
def register_user(self, user_id: int, email: str):
user = self._repo.find_by_id(user_id)
self._email.send(email, "Bun venit", "Contul tău a fost creat")
3. Configurează containerul DI
# Simple DI container
class Container:
def __init__(self):
self._services = {}
def register(self, interface, implementation):
self._services[interface] = implementation
def resolve(self, interface):
return self._services[interface]()
# Configurare
container = Container()
container.register(UserRepository, DatabaseRepository)
container.register(EmailSender, SMTPEmailSender)
# Folosire
service = UserService(
container.resolve(UserRepository),
container.resolve(EmailSender)
)
4. Testează cu mock-uri
from unittest.mock import Mock
def test_register_user():
mock_repo = Mock()
mock_email = Mock()
service = UserService(mock_repo, mock_email)
service.register_user(1, "test@example.com")
mock_repo.find_by_id.assert_called_once_with(1)
mock_email.send.assert_called_once()
Sfaturi de Prevenție
- Preferă constructor injection în loc de setter injection
- Folosește un framework DI (Spring, Google Guice, FastAPI) în proiecte mari
- Nu injecta prea multe dependințe într-o clasă (semn că clasa face prea multe)
Greșeli Comune
- Injectarea prea multor dependințe într-o singură clasă
- Service Locator anti-pattern în loc de DI propriu-zis
- Instanțierea manuală a dependințelor când există un container DI
- Dependințe ciclice care nu pot fi rezolvate de container
- Injectarea de obiecte mutable partajate între mai multe clase
Întrebări Frecvente
Construit de dezvoltatorii Doda Browser, DodaZIP și Durga Antivirus Pro. Uneltele DodaTech folosesc DI pentru module extensibile și testabile.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro