В прошлом модуле мы раздавали обязанности: кому считать сумму, кто создаёт объект, кто принимает событие. Допустим, раздали удачно – классы получились связные, зависимостей немного. Остался вопрос, на который GRASP не отвечает: что случится с этой конструкцией, когда требования изменятся?
Меняются они всегда. Появится второй способ оплаты, бухгалтерия попросит другой формат отчёта, у отчёта появится третий вид. SOLID – это пять проверок на то, во что обойдётся такое изменение: придётся ли переписывать работающий код, сломается ли что-то в стороне и где именно конструкция треснет.
Откуда взялся SOLID
Принципы собрал Роберт Мартин (Robert C. Martin) – тот самый «дядюшка Боб», которого в России знают по жёлтой книге с кузнечиком. Собрал – точное слово: он не придумывал их с нуля, а свёл вместе идеи, которые к тому моменту уже существовали по отдельности. Открытость-закрытость сформулировал Бертран Мейер ещё в 1988-м, принцип подстановки – Барбара Лисков в конце 80-х, а разделение интерфейсов выросло из вполне конкретной работы Мартина над софтом для принтеров Xerox.
Собранными в одном месте принципы впервые появились в статье «Design Principles and Design Patterns» (2000), а подробный разбор с примерами – в книге «Agile Software Development, Principles, Patterns, and Practices» (2002). «Чистый код» вышел позже, в 2008-м, и он не про SOLID: там речь про имена, функции и работу с кодом руками. Читать его стоит, но за принципами – в две другие книги, «Agile Software Development» и «Чистую архитектуру» (2017).
Сам акроним появился ещё позже: буквы в удобное слово сложил Майкл Фэзерс (Michael Feathers) в середине 2000-х. Порядок букв – результат этой перестановки, а не последовательность изучения: SRP и DIP связаны теснее, чем соседние по алфавиту буквы.
SOLID – не продолжение GRASP и не его замена: это независимый набор, появившийся примерно тогда же. GRASP отвечает на вопрос «кому поручить обязанность», SOLID – «переживёт ли это изменение требований».
Пять принципов
| Буква | Принцип | О чём | От чего защищает |
|---|---|---|---|
| S | Single Responsibility | у класса одна причина меняться | правка для бухгалтерии ломает вёрстку писем |
| O | Open–Closed | расширять, не переписывая | каждый новый вариант правит работающий код |
| L | Liskov Substitution | наследник не подводит того, кто ждал предка | код, написанный под базовый класс, падает на наследнике |
| I | Interface Segregation | узкие интерфейсы вместо одного широкого | реализация обязана уметь то, что ей не нужно |
| D | Dependency Inversion | зависеть от абстракций, а не от реализаций | смена библиотеки правит половину проекта |
Чего SOLID не обещает
Принципы часто цитируют как заповеди, поэтому сразу оговорим границы.
- Это не критерии «правильного» кода. Соблюсти все пять до буквы – значит развести интерфейсы над каждым классом и получить разрушительное расцепление: границ много, смысла мало.
- Формулировки не окончательные. Тот же SRP Мартин уточнял годами: от «одной причины для изменения» до «одного заказчика, который приходит с требованиями», – потому что первую версию все понимали как «класс должен быть маленьким».
- Они про объектный код. В функциональном коде часть из них теряет смысл или выглядит совсем иначе.
- Критика тоже полезна. Разбор Кевлина Хенни «SOLID Deconstruction» – о том, какие из пяти принципов говорят об одном и том же и что в них устарело; ссылки собраны в методических материалах.
Читая следующие уроки, держите в голове не букву, а вопрос за ней: «что придётся переписать, когда это изменится». Принцип, применённый там, где ничего не меняется, – просто лишний код.