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