Хорошая подборка!
Значит, мы не зря придумывали и реализовывали эти правила.
Есть замечания
>ОписаниеОшибки() и КраткоеПредставлениеОшибки() не содержат текста строки, вызвавшей ошибку. Код может измениться к моменту анализа ошибки, и придется дополнительно исследовать, где же именно возникла ошибка.
это неверно. Эти методы как раз содержат текст ошибки и строку с модулем, в котором возникла ошибка, и только.
но нет стека вызовов, а значит, непонятно, какая последовательность вызовов привела к ошибке.
именно наличие стека вызовов важно, а он есть только в ПодробноеПредставлениеОшибки, поэтому и нужно использовать данный метод.
Описания есть на соответствующих площадках, и лучше их из Сонара настроенного и смотреть. Правила живые, оптимизируются, дополняются. Ваша статья таким свойством не обладает.
Дополнения (ссылки на статьи) - полезные, но для внутреннего ресурса управления знаниями.
Зачем (ради чего) личные заметки публиковать на ресурсе?
Через год/два, когда поменяется платформа и подходы - правила проверки сонаром изменятся, но разработчики будут гуглить и наткнутся на эту статью, которая по факту будет не актуальной.
Сколько подобных устаревших и вредных статей по оптимизации? Вячеслав устал уже опровергать предложенные методы.
трудно анализируемым ошибкам времени выполнения типа "В этой транзакции уже происходили ошибки." - анализируются средствами ТЖ.
Про ТранзакцияАктивна() - "я не понимаю, зачем это нужно, поэтому не используйте". Подход убийственный. ответ на это правильный такой: Правильно писать не "ОтменитьТранзакцию()", а
Если ТранзакцияАктивна() Тогда
ОтменитьТранзакцию()
КонецЕсли;
Всегда.
Почему? Потому, что 1С не поддерживает вложенные транзакции. Вы никогда не знаете наверняка, является ли ваша транзакция вложенной или ее саму куда-то вложили. никакие сонары это не показывают
(5)А еще лучше управлять исключительными ситуациями на том слое, на котором они возникли, и тогда ге придется ломать голову, а выше открыта транзакции или нет, есть ли там попытка или нет. Например, через проброс исключения наверх.
Общий модуль.ОбщийСервер.КакойтоМетод()
НачатьТранзакцию();
Попытка
Док.Записать();
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки;
И плевать, что там в вызывающем модуле, транзакции, попытка или еще что.
(20) Для меня попытка исключение и транзакция вещи не совместимые - ты либо делаешь в транзакции, либо в попытке, как можно вообще смешивать это? А главное зачем?
(20) Обработка исключения это не только * транзакции. Например там можно сделать запись в журнал и Отказ = Истина, прочие обработки потом пробросить его наверх
Например там можно сделать запись в журнал и Отказ = Истина, прочие обработки потом пробросить его наверх
вот как раз с записью в журнал в сломанной транзакции есть проблемы:
При обработке исключения в сломанной транзакции часто разумно писать диагностическую
информацию в журнал регистрации. При этом метод ЗаписьЖурналаРегистрации() неявно берет
представление от ссылки, используя кэш представлений ссылок, и помещает его
в поле "Представление данных" события журнала. Обращение к этому кэшу в сломанной
транзакции несет риск невосстановимой ошибки. (с) https://infostart.ru/1c/articles/1026771/
поэтому правильным считаю либо использовать СсылкаДляПередачиВЖурналРегистрации() из той статьи, либо писать ВызватьИсключение; // есть внешняя транзакция сразу после отмены транзакции (оставив работу по записи в журнал вызывающему методу) если внешняя транзакция конечно же есть
Код, который начинает транзакцию, обязан завершить или откатить ее. В случаях когда метод НачатьТранзакцию() находится внутри блока Попытка-Исключение есть риск нарушения парности вызовов НачатьТранзакцию()-ЗафиксироватьТранзакцию(
Вот это что-то из области древних знаний, истоки которых утеряны. Как этот риск возникает? Почему? Никто уже не помнит.
И ссылка на источник, в котором написано ровно то же слово в слово. Вы че серьезно собираетесь ссылаться друг на друга и на том основании считать, что так и надо?
Риск точно такой же, как если кто-то впишет код между началом транзакции и попыткой.
(14)Наверное, можно предположить обоснование следующее. А что, если выскочит ошибка на строке НачатьТранзакцию(), то, соответственно, попадаем в исключение, а там ОтменитьТранзакцию(), которую так и не смогли начать.
Правда не знаю, может ли возникнуть ситуация, чтобы НачатьТранзакцию() вызвало исключение.
Не понимаю, почему данный код считается ошибочным:
Процедура Пример2()
НачатьТранзакцию();
Попытка
Метод();
Исключение
ОтменитьТранзакцию();
Возврат;
КонецПопытки;
ЗафиксироватьТранзакцию(); // <-- Ошибка: вне попытки
КонецПроцедуры
Показать
Если после отмены транзакции мы вызываем Возврат - это как раз и есть гарантия того, что после отмены транзакции уже ничего не выполнится в методе. Разве нет? Или просто потому что код не такой красивый как хотелось бы автору данной рекомендации?
(21)написание кода регламентирует стандартами разработки. Да, это не свод правил, но они предельно логичны, читаемы и определенно в большинстве своем оптимальны.
НачатьТранзакцию();
Попытка
// нечто
Если Истина Тогда
ЗафиксироватьТранзакцию();
Возврат;
КонецЕсли;
// Еще нечто
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение;
КонецПопытки
Я что то не понял, а если я хочу совместить транзакции, попытку и запись в журнал регистрации, то какой паттерн то в итоге использовать?
Как правильно? Так:
НачатьТранзакцию();
Попытка
... // чтение или запись данных
ЗафиксироватьТранзакцию();
Исключение
// И запись события в журнал регистрации для системного администратора.
ЗаписьЖурналаРегистрации(НСтр("ru = 'Выполнение операции'"),
УровеньЖурналаРегистрации.Ошибка,,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ОтменитьТранзакцию();
... // дополнительные действия по обработке исключения
КонецПопытки;
Или так:
НачатьТранзакцию();
Попытка
... // чтение или запись данных
ОтменитьТранзакцию();
Исключение
ЗафиксироватьТранзакцию();
// И запись события в журнал регистрации для системного администратора.
ЗаписьЖурналаРегистрации(НСтр("ru = 'Выполнение операции'"),
УровеньЖурналаРегистрации.Ошибка,,,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ОтменитьТранзакцию();
... // дополнительные действия по обработке исключения
КонецПопытки;
Показать
Что первым делать, в журнал писать или транзакцию откатывать? Или все таки правильней получить описание ошибки в переменную, потом откатить транзакцию, а потом записать в журнал. Описание ошибки же в первую очередь нужно, но это противоречит тому, что в первую очередь нужно откатывать транзакцию... По сути все рекомендации бессмысленны, если их применять все вместе, а если применять их по отдельности, то тоже бессмысленны...
(34) правильно делать, как на сайте ИТС написано. Ссылка или в моих комментариях выше или в статье есть.
Там валидный пример, аналог вашего варианта №2
смотрите, шаблон-то простой
только зачем у вас Зафиксировать, а потом почти сразу же ОтменитьТранзакцию?
И объясните на кой черт использовать НСтр всегда и везде, если в параметры передаем только один язык? Я понимаю если бы было еще на английском, или это типа на будущее, что вдруг будем портировать на английский рынок и придется добавить на английском что ли?
(35) Если нет планов переходить на другой язык, конечно, НСтр можно не юзать.
Мне также не нравится его использование, только засоряет код и очень легко пропустить ошибки разного рода.