Правила работы с транзакциями 1С
Список правил при работе с транзакциями из BSL Language Server и SonarQube 1C (BSL) Plugin. Переработка и осмысление материала.
- Описание
- Подробнее
Описание
Описание диагностик из проектов BSL Language Server и SonarQube 1C (BSL) Plugin
Общепринятый паттерн
Описан в ИТС
НачатьТранзакцию();
Попытка
... // чтение или запись данных
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
... // дополнительные действия по обработке исключения
КонецПопытки;
Метод "НачатьТранзакцию" должен располагаться непосредственно перед оператором "Попытка"
Описание диагностики
Метод НачатьТранзакцию должен быть за пределами блока Попытка-Исключение непосредственно перед оператором Попытка. (с) ИТС: Транзакции: правила использования, пункт 1.3
Начало транзакции и ее фиксация (отмена) должны происходить в контексте одного метода.
Код, который начинает транзакцию, обязан завершить или откатить ее. В случаях когда метод НачатьТранзакцию() находится внутри блока Попытка-Исключение есть риск нарушения парности вызовов НачатьТранзакцию()-ЗафиксироватьТранзакцию(), что может привести к трудно анализируемым ошибкам времени выполнения типа "В этой транзакции уже происходили ошибки."
Неправильно:
Процедура Пример2()
НачатьТранзакцию(); // <-- Ошибка: код перед попыткой
Метод();
Попытка
Метод2();
Исключение
ОтменитьТранзакцию();
Возврат;
КонецПопытки;
ЗафиксироватьТранзакцию();
КонецПроцедуры
Процедура Пример3()
Попытка
НачатьТранзакцию(); // <-- Ошибка: в попытке
Метод();
Исключение
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию();
Иначе
ОтменитьТранзакцию();
КонецЕсли;
Возврат;
КонецПопытки;
КонецПроцедурыИсточник: Стандарт: Транзакции: правила использования
Метод "ЗафиксироватьТранзакцию" должен идти последним в блоке "Попытка"
Описание диагностики
Метод ‘ЗафиксироватьТранзакцию’ должен идти последним в блоке ‘Попытка’ перед оператором ‘Исключение’, чтобы гарантировать, что после ЗафиксироватьТранзакцию не возникнет исключение.
Неправильно:
Процедура Пример2()
НачатьТранзакцию();
Попытка
Метод();
Исключение
ОтменитьТранзакцию();
Возврат;
КонецПопытки;
ЗафиксироватьТранзакцию(); // <-- Ошибка: вне попытки
КонецПроцедуры
Процедура Пример3()
НачатьТранзакцию();
Попытка
Метод();
Исключение
Если ТранзакцияАктивна() Тогда
ЗафиксироватьТранзакцию(); // <-- Ошибка: в исключении
Иначе
ОтменитьТранзакцию();
КонецЕсли;
Возврат;
КонецПопытки;
КонецПроцедурыИсточник: Стандарт: Транзакции: правила использования
Метод "ОтменитьТранзакцию" должен идти первым в блоке "Исключение"
Описание диагностики
В блоке Исключение нужно сначала вызвать метод ОтменитьТранзакцию, а затем выполнять другие действия, если они требуются.
Такое правило необходимо, чтобы убрать потенциальную возможность выброса исключения в блоке "Исключение", что может привести к тому, что метод "ОтменитьТранзакцию" не будет вызван.
Примеры
Неправильно:
Процедура ЗаписатьЭлемент()
НачатьТранзакцию();
Попытка
Метод();
ЗафиксироватьТранзакцию();
Исключение
Метод2(); // <-- Ошибка: код перед отменой
ОтменитьТранзакцию();
КонецПопытки;
КонецПроцедурыИсточник: Стандарт: Транзакции: правила использования
Необоснованное использование метода ТранзакцияАктивна()
При жестком соблюдении правил работы с транзакциями использование метода ТранзакцияАктивна() в блоке Исключение становится лишним.
Требует обоснования:
НачатьТранзакцию();
Попытка
ДелаемЧтоТо();
ЗафиксироватьТранзакцию();
Исключение
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию();
КонецЕсли;
ЗаписьЖурналаРегистрации();
КонецПопытки;Использование данного паттерна нарушает инкапсуляцию и приводит к "размазыванию" логики управления транзакциями.
На нашем уровне абстракции мы обязаны заботиться только о нашей транзакции. Все прочие должны быть нам неинтересны. Они чужие, мы не должны нести за них ответственность. Именно НЕ ДОЛЖНЫ. Нельзя предпринимать попыток выяснения реального уровня счетчика транзакций. (с) Вы не умеете работать с транзакциями

