Ситуация, когда в существующем коде обнаруживается «запрос в цикле», — это классический сценарий как для реальной практики, так и для проверочных тестов при приеме на работу. Рассмотрим подробно, почему такая конструкция считается критической ошибкой производительности и как грамотно подойти к решению задачи в условиях командной разработки.
Прежде чем приступать к исправлению, разберем техническую сторону проблемы. Проанализируем, что происходит на уровне системы, когда функция проверки остатка вызывается для каждой строки табличной части документа в цикле:
Deadlocks (взаимных блокировок).Рассмотрим, как превратить неоптимальный код в производительный. Вместо того чтобы передавать в функцию одну номенклатуру, мы должны научить систему работать со списком данных. Разберем этот процесс по шагам.
Шаг 1. Сбор данных из табличной части. Сначала мы выгружаем все уникальные пары Номенклатура-Серия из документа в таблицу значений или массив.
Шаг 2. Единый запрос к базе данных. Формируем запрос, который получает остатки сразу по всем позициям. Рассмотрим пример кода, который реализует оптимальную проверку:
// Подготавливаем таблицу товаров из документа
ТаблицаТоваров = Объект.Товары.Выгрузить( , "Номенклатура, Серия");
ТаблицаТоваров.Свернуть("Номенклатура, Серия");
// Создаем запрос для получения остатков по всему списку
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ВТ_Товары.Номенклатура КАК Номенклатура,
| ВТ_Товары.Серия КАК Серия
|ПОМЕСТИТЬ ВТ_ТоварыДокумента
|ИЗ
| &ТаблицаТоваров КАК ВТ_Товары
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.Серия КАК Серия,
| Остатки.ВНаличииОстаток КАК Остаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&Период, (Номенклатура, Серия) В
| (ВЫБРАТЬ Номенклатура, Серия ИЗ ВТ_ТоварыДокумента)) КАК Остатки";
Запрос.УстановитьПараметр("ТаблицаТоваров", ТаблицаТоваров);
Запрос.УстановитьПараметр("Период", ДатаПроверки);
// Загружаем результат в Соответствие для быстрого поиска в памяти
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
КэшОстатков = Новый Соответствие;
Для Каждого Стр Из РезультатЗапроса Цикл
// Ключом будет структура или строка для уникальной идентификации
Ключ = Строка(Стр.Номенклатура.УникальныйИдентификатор()) + "_" + Строка(Стр.Серия.УникальныйИдентификатор());
КлючОстатков.Вставить(Ключ, Стр.Остаток);
КонецЦикла;
Шаг 3. Быстрая проверка в цикле по кэшу. Теперь, когда данные получены одним запросом, мы можем итерировать строки документа и проверять наличие остатка в объекте Соответствие. Это выполняется в оперативной памяти мгновенно.
Вопрос в тесте проверяет не только знание 1С, но и вашу адекватность как командного игрока. Проанализируем предложенные варианты действий:
Проанализируем ситуацию комплексно и выстроим оптимальную стратегию поведения разработчика:
Важный момент: Современные стандарты разработки 1С (БСП) настоятельно рекомендуют использовать механизмы «предварительной выборки данных». Посмотрите, как это реализовано в типовых конфигурациях: перед проведением формируется временная таблица со всеми данными документа, и один запрос проверяет все условия (остатки, резервы, графики) сразу. Именно к такому подходу нужно стремиться в профессиональной разработке.
В итоге, на собеседовании лучше всего аргументировать свой выбор так: «Я сообщу руководителю о неоптимальности текущего метода. Если время позволяет, я предложу провести рефакторинг общей функции, чтобы она поддерживала пакетную обработку данных, так как это исключит проблемы с производительностью в моем новом документе и улучшит систему в целом». Это ответ зрелого разработчика уровня Senior.