Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI26 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
DIP (Dependency Inversion Principle) — Принцип Инверсии Зависимостей
DIP — один из пяти принципов SOLID, который гласит: зависимости должны быть от абстракций (интерфейсов), а не от конкретных реализаций. Высокоуровневые модули не должны зависеть от низкоуровневых модулей; оба должны зависеть от абстракций.
Основная идея
// ❌ Нарушение DIP — высокий уровень зависит от низкого
class OrderService {
private MySQLDatabase $db; // Зависит от конкретной БД!
public function __construct() {
$this->db = new MySQLDatabase();
}
public function createOrder($data) {
return $this->db->insert('orders', $data);
}
}
// Проблемы:
// - Сложно менять БД (MySQL → PostgreSQL → MongoDB)
// - Сложно тестировать (нужна реальная БД)
// - Класс делает слишком много (создаёт зависимость сам)
Правильное решение — инверсия зависимостей:
// ✅ Соблюдение DIP — зависимость от интерфейса
interface DatabaseInterface {
public function insert(string $table, array $data);
public function find(string $table, int $id);
}
class MySQLDatabase implements DatabaseInterface {
public function insert(string $table, array $data) {
// MySQL реализация
}
public function find(string $table, int $id) {
// MySQL реализация
}
}
class OrderService {
private DatabaseInterface $db; // Зависит от интерфейса!
public function __construct(DatabaseInterface $db) {
$this->db = $db;
}
public function createOrder($data) {
return $this->db->insert('orders', $data);
}
}
Основные правила DIP
- Высокоуровневые модули должны зависеть от абстракций — заказ зависит от интерфейса БД, не от MySQL
- Низкоуровневые модули тоже от абстракций — MySQL реализует интерфейс БД
- Абстракции не зависят от деталей — интерфейс не меняется, когда меняется реализация
Внедрение зависимостей (Dependency Injection)
// ✅ Инъекция через конструктор (лучший способ)
class UserService {
public function __construct(
private DatabaseInterface $db,
private EmailInterface $email,
private LoggerInterface $logger
) {}
public function register(string $email, string $password) {
try {
$user = $this->db->insert('users', [
'email' => $email,
'password' => bcrypt($password)
]);
$this->email->send($email, 'Welcome!');
$this->logger->log('User registered');
return $user;
} catch (Exception $e) {
$this->logger->log('Registration failed');
throw $e;
}
}
}
Контейнер зависимостей
// ✅ Централизованное управление зависимостями
class Container {
private array $bindings = [];
public function bind(string $key, $value) {
$this->bindings[$key] = $value;
}
public function get(string $key) {
if (isset($this->bindings[$key])) {
$binding = $this->bindings[$key];
return is_callable($binding) ? $binding($this) : $binding;
}
throw new Exception('Binding not found');
}
}
// Регистрируем зависимости
$container = new Container();
$container->bind('db', fn($c) => new MySQLDatabase());
$container->bind('email', fn($c) => new SMTPEmail());
$container->bind('logger', fn($c) => new FileLogger());
$container->bind('userService', fn($c) => new UserService(
$c->get('db'),
$c->get('email'),
$c->get('logger')
));
DIP в архитектуре (Domain-Driven Design)
// ✅ Правильная иерархия зависимостей
namespace App\Domain;
interface UserRepository {
public function findById(int $id): ?User;
public function save(User $user): void;
}
interface EmailService {
public function send(string $to, string $subject, string $body): void;
}
// Бизнес-логика зависит от интерфейсов
class RegisterUserUseCase {
public function __construct(
private UserRepository $users,
private EmailService $email
) {}
public function execute(string $email, string $password): User {
$user = new User($email, bcrypt($password));
$this->users->save($user);
$this->email->send($email, 'Welcome', 'Thanks for signing up!');
return $user;
}
}
Преимущества DIP
- Слабая связанность — модули независимы друг от друга
- Легче тестировать — можно подменять реализации на mock'и
- Гибкость — просто меняешь реализацию интерфейса
- Масштабируемость — легко добавлять новые реализации
- Чистая архитектура — логика отделена от деталей реализации