Почему не стоит вызывать метод Записать() внутри процедуры ОбработкаПроведения?

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

В процессе разработки на платформе 1С:Предприятие мы часто сталкиваемся с необходимостью оптимизации или рефакторинга чужого кода. Одной из типичных «ошибок новичка» или примеров неудачного проектирования является попытка принудительно записать объект документа непосредственно в процессе его проведения.

Давайте разберем, почему использование ЭтотОбъект.Записать() внутри ОбработкаПроведения является крайне нежелательным действием и к каким последствиям это может привести.

Основные причины отказа от метода Записать() при проведении

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

  1. Избыточные транзакции и снижение производительности. Вызов Записать() внутри уже запущенной транзакции создает лишнюю нагрузку на сервер СУБД. При массовом проведении документов это приводит к кратному замедлению работы системы.
  2. Риск возникновения взаимоблокировок (Deadlocks). Поскольку объект уже находится в состоянии записи, попытка снова его записать может вызвать конфликт блокировок между сеансами, что приведет к ошибкам «Конфликт блокировок при выполнении транзакции» и отказу от проведения документов.
  3. Побочные эффекты событий записи. Повторный вызов Записать() снова запустит обработчики событий ПередЗаписью и ПриЗаписи. Это может привести к непредсказуемым результатам: повторной отправке уведомлений, лишнему обновлению статусов или ошибочному выполнению фоновых задач.
  4. Нарушение идеологии платформы. Механизм проведения предназначен исключительно для формирования движений по регистрам. Если в шапку документа необходимо записать результат расчетов, значит, сама модель данных спроектирована неоптимально.

Как правильно поступать в таких ситуациях?

Если в процессе проведения вы получаете данные, которые необходимо сохранить, рассмотрите следующие варианты архитектурных решений:

1. Использование регистров сведений

Вместо того чтобы хранить рассчитанные данные в реквизитах самого документа, вынесите их в РегистрСведений. Это позволит хранить информацию отдельно, легко получать ее с помощью запросов и не перегружать основной объект документа.

2. Перенос логики в процедуру ПередЗаписью

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


// Пример корректного подхода: расчет данных перед записью
Процедура ПередЗаписью(Отказ, РежимЗаписи, РежимПроведения)
    // Рассчитываем сумму или себестоимость до того, как документ попадет в базу
    ЭтотОбъект.СуммаДокумента = РассчитатьИтоговуюСумму();
КонецПроцедуры

3. Анализ необходимости сохранения данных в реквизитах

Часто разработчики пытаются сохранить себестоимость или сумму списания в шапку документа просто для того, чтобы «видеть цифру в журнале». Проанализируйте, действительно ли это нужно для логики работы программы или это просто привычка. Для отображения итоговых сумм в журналах документов лучше использовать механизмы вывода данных в списках или отчеты по регистрам накопления, где и должны храниться все движения документа.

Помните, что чистота кода и соответствие архитектурным принципам платформы 1С — это залог стабильной работы системы под высокой нагрузкой. Избегайте «костылей» в виде принудительной записи объекта там, где это противоречит жизненному циклу транзакции!

← На главную