При написании логики программистам регулярно приходится проверять множество условий. Часто возникает дискуссия: как именно оформлять эти проверки, чтобы код легко читался, поддерживался и не вызывал головной боли у коллег? Рассмотрим подробнее популярную проблему — выбор между глубокой вложенностью условий и плоскими, объединенными проверками.
Проанализируем два типичных варианта написания условных конструкций.
Вариант 1: Вложенные условия
Если А Тогда
Если Б Тогда
// какие-то действия
КонецЕсли;
Если С Тогда
// какие-то действия
КонецЕсли;
Иначе
Если Д Тогда
// какие-то действия
КонецЕсли;
КонецЕсли;
Вариант 2: Плоские условия
Если А И Б Тогда
// какие-то действия
КонецЕсли;
Если А И С Тогда
// какие-то действия
КонецЕсли;
Если НЕ А И Д Тогда
// какие-то действия
КонецЕсли;
На первый взгляд разница может показаться непринципиальной. Однако современные стандарты разработки 1С и инструменты контроля качества кода однозначно отдают предпочтение второму (плоскому) варианту. Выясним причину такого выбора.
Для оценки запутанности алгоритма статические анализаторы (например, SonarQube, который активно используется в CI/CD контурах 1С) применяют метрику когнитивной сложности (Cognitive Complexity). В отличие от устаревшей цикломатической сложности, которая просто подсчитывает количество ветвлений, когнитивная метрика накладывает прогрессивный штраф за вложенность.
Разберем по шагам, как она рассчитывается:
Если дает +1 балл к сложности метода.Именно поэтому первый вариант из нашего примера объективно хуже. Он очень быстро приведет к превышению допустимых лимитов (стандартом считается не более 15 баллов на одну функцию или процедуру), и система автоматизированного контроля просто отклонит такой код.
Посмотрим на пример того, как можно дополнительно улучшить второй вариант, задействовав логическую конструкцию ИначеЕсли:
Если А И Б Тогда
// действия 1
ИначеЕсли А И С Тогда
// действия 2
ИначеЕсли НЕ А И Д Тогда
// действия 3
КонецЕсли;
Главное преимущество этого способа заключается в том, что при чтении кода моментально пропадает иллюзия параллельности: мы четко видим, что выполнится только один блок. В случае с отдельными блоками Если (без Иначе) разработчику приходится держать в памяти все условия и анализировать, могут ли они пересекаться и выполняться друг за другом.
При объединении условий часто возникает опасение: а не будет ли тратиться лишнее процессорное время на повторное вычисление переменных (например, условия А)?
Важно помнить, что платформа 1С:Предприятие применяет принцип ленивых вычислений. Проанализируем выражение Если А И Б Тогда. Платформа вычисляет значения слева направо. Если переменная А равна Ложь, система сразу же понимает, что все выражение уже не сможет стать истинным. Следовательно, операнд Б вообще не вычисляется. Это делает объединенные проверки безопасными для быстродействия и не создает лишней нагрузки.
Чтобы избежать написания огромных и вложенных друг в друга условий, давайте применим профессиональный паттерн раннего возврата (Guard Clauses). Его суть — отсечение неподходящих и ошибочных сценариев в самом начале метода при помощи оператора Возврат.
Рассмотрим применение на практике:
Если НЕ А Тогда
Возврат;
КонецЕсли;
Если Б Тогда
// Выполняем действия
Возврат;
КонецЕсли;
Если С Тогда
// Выполняем другие действия
Возврат;
КонецЕсли;
Использование раннего возврата избавляет нас от создания антипаттерна "Arrow Code" (когда код смещается вправо формой стрелы из-за множества отступов). Вся позитивная бизнес-логика остается на верхнем уровне, и процедура читается легко — линейно и строго сверху вниз.
Следует отметить, что объединение условий не всегда является универсальной "серебряной пулей". Если условия семантически различны и не связаны между собой общей бизнес-задачей, разделять их логично.
Посмотрим на пример корректного разделения уровней логики:
Если ЭтоРабочаяБаза Тогда
Если ПроверкаБизнесЛогики Тогда
// Основной алгоритм
Иначе
// Отказ
КонецЕсли;
Иначе
// Логика, специфичная только для тестовых баз
КонецЕсли;
В этом случае проверка среды (рабочая база или копия) никак не относится к логике проведения документа, поэтому объединять их через И было бы смысловой ошибкой.
Если же код внутри ваших условий все равно получается слишком большим, всегда прибегайте к декомпозиции. Выносите однотипные проверки и объемные блоки логики в отдельные функции со своими зонами ответственности. Это не только снизит когнитивную сложность до приемлемых значений, но и сделает разработку удобной и безошибочной.