Что такое принцип S.O.L.I.D?

Введение

Мы все сталкивались с проблемой меняющихся требований и сжатых сроков в Agile-среде. Иногда это может стать довольно громоздким, когда приложение не соответствует надлежащим шаблонам проектирования, а задача улучшения или работа по обслуживанию функций занимает больше времени, чем ожидалось бизнес-группой. Поздняя функция может оказать негативное влияние на бизнес, поэтому для приложения очень важно с самого начала следовать определенным рекомендациям по проектированию. Следование этим рекомендациям упрощает и ускоряет разработку функций, которые имеют первостепенное значение на рынке для роста бизнеса в этом постоянно меняющемся мире.

S.O.L.I.D?

ТВЕРДЫЙ означает

  1. Принцип единой ответственности
  2. Открытый/Закрытый принцип
  3. Лисков Принцип замещения
  4. Принцип разделения интерфейса
  5. Принципы инверсии зависимостей

В следующих разделах мы обсудим, как эти упомянутые принципы помогают нам создавать приложения с

  1. Модульная структура
  2. Высокая ремонтопригодность
  3. Высокая расширяемость

Принцип единой ответственности

Принцип единственной ответственности предполагает, что класс должен иметь только одну ответственность или цель. Это также можно понимать как один класс будет решать только одну и только одну проблему. Давайте посмотрим на приведенный ниже пример автомобильной парковки.

В приведенном выше примере класс DriverService содержит все методы, относящиеся к Driver, а в CarParkingService присутствуют все методы, связанные с парковкой автомобиля. Таким образом, DriverService не содержит никакой другой логики, кроме связанной с Driver.

Открытый/Закрытый принцип

Принцип Open/Closed звучит запутанно, но это означает, что класс должен быть открыт для расширения, но закрыт для модификаций. В нем говорится, что классы, которые существуют и хорошо протестированы, никогда не должны изменяться, поскольку это может привести к появлению новых ошибок. Чтобы изменить любую существующую функциональность, всегда следует расширять класс/интерфейс и переопределять функцию. Он использует базовую концепцию полиморфизма для внесения изменений в функциональность.

Лисков Принцип замещения

Принцип подстановки Лискова гласит, что если для каждого объекта x типа S существует объект y типа T, такой что для всех свойств/методов P, определенных в T, поведение P не изменяется при замене x на y, то S является подтипом Т.

Слишком много букв? Не волнуйтесь, давайте начнем медленно читать с простого примера.

Скажем, у нас есть три класса: Animal, Lion и Human:

Обратите внимание, что класс «Человек» и «Лев» является подтипом класса «Животное», или Человек и Лев унаследованы от Животного.

Теперь в приведенном выше фрагменте кода функциональность работает хорошо, когда мы создаем экземпляры двух подтипов и вызываем их метод Walk. LSP утверждает, что если мы используем базовый тип (Животное) вместо двух подтипов (Человек и Лев), функциональность не должна изменяться.

Принцип разделения интерфейса

Принцип разделения интерфейсов рекомендует создавать меньшие интерфейсы, а не создавать огромный интерфейс. Слишком много маленьких интерфейсов лучше, чем несколько больших интерфейсов. Эта идея была предложена Робертом С. Мартином во время консультирования Xerox, поэтому давайте возьмем пример класса принтера, чтобы разобраться в этом вопросе.

Рассмотрим интерфейс «IAmAPrinter»:

Дешевый принтер не может отправлять факсы, но класс вынужден реализовывать функции факса. Это когда принцип разделения интерфейса помогает нам разрабатывать лучшие интерфейсы.

Принцип инверсии зависимости

Это мой любимый принцип SOLID. Принцип инверсии зависимости гласит, что

  1. Модули высокого уровня не должны зависеть от модулей низкого уровня. Оба должны зависеть от абстракций.
  2. Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.

Давайте начнем понимать этот принцип с понимания зависимости.

Класс A зависит от класса B, значит, для создания/использования объекта класса A вам понадобится экземпляр класса B. Например, в приведенном ниже примере класс UserService тесно связан/зависим от ConsoleLogger.

Это портит принцип Open/Closed, потому что, если в будущем возникнет необходимость обновить логгер в UserService, без модификации этого класса это сделать не получится. Кроме того, UserService тесно связан с ConsoleLogger, что не позволяет UserService более высокого уровня сохранять для своих зависимостей принцип plug-n-play. Любому приложению, которое вызывает UserService, потребуется экземпляр ConsoleLogger.

Есть лучший способ справиться с такой ситуацией. Давайте введем интерфейсы (абстракции) и сделаем зависимости от них, а не от конкретных классов. (Как указано в принципе инверсии зависимостей)

Теперь этот подход упрощает переключение регистратора между ConsoleLogger или FileLogger для UserService. Каждое приложение, вызывающее UserService, может выбрать собственную реализацию ILogger, и UserService будет автоматически использовать выбранный регистратор.

На этом мы подошли к концу принципов SOLID. Я надеюсь, что статья помогла вам понять принципы.