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

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

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

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

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


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

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

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

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

Prompt
Напиши программу на Go с функцией totalArea, которая вычисляет суммарную площадь фигур с помощью switch по полю Kind (круг и прямоугольник хранятся в одной структуре с шириной, высотой и радиусом). Выведи общую площадь нескольких фигур — как плохую отправную точку для принципа открытости/закрытости.
Вывод: программа на Go и захваченный вывод

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

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

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

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

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

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

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

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

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