SOLID: O — Open-Closed Principle

SOLID: O — Open-Closed Principle

Makar M.

Введение

Второй принцип SOLID, который мы называем принципом открытости/закрытости известен с давних времён. Впервые он был сформулирован в далёком 1988 году Бертраном Мейером в своей книге «Object-Oriented Software Construction» (читать).

Еще одно требование, которое должна удовлетворять любая техника модульной декомпозиции, — это принцип открытости/закрытости. Противоречие между этими двумя терминами только кажущееся, так как они соответствуют целям разной природы:

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

• Модуль считается закрытым, если он доступен для использования другими модулями. Это предполагает, что модуль имеет четко определенное и стабильное описание (его интерфейс в контексте скрытия информации). На уровне реализации закрытость модуля также подразумевает, что его можно скомпилировать, возможно, сохранить в библиотеке и сделать доступным для других (его клиентов). В случае модуля проектирования или спецификации закрытие модуля означает, что он был утвержден руководством, добавлен в официальное хранилище проекта с принятыми программными компонентами (часто называемое базовой линией проекта) и опубликован его интерфейс для удобства других авторов модулей.. 

(«Object-Oriented Software Construction», Bertrand Meyer)

Этот принцип, несмотря на возраст, остаётся актуальным. Сегодня многие языки программирования не требуют компиляции модулей, а утверждение их спецификаций руководством наводит на мысль об устаревших каскадных методологиях. Однако сама идея, лежащая в основе этого принципа, остаётся неизменной:

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

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

Более того, если старый код остаётся неизменным, его не требуется повторно компилировать или развёртывать. Внедрение новой функциональности сводится лишь к развёртыванию новых компонентов — будь то jar, dll или gem.

А это, в свою очередь, даёт подсказку о том, какими должны быть такие компоненты: Они должны представлять собой независимые, изолируемые единицы функциональности.

Операция дробовиком

К сожалению, мы редко оказываемся в ситуации, когда система закрыта от изменений, но при этом может быть легко дополнена новым функционалом. Как это обычно бывает, добавление нового функционала производится путём внесения множества модификаций существующего кода. Мы знаем, что это плохо. И знали, что это плохо ещё до того, как Мартин Фаулер в своей книге «Refactoring: Improving the Design of Existing Code» (читать) назвал это «Shotgun Surgery» (операция дробовиком), но мы всё равно так делаем:

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

(«Refactoring: Improving the Design of Existing Code», Martin Fowler, Kent Beck, John Brant, William Opdyke, Don Roberts)

Плагины

Существует много программного обеспечения, которое можно легко расширить без их изменения или повторного развёртывания, например: IntelliJ IDEA, PyCharm, Visual Studio, Vim, Eclipse, Text Mate или тот же Minecraft. Благодаря чему мы их расширяем? Благодаря плагинам.

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

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

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

Архитектура на основе плагинов

Представьте, что дизайн вашего проекта, использующий плагины, подобен таким системам, как Vim, Minecraft или IntelliJ IDEA. Он позволяет подключать базы данных или разные графические интерфейсы как расширения, подобно тому как это делается в вашей любимой IDE. Что, если поведение вашей системы в основном зависило бы от конфигурации плагинов, а не от жёсткой связи классов с высоким зацеплением? Насколько легко было бы внедрить или удалить SOA? Насколько просто было бы добавить или убрать REST? Как легко было бы заменить или добавить фреймворки, такие как Spring (Java), Django (Python), Laravel (PHP)?

Когда ключевые бизнес-правила находятся в ядре архитектуры плагинов, вы не привязаны к конкретным функциям, базам данных, фреймворкам или чему-либо ещё.

Заключение

Я не раз слышал, что принцип OCP якобы не работает, является непрактичным и не подходит для настоящих разработчиков, которым нужно решать реальные задачи. Однако появление архитектур с плагинами наглядно демонстрирует, что такие утверждения ошибочны. Напротив, надёжная архитектура с плагинами, вероятно, станет одним из важнейших элементов программных систем будущего.

Report Page