Ответ
Абстракция — это принцип ООП, который позволяет скрыть сложную внутреннюю реализацию и показать пользователю (другому разработчику) только необходимый, упрощенный интерфейс для взаимодействия.
Простыми словами: Я создаю "черный ящик". Пользователь знает, что этот ящик делает (например, отправляет уведомление), но не знает и не должен знать, как именно он это делает (через email, SMS или Slack).
Как я это применяю на практике:
- С помощью абстрактных классов и интерфейсов определяю контракт (набор методов), который должны реализовать конкретные классы.
- Клиентский код зависит от абстракции (интерфейса), а не от конкретной реализации. Это основа для соблюдения принципа DIP (Dependency Inversion).
Пример из реального проекта: Система логирования. Вместо того чтобы жестко зависеть от конкретной библиотеки логирования (например, Monolog) во всем коде, я создаю абстракцию.
// Абстракция - что мы можем делать с логгером?
interface LoggerInterface {
public function info(string $message, array $context = []): void;
public function error(string $message, array $context = []): void;
}
// Конкретная реализация, скрывающая детали работы с Monolog
class MonologLoggerAdapter implements LoggerInterface {
private MonologLogger $logger;
public function __construct() {
$this->logger = new MonologLogger('app');
$handler = new MonologHandlerStreamHandler('path/to/your.log');
$this->logger->pushHandler($handler);
}
public function info(string $message, array $context = []): void {
$this->logger->info($message, $context);
}
public function error(string $message, array $context = []): void {
$this->logger->error($message, $context);
}
}
// Сервис в приложении, который использует логгер. Он зависит только от интерфейса.
class OrderService {
public function __construct(private LoggerInterface $logger) {}
public function processOrder(Order $order): void {
try {
// ... логика обработки заказа ...
$this->logger->info('Order processed', ['order_id' => $order->id]);
} catch (Exception $e) {
$this->logger->error('Order processing failed', ['error' => $e->getMessage()]);
throw $e;
}
}
}
Преимущества такого подхода:
- Снижение связанности:
OrderServiceне знает о Monolog. - Гибкость: Завтра я могу легко заменить Monolog на другую библиотеку или отправить логи в Sentry, создав новый адаптер
SentryLoggerAdapter. Мне нужно будет изменить только конфигурацию внедрения зависимостей, а кодOrderServiceостанется прежним. - Упрощение тестирования: Я могу подставить заглушку (mock)
LoggerInterfaceв юнит-тестах дляOrderService.
Видео-ответы
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶
▶