Перейти к основному содержимому

Открыт для расширения, закрыт для изменения

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

Каждая правка работающего кода — это шанс его сломать. Когда добавление возможности означает только добавление нового кода, старый код остаётся проверенным.

Инструмент PHP для этого — интерфейс: функция, которая зависит от интерфейса, никогда не потребует изменений, когда его реализует новый класс.


switch, который никогда не перестаёт расти

Этот калькулятор площадей использует switch по виду фигуры. Он работает — до появления следующей фигуры. Треугольник? Правим switch. Пятиугольник? Правим снова. Функция никогда не бывает готова, и каждая правка ставит под угрозу фигуры, которые уже работали.

switch по виду фигуры

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

Prompt
Напиши PHP-скрипт с функцией totalArea, которая вычисляет суммарную площадь фигур с помощью switch по свойству kind (circle и rectangle хранятся в одном классе со свойствами width, height, radius). Выведи суммарную площадь нескольких фигур — как плохую отправную точку для принципа открытости/закрытости.
Вывод: PHP-скрипт

Расширяем через интерфейс

Решение: каждая фигура знает свою площадь сама. Интерфейс Shape требует один метод, area(), а totalArea просто складывает всё, что получает — ей больше не важно, что это за фигуры.

Теперь посмотрите, как принцип работает: совершенно новый Triangle подключается, а totalArea остаётся нетронутой. Расширение без изменения.

Каждая фигура сама вычисляет свою площадь

totalArea зависит только от интерфейса Shape. switch исчез — а вместе с ним и необходимость когда-либо снова править эту функцию.

Prompt
Переработай фигуры на PHP в стиле «открытость/закрытость»: интерфейс Shape с методом area, отдельные классы Circle и Rectangle, каждый из которых сам вычисляет свою площадь, и функция totalArea, которая суммирует любое количество объектов Shape без switch. Выведи сумму площадей.
Вывод: PHP-скрипт

Добавляем новую фигуру, не трогая ничего

Triangle — это чистый новый код: класс, который реализует area(). totalArea, Circle и Rectangle остались точно такими, какими были — открыты для расширения, закрыты для изменения.

Prompt
Расширь пример с интерфейсом Shape на PHP совершенно новым классом Triangle, реализующим area, не изменяя ни totalArea, ни Circle, ни Rectangle. Выведи новую сумму площадей вместе с треугольником, чтобы показать расширение без изменения.
Вывод: PHP-скрипт
Add a new shape, touch nothing