← Назад к вопросам

Что такое принцип Open Closed?

2.0 Middle🔥 151 комментариев
#Микросервисы и архитектура

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое принцип Open Closed?

Принцип Open Closed (Открыт для расширения, закрыт для изменения) — это один из пяти фундаментальных SOLID принципов объектно-ориентированного дизайна, предложенных Робертом Мартином. Его суть заключается в том, что программные сущности (классы, модули, функции) должны быть открыты для расширения, но закрыты для изменения.

Смысл принципа

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

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

Пример нарушения принципа и его исправления

Рассмотрим классический пример в контексте Go.

Ситуация нарушения принципа: У нас есть функция расчета площади для различных геометрических фигур, которая требует постоянных изменений при добавлении новой фигуры.

// НЕПРАВИЛЬНО: Код открыт для изменений
type ShapeType string

const (
    CircleType    ShapeType = "circle"
    RectangleType ShapeType = "rectangle"
)

func CalculateArea(shapeType ShapeType, data interface{}) float64 {
    switch shapeType {
    case CircleType:
        circle := data.(Circle)
        return math.Pi * circle.Radius * circle.Radius
    case RectangleType:
        rect := data.(Rectangle)
        return rect.Width * rect.Height
    default:
        return 0
    }
}

Если мы захотим добавить поддержку треугольника, нам придется изменить функцию CalculateArea, дописать новый case в switch. Это прямо нарушает принцип "закрыт для изменения".

Решение в соответствии с Open Closed: Используем абстракцию — интерфейс.

// ПРАВИЛЬНО: Код открыт для расширения через новые типы
type Shape interface {
    Area() float64
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Новая функция расчета общей площади списка фигур не требует изменений при добавлении новой фигуры
func TotalArea(shapes []Shape) float64 {
    total := 0.0
    for _, shape := range shapes {
        total += shape.Area()
    }
    return total
}

Теперь, чтобы добавить поддержку треугольника, мы не изменяем TotalArea или какие-либо существующие структуры. Мы просто расширяем систему:

type Triangle struct {
    A, B, C float64 // стороны
}

func (t Triangle) Area() float64 {
    // Используем формулу Герона
    s := (t.A + t.B + t.C) / 2
    return math.Sqrt(s * (s - t.A) * (s - t.B) * (s - t.C))
}

Функция TotalArea([]Shape) продолжит работать корректно с треугольниками, так как Triangle теперь реализует интерфейс Shape. Система открыта для расширения через новые реализации интерфейса.

Как применять принцип в Go

В Go, не являющемся чисто объектно-ориентированным языком, принцип Open Closed реализуется преимущественно через:

  • Интерфейсы (interface) — главный инструмент для создания абстракций, открытых для расширения.
  • Композицию и внедрение зависимостей — поведение модуля можно расширять, передавая ему разные реализации зависимостей через интерфейсы.
  • Функции высшего порядка и замыкания — иногда поведение можно расширить, передавая функцию как аргумент, не меняя код вызывающей стороны.
  • Стратегия (Strategy pattern) и другие паттерны проектирования, построенные на интерфейсах.

Преимущества соблюдения принципа

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

Вывод

Принцип Open Closed направляет нас на создание устойчивого ядра системы через абстракции (в Go это чаще всего интерфейсы). Новые функции добавляются путем создания новых реализаций этих абстракций, что делает процесс развития программного продукта более безопасным, организованным и соответствующим инженерным лучшим практикам. Это не просто теоретическая концепция, а практический подход, который напрямую влияет на снижение стоимости поддержки и увеличение долголетия вашего кода.

Что такое принцип Open Closed? | PrepBro