В процессе разработки на платформе 1С:Предприятие 8 часто возникает соблазн сократить программный код, сделав его более лаконичным. Одним из таких примеров является попытка объединить переход к следующей записи выборки и проверку условий этой записи в одном выражении Если. На первый взгляд это кажется удобным, но на практике такая конструкция таит в себе серьезные угрозы — от нестабильной работы программы до катастрофического падения производительности. В этой статье мы подробно проанализируем, почему так писать нельзя, и разберем правильные подходы к решению задачи.
Рассмотрим ситуацию, когда разработчик пишет следующий код:
Если Выборка.Следующий() И Выборка.Номенклатура.Наименование <> "ххх" Тогда
// Обработка данных
КонецЕсли;
Проанализируем механику работы этого условия. В многих современных языках программирования (таких как C#, Java или Python) реализованы так называемые короткие (ленивые) вычисления. Это значит, что если первая часть условия с оператором И возвращает Ложь, то вторая часть даже не вычисляется, так как результат всего выражения уже предопределен.
Однако в языке 1С логические операторы не являются короткими. Платформа всегда пытается вычислить все части выражения, независимо от того, что вернула первая функция. Рассмотрим, что произойдет, когда выборка дойдет до последней записи:
Выборка.Следующий() возвращает Ложь, так как данных больше нет.Выборка.Номенклатура.Наименование.Ложь), обращение к полям выборки вызывает исключение (ошибку выполнения): "Чтение после конца выборки" или "Ошибка обращения к полю".Таким образом, использование вложенных условий Если...Тогда — это не избыточность, а техническая необходимость для обеспечения стабильности кода. Правильная структура обхода должна выглядеть так:
Пока Выборка.Следующий() Цикл
Если Выборка.Наименование <> "ххх" Тогда
// Безопасная обработка
КонецЕсли;
КонецЦикла;
Проанализируем еще одну критическую деталь в исходном примере: обращение Выборка.Номенклатура.Наименование. В терминах платформы 1С это называется разыменованием ссылочного поля.
Когда мы обращаемся через точку к реквизиту объекта (например, к наименованию номенклатуры), который не был явно выбран в тексте запроса, система вынуждена выполнить неявный дополнительный запрос к базе данных. Выясним причину, почему это плохо:
Рассмотрим, как правильно подготовить данные еще на этапе формирования запроса. Вместо фильтрации во встроенном языке, мы должны максимально использовать возможности SQL-сервера.
Самый эффективный способ решить задачу — это перенести условие непосредственно в секцию ГДЕ текста запроса. Давайте посмотрим на пример:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка КАК Номенклатура,
| Номенклатура.Наименование КАК Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Наименование <> &ИсключаемоеНаименование";
Запрос.УстановитьПараметр("ИсключаемоеНаименование", "xxxxxxxxxx");
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Здесь только полезная нагрузка, фильтрация уже выполнена СУБД
КонецЦикла;
Преимущества этого подхода:
ГДЕ произойдет мгновенно, в то время как обход в цикле требует полного сканирования всех данных.Иногда возникают ситуации, когда условие невозможно наложить в запросе (например, если проверка зависит от сложной логики во внешних функциях или временных переменных, недоступных в языке запросов). В этом случае мы должны придерживаться стандартов разработки 1С:
1. Явно выбирайте реквизиты. Если вам нужно наименование, добавьте его в секцию ВЫБРАТЬ запроса. Тогда обращение Выборка.Наименование не вызовет дополнительного обращения к серверу БД.
2. Используйте вложенные Если. Разделим проверку состояния выборки и проверку данных:
Пока Выборка.Следующий() Цикл
// Условие внутри цикла безопасно, так как мы гарантированно стоим на записи
Если Выборка.Наименование <> "ххх" Тогда
// Обработка
КонецЕсли;
КонецЦикла;
Мы проанализировали конструкцию Если Выборка.Следующий() И ... и выяснили, что она является ошибочной из-за отсутствия сокращенного вычисления логических выражений в 1С. Стремление к экономии строк кода в данном случае ведет к нестабильности системы.
Запомним основные правила качественного кода:
Следующий() с другими условиями в одной строке через И.ГДЕ).Соблюдение этих простых принципов сделает ваш код профессиональным, производительным и устойчивым к ошибкам на больших объемах данных.