Что делать, если вы нарушаете принцип OCP из SOLID?

Один из самых распространенных вопросов на собеседованиях по техническим вопросам: что такое S.O.L.I.D и можете ли вы привести несколько примеров для каждого принципа.

Существует множество ресурсов, проповедующих, как должен работать SOLID. Однако на практике дьявол кроется в деталях.

Принцип открытого-закрытого

Что это такое?

Объекты или сущности должны быть открыты для расширения, но закрыты для модификации.

Это означает, что объект должен быть расширяемым без изменения самого объекта.

Первым признаком нарушения OCP является использование операторов if-else или switch. В качестве примечания: любое разветвление if-else или switch должно вызвать небольшой вопросительный знак для возможного запаха кода.

Примеры ситуаций, которые вы можете найти в своей кодовой базе:

Представьте, что бизнес-требования изменились, и вам нужно добавить AnalyticsLogger, который будет записываться в GoogleAnalytics или в FacebookAnalytics.

Ваш класс Logger открыт для расширения, но в то же время он также будет открыт для модификации (поскольку вам действительно нужно добавить новый switch case), что нарушает правило OCP.

Давайте посмотрим на другой пример:

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

Допустим, Product Owner приходит через месяц и хочет, чтобы приложение могло хранить что-то в памяти вместо двух постоянных способов. Что происходит тогда? Еще один сценарий else if, потом еще один и так далее.

Другие сценарии могут быть, но не ограничиваются:

Мы можем ясно видеть закономерность, возникающую здесь.

Теперь естественный вопрос: как это исправить? Как мы можем предотвратить это?

Все возможные сценарии реализации должны соответствовать некоторой абстракции (интерфейсу, протоколу и т. д.), а лицо, принимающее решение о правильной реализации, должно быть перемещено выше в цепочке ответственности.

Чтобы проиллюстрировать это в примере с StorageService, мы будем использовать шаблон поведенческого проектирования под названием Strategy.

Если вы внимательно посмотрите на строку 32, а затем на строки 38–40, мы можем сделать вывод, что сущность StorageService теперь «заблокирована», закрыта для модификации и открыта для расширения. Строки 38–40 показывают нам, что мы можем добавить столько новых методов хранения, сколько нам нужно, и не менять код внутри файла StorageService.

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

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

Спасибо, что прочитали!

Следите за новостями.