SOLID. Что такое SOLID и кому это надо. Глава 3, последняя
В предыдущий двух частях SOLID. Часть 1 и SOLID. Часть 2 мы рассмотрели четыре принципа SOLID. В этой главе, финальной, наших глаз коснется пятый, последний, принцип SOLID и краткое резюме по использованию данных принципов.
Dependency Inversion. Последний принцип SOLID.
Dependency Inversion или Dependency Injection спросите вы. И я отвечу что Dependency Inversion. Так как это два разных понятия и кто-то может путать эти названия. То теперь то вы не спутаете их, правда? Теперь то вы осведомлены об этом.
Маленькими шагами мы подошли к этому принципу. Теперь давайте рассмотрим его по-подробней. Для начала разберемся что это за принцип и насколько принципиален он нам.
Код должен зависеть от абстракций, а не от конкретики.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Когда мы пишем наш код – он взаимосвязью между собой. Так вот, эта связь должна основываться на абстракциях, а не на конкретных классах.
К примеру, когда нам нужно добавить запись в MySQL – мы можем использовать конкретный класс, который будет это делать. А можем – интерфейс, тогда мы не будем так жестко связаны с реализацией. В этом случае мы сможем использовать в дальнейшем любое другое хранилище отличное от MySQL.
Чем быстрее мы перейдем к примеру – тем понятней станет. Поэтому давайте не будем терять времени.
Давайте рассмотрим приверженном, который отправляет вашу секретную информацию о вас: возраст, денежное состояние, вежи болезни, половых партнеров. Но вы тоже не пальце деланы. Вы можете попробовать предотвратить отправку данной информации по конкретному каналу. Потому Отправитель пытается раскрыть вас через множество источников: по почте, смс, email, новости. И это только начало списка.
Мы можем создать следующий класс.
Dependency Inversion. Пример.
class EmailSender { public function getData() { } public function sendData() { } } class Revealer { ... public function run(EmailSender $sender) { ... $sender->sendData(); .. } }
Здесь у нас есть класс, который отправляет email и какой-то класс Revealer. Он разбирается когда это лучше всего рассказать, и, вполне возможно, создает много других, очень плохих дел для человека.
Как видим, данный класс у нас тесно завязан на классе EmailSender. Это не очень хорошо и плохо масштабируемо. Поверьте.
Давайте немного преобразуем наш код. Для этого создадим интерфейс Sender. У него будет один метод sendData()
Далее, для отправки сообщения каждым из способов – создадим соответствующие классы, которые будут реализовывать данный интерфейс. Тогда в метод run мы будем передавать не конкретный класс, а интерфейс Sender. Таким образом бы не будем завязаны на реализации функции отправки и сможем использовать тот, который посчитаем нужным. Давайте посмотрим на это все в виде кода.
interface Sender { public function sendData() { } } class EmailSender implements Sender { public function getData() { } public function sendData() { ... } } class NewsSender implements Sender { public function sendData() { ... } } class Revealer { ... public function run(Sender $sender) { ... $sender->sendData(); .. } }
Как видим, такой способ реализации до невозможного упрощает нашу жизнь. В классе Revealer мы не завязаны на способе отправки и в дальнейшем мы можем добавлять варианты отправки на свое усмотрение. Для этого нужно будет просто реализовать интерфейс Sender.