Что такое SOLID?

SOLID — это аббревиатура, в которой содержатся 5 принципов ОО-дизайна...

Posted by Марк Мельник on May 4, 2013
SOLID — это аббревиатура, в которой содержатся 5 принципов ОО-дизайна.
  • S (SRP) — Single Responsibility Principle
  • O (OCP) — Open/Closed Principle
  • L (LSP) — Liskov Substitution Principle
  • I (ISP) — Interface Segregation Principle
  • D (DIP) — Dependency Inversion Principle

WTF do you mean?

Single Responsibility Principle — Принцип единственной ответственности. Каждая сущность имеет один единственный домен ответственности. Сущность должна быть такой, чтобы деление ее функционала было бессмысленным. Другими словами сущность — квант ответственности.

Open/Closed Principle — Принцип открытости-закрытости. Сущности обязаны быть открыты для расширения, но не для изменения.

В чем разница?

Разработчику должна быть предоставлена возможность добавлять в сущность методы, но не изменять существующие. Разработчику должна быть предоставлена возможность добавлять свойства в набор свойств сущности, но не удалять их. То есть, должна быть возможность сделать больше, но не по другому.

Liskov Substitution Principle — Принцип подстановки Барбары Лисков. Оригинальные объекты могут быть заменены их наследниками без изменения кода приложения.

В чем заключается фишечка? Или покажи мне пример!

Допустим мы занимаемся разработкой очередного замечательного веб-фреймворка на Ruby. В качестве интерфейса взаимодействия с сервером используем самый вкусный, сочный, сладкий, нет, не арбуз, а Rack. В коде нашего приложения (фреймворка) мы использовали экземпляры класса Rack::Request, но затем пришли к тому, что функционала у этих объектов маловато. Можно перейти к т.с. функциональному стилю и делать что-то вроде:

additional_method(request)

Однако мы люди адекватные, используем Ruby и ОО-парадигму, а потому должны создать свой класс Request унаследованный от Rack::Request.

class ActionDispatch::Request < Rack::Request
# some beautiful code here
end

Теперь используя экземпляры собственного Request мы получаем обратную совместимость с оригинальными объектами + дополнительный функционал. Согласно принципу подстановки Барбары Лисков система должна расширяться таким образом и при том без необходимости изменять код, который работал с прежними объектами.

Все вышесказанное, кроме примера, — это то, что написано в википедиях. Мое мнение заключается в том, что в Википедии технические статьи часто пишут очень сложным языком. Вероятно из-за того, что переводят, а не пишут сами, а еще плохо разбираются в теме. На самом деле все вышесказанное означает лишь то, что новые объекты должны подражать в своем API старым.

Interface Segregation Principle — Принцип разделения интерфейса. Множество микроинтерфейсов лучше, чем один макроинтерфейс.

Что ты хочешь сказать?

Я хочу сказать то, что необходимо дробить код и создавать пространства имен. Не нужно создавать Звезду Смерти. Нам необходима космическая флотилия! Этот принцип очень сильно пересекается с SRP.

Dependency Inversion Principle — Принцип инверсии зависимостей. Все есть относительно абстрактно. Точнее, мы должны строить систему на основе абстракций. При необходимости наслаивать одни абстракции на другие. При этом верхние слои не должны зависеть от нижних.

Что!? О чем ты!? Я тебя не понимаю!

Приведу простой пример. У нас есть super-duper крутой ActiveRecord. Волшебным образом он работает одинаково хорошо и с MySQL, и с PostgreSQL, и с MSSQL и другими СУБД. Все это потому, что ActiveRecord использует адаптеры для различных СУБД и не зависит от них.

Появилась новая CoproSQL — нам нет необходимости что-то править в ActiveRecord. Мы пишем адаптер для этой СУБД, который реализует определенный интерфейс и voila!

Что важно знать:

  • Все принципы пересекаются между собой.
  • Нарушишь один и тебя постигнет кара небесная.
  • PHP-developers не знают о SOLID (тс-с-с!).