Как правильно организовать проверки в коде 1С: функции с возвратом Булево или параметр Отказ?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При проектировании алгоритмов валидации данных в 1С разработчики часто сталкиваются с дилеммой: как оформить код проверок? С одной стороны, можно использовать логические функции, возвращающие Истина или Ложь. С другой стороны, часто применяется процедурный подход с передачей входного параметра Отказ, изменяемого по ссылке. Разберем по шагам, в каких ситуациях каждый подход считается стандартом, какие подводные камни скрывает неявная мутация данных и как писать чистый, поддерживаемый код.

Вариант 1. Чистые функции с возвратом булева значения (рекомендуемый подход)

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

Посмотрим на пример правильной организации вызова:


Если НЕ ДанныеЗаполненыКорректно(ДокументОбъект) Тогда
    Возврат;
КонецЕсли;

Рассмотрим преимущества такого подхода:

  1. Отсутствие побочных эффектов: В языке 1С параметры по умолчанию передаются по ссылке. Процедура с сигнатурой ПроверитьДанные(Отказ) неявно модифицирует переданную переменную, что затрудняет отладку и чтение кода. Функция же возвращает явный результат.
  2. Читаемость и прозрачность потока данных: Глядя на вызов функции в конструкции Если НЕ ... Тогда, разработчик сразу понимает логику ветвления алгоритма без необходимости переходить внутрь процедуры.
  3. Клиент-серверная оптимизация: При контекстных вызовах между клиентом и сервером передача изменяемых параметров приводит к их двусторонней сериализации и маршалингу данных, тогда как возврат простого значения булева типа минимизирует накладные расходы.
  4. Удобство модульного тестирования: Чистую логическую функцию легко покрыть автоматизированными тестами, проверяя входные данные и ожидаемый ответ Истина/Ложь.

Вариант 2. Использование переменной Отказ (событийная и накопительная модель)

Переменная Отказ широко используется в платформе 1С, однако у нее есть строго определенное назначение. Ее применение оправдано в двух ключевых сценариях:

  1. Обработчики событий платформы: Стандартные события форм и объектов (ПередЗаписью, ОбработкаПроведения, ПриОткрытии и др.) изначально содержат системный параметр Отказ. Здесь задача платформы — получить сигнал об отмене действия.
  2. Накопительная валидация (продолжение проверок): Когда необходимо выполнить сразу несколько независимых проверок, вывести пользователю полный список всех найденных ошибок и только потом прервать операцию.

Проанализируем пример накопительного сбора ошибок:


Отказ = Ложь;

ПроверитьЗаполнениеШапки(Отказ, ЭтотОбъект);
ПроверитьТабличнуюЧасть(Отказ, ЭтотОбъект);
ПроверитьОстаткиНаСкладе(Отказ, ЭтотОбъект);

Если Отказ Тогда
    Возврат;
КонецЕсли;

При использовании переменной Отказ необходимо строго соблюдать стандарты разработки платформы 1С:

  1. Запрет сброса флага (кумулятивность): Параметру Отказ категорически запрещено явно присваивать значение Ложь внутри вспомогательных методов. Если одна проверка уже установила флаг в значение Истина, последующая процедура не должна его затирать. Значение должно только накапливаться.

Посмотрим на пример безопасной установки флага внутри процедуры:


Процедура ПроверитьТабличнуюЧасть(Отказ, ДокументОбъект) Экспорт
    
    Если ДокументОбъект.Товары.Количество() = 0 Тогда
        // Накапливаем флаг отказа, не сбрасывая его в Ложь
        Отказ = Истина;
        
        // Информируем пользователя о причине отказа
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = НСтр("ru = 'Табличная часть не может быть пустой!'");
        Сообщение.Поле = "Товары";
        Сообщение.УстановитьДанные(ДокументОбъект);
        Сообщение.Сообщить();
    КонецЕсли;
    
КонецПроцедуры
  1. Обязательное информирование: Установка флага Отказ = Истина; обязательно должна сопровождаться формированием объекта СообщениеПользователю. Если отменить проведение или запись молча, платформа выдаст стандартную системную ошибку (например, «Не удалось записать документ»), не объясняя пользователю причину.
  2. Ограничения в расширениях: В расширениях конфигурации для перехватчиков &После платформенных событий вызов исключения платформы запрещает изменение параметра, отменяющего действие. Это еще одна причина избегать неконтролируемого использования входных параметров-флагов в прикладном коде.

Вариант 3. Паттерн «Результат операции» (Result Object)

Если в результате проверки требуется вернуть не только факт успеха или ошибки, но и сопроводительную информацию (текст ошибки, код сбоя или вычисленные данные), ни булева функция, ни мутация переменной Отказ не являются оптимальными. В таких случаях стандартом считается возврат объекта структуры.

Разберем пример реализации через структуру:


Функция ПроверитьВозможностьОтгрузки(ЗаказКлиента) Экспорт
    
    Результат = Новый Структура;
    Результат.Вставить("Успех", Истина);
    Результат.Вставить("ТекстОшибки", "");
    
    Если ЗаказКлиента.СуммаДокумента <= 0 Тогда
        Результат.Успех = Ложь;
        Результат.ТекстОшибки = НСтр("ru = 'Сумма заказа должна быть больше нуля.'");
        Возврат Результат;
    КонецЕсли;
    
    // Дополнительные проверки состояния взаиморасчетов
    
    Возврат Результат;
    
КонецФункции

Посмотрим, как аккуратно выглядит обработка такого вызова в вызывающем коде:


РезультатПроверки = ПроверитьВозможностьОтгрузки(ТекущийЗаказ);
Если НЕ РезультатПроверки.Успех Тогда
    ОбщегоНазначенияКлиентСервер.СообщитьПользователю(РезультатПроверки.ТекстОшибки);
    Возврат;
КонецЕсли;

Критическая валидация: механизм исключений

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


Если Остаток < ТребуемоеКоличество Тогда
    ВызватьИсключение НСтр("ru = 'Недостаточно остатка товара на складе для списания.'");
КонецЕсли;

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

Итоги и рекомендации

Подведем практический итог для выбора архитектурного решения:

  1. Для автономных, изолированных проверок всегда используем Функции, возвращающие булево (Истина / Ложь). Имя метода должно быть предикатом: ДанныеЗаполнены(), ПроверкаПройдена().
  2. Параметр Отказ используем в стандартных событиях платформы и в блоках комплексной валидации, когда цель — собрать все ошибки за один проход без немедленного прерывания цепочки проверок. При этом никогда не сбрасываем флаг в Ложь.
  3. Если валидация предполагает возврат причины отказа или служебных данных, применяем Структуру результата.
  4. Никогда не используем тип Неопределено в качестве признака отрицательного результата проверки: это значение должно означать лишь невозможность выполнения операции или отсутствие инициализированного значения.
← На главную