Как проверить нарушение принципа открытости-закрытости на кодревью
Что проверяют
Умеете ли вы увидеть нарушение в конкретном диффе, а не пересказать определение из SOLID. Хороший ревьюер отличает исправление бага от правки, которая добавляет новый вариант поведения в работающий класс. Следом обычно просят показать, как такой код переписать и когда переписывать не стоит.
Как отвечать
Главный вопрос на ревью: что придётся менять, когда появится ещё один вариант. Признаки нарушения:
- растущий
switch: поenumили типу, и каждая задача добавляет в него ветку. Особенно тревожно, когда такой жеswitchпо тому жеenumживёт в нескольких местах; - проверки типа:
if (x is PdfReport), приведения и паттерн-матчинг по конкретным классам внутри общего сервиса; - дробовой дифф: одна новая фича задевает пять старых файлов, хотя логика у неё своя;
- флаги в сигнатуре: к методу добавляют
bool isExport, а внутри появляется ещё одна ветка.
Лечится это точкой расширения. Вариант поведения выносится в интерфейс, например IReportFormatter, каждая реализация регистрируется в контейнере, а сервис получает IEnumerable<IReportFormatter> и выбирает нужную по свойству. С .NET 8 для этого есть keyed services: AddKeyedScoped<IReportFormatter, PdfFormatter>("pdf") и атрибут [FromKeyedServices("pdf")]. Новый формат теперь это новый класс и одна строка регистрации, старый код не трогается. Другие инструменты: декоратор для сквозной логики, события, конвейер middleware в ASP.NET Core.
Оговорите границу: OCP касается тех осей изменений, которые реально ожидаются. switch по дням недели или по закрытому набору статусов нарушением не является.
Где спотыкаются
Считают нарушением любой switch и любое изменение старого класса. Исправление бага или рефакторинг это нормальная правка, принцип говорит о добавлении нового поведения.
Предлагают интерфейс с единственной реализацией «на будущее». Абстракция без второго варианта только усложняет навигацию, и на ревью это такая же проблема, как растущий switch.
Путают OCP с SRP. Громоздкий класс нарушает прежде всего единственную ответственность, а OCP проверяется конкретным сценарием: добавьте новый вариант и посмотрите, сколько старого кода пришлось править.