Осторожно, вольное (опытное) трактование канонов программирования! Автор написал эту статью после безуспешных попыток научить молодых программистов «по книжкам», которое потерпело жесткое фиаско ввиду неочевидности и запутанности объяснения принципов SOLID.
Кажется нет более легкого способа бросить курить чем детально изучить принципы объектно-ориентированного программирования SOLID на примере скажем двух языков – PHP и JavaScript 😂 Перефразировав классика квантовой механики, можно с уверенностью сказать: если вы изучили SOLID и вам не стало страшно, вы не поняли SOLID.
По современным меркам (в сравнении с языком C, который появился в 1972 году) принципы хоть и не молоды, но их впервые собрал воедино в 2000-м году Роберт Мартин в авторской статье Design Principles and Design Patterns.
SOLID это мнемонический акроним, который содержит 5 принципов:
- S is for Single Responsibility Principle (Принцип единственной ответственности);
- O is for Open/Closed Principle (Принцип Открытости/Закрытости);
- L is for Liskov Substitution Principle (Принцип подстановки Барбары Лисков);
- I is for Interface Segregation Principle (Принцип разделения Интерфейса);
- D is for Dependency Inversion Principle (Принцип инверсии зависимостей);
И так, наша Азбука смерти, наш акроним расшифрован, погрузимся в каждый принцип детальнее.
Single Responsibility Principle (Принцип единственной ответственности).
Официальная формулировка, из-за которой хочется плакать: существует лишь одна причина, приводящая к изменению класса.
Фраза настолько туманная, что порождает больше вопросов чем ответов. Какая причина, зачем нам менять Класс, если мы работаем с экземплярами класса – объектами и пр.
Корректнее по моему и коллег опыту говорить об ответственности, или зоне ответственности: корзина, пользователь, администратор, плагины системы, работа с кешем, обработка запросов и ответов драйвера базы данных и пр.
Если хотите, это экранизация фразы «мухи отдельно, котлеты отдельно». Нужно семантически (или логически) разделять элементы архитектуры, не допуская пересечения функционала. Например, мы создаем бекенд для интернет-магазина с нуля (ну вот такие мы извращенцы) и нам нужно описать класс, отвечающий за работу корзины товаров. По сути нам нужен CRUD, но для товаров :) Код на PHP будет выглядеть примерно так
<?php
class Cart extends Ecommerce {
public function addToCart($data) {
//
}
public function deleteFromCart($product_id) {
//
}
public function getCartProducts() {
//
}
public function cleanCache() {
// wtf?!
}
}
Рассмотрим приведенный выше код. Класс Cart
(наследование класса Ecommerce
не имеет тут логической нагрузки) содержит 4 своих метода addToCart()
, deleteFromCart()
, getCartProducts()
, cleanCache()
. Если первые 3 явно связаны с функционалом корзины, они добавляют, удаляют или возвращают товары, то 4-й cleanCache()
чистит какой-то кеш в нашем системе, что можно считать нарушением принципа SRP, принципа единой ответственности.
Читатель должен подразумевать, что бывают еще и стереотипные роли объектов, но на данном этапе не усложняйте последовательное образование.
Пример кода и разъяснения для JavaScript будут добавлены после официального релиза ECMAScript 2019.