Привет всем в 7-ом эпизоде сериала “ООП здорового человека”. В этой серии: D – последняя буква аббревиатуры 5-ти принципов SOLID – что он значит? Идемте разбираться.
Теория
Принцип имеет 2 формулировки:
- Модули верхних уровней не должны зависеть от модулей нижних уровней. Оба типа модулей должны зависеть от абстракций
- Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Представим, что есть класс по работе с БД и класс, делающий расчеты на основании того, что прилетело с БД. Таким образом, расчетный модуль ставит в зависимость модуль по работе с БД и , первый- модуль высокого уровня; второй, соответственно, более низкого уровня. Собственно, данный принцип – это следование принципу LSP и OSP.
Примеры
№1: рассмотрим все тот же пример с БД и расчетами: однажды, по какой-нибудь причине может понадобиться переключится на иную БД.
№2: ближе к жизни. Человек передвигался на велосипеде, нафармил денег – купил машину. Здесь уже DIP сохранен, постольку, и велик, и тачка, созданы для управление руками и ногами.
Практика
Рассмотрим пример с велосипедом и машиной. В самом простом случаи(без всяких принципов), начальная позиция выглядит так
<?php
class Human
{
function move()
{
$transport = new Bicycle();
$transport->getMaxSpeed();
}
}
class Bicycle
{
function getMaxSpeed()
{}
}затем мы класс Bicycle заменяем классом Car. В моем коде это одноо место, в боевом коде же- их будет много; лазить по коду и везде переписывать – как минимум – долго(не говоря о возникших багах). Следующей ступенью развития может быть использование Внедрение зависимостей (Dependency injection)
<?php
class Human
{
public function __construct(private Bicycle $transport)
{
}
function move()
{
$this->transport->getMaxSpeed();
}
}это уже лучше – один раз на класс это делаем в конструкторе; но если классов где нужно переключить много?
В этом случаи на помощь придет вместо обращения к классу, обращение к интерфейсу(или абстрактному классу) и, по средству позднего связывания, дергать нужный класс
<?php
class Human
{
public function __construct(private TransportInterface $transport)
{
}
function move()
{
$this->transport->getMaxSpeed();
}
}
class Bicycle implements TransportInterface
{
function getMaxSpeed()
{}
}
interface TransportInterface
{
function getMaxSpeed();
}таким образом, остается лишь указать класс-реализатор нужного интерфейса.