Довідковий матеріал

Перехоплення винятків у коді

<em>Сфера застосування: керований застосунок, мобільний застосунок, звичайний застосунок.</em>Окремі випадки некоректного використання та перехоплення винятків

Редакційна сцена про коректне опрацювання винятку: помилка потрапляє до докладного журналу для діагностики, а користувач отримує коротке зрозуміле повідомлення.

Окремі випадки некоректного використання та перехоплення винятків

 

Сфера застосування: керований застосунок, мобільний застосунок, звичайний застосунок.

Загалом не рекомендується перехоплювати винятки. Зокрема не потрібно перехоплювати винятки лише заради виведення повідомлення про помилку. Необроблений виняток у будь-якому разі буде показано користувачеві у вигляді повідомлення про помилку.

Проте потреба в перехопленні винятків у коді все ж виникає. Наприклад, щоб уточнити текст помилки, доповнивши його прикладною, зрозумілою кінцевому користувачеві, інформацією. Однак при цьому необхідно фіксувати причину помилки в журналі реєстрації, щоб системний адміністратор мав можливість виконати діагностику проблеми й за потреби передати інформацію про помилку до служби технічної підтримки.

Рекомендується записувати до журналу реєстрації докладне подання винятку, а коротке подання додавати до тексту повідомлення користувачеві.

Окремі випадки некоректного використання та перехоплення винятків

Сфера застосування (уточнення): керований застосунок, звичайний застосунок.

1. Якщо є деяка серверна бізнес-логіка, яка викликається з клієнта під час інтерактивної роботи користувача:

&НаСервере Процедура ВыполнитьОперацию() // код, що призводить до виклику винятку .... КонецПроцедуры

то неправильно:

// на клієнті Попытка ВыполнитьОперацию(); Исключение Предупреждение("Операція не може бути виконана." ); КонецПопытки;

Правильно:

&НаСервере Процедура ВыполнитьОперацию() Попытка // код, що призводить до виклику винятку .... Исключение // Запис події до журналу реєстрації для системного адміністратора. ЗаписьЖурналаРегистрации(НСтр("ru = 'Виконання операції'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение; КонецПопытки; КонецПроцедуры

і тоді на клієнті:

Попытка ВыполнитьОперацию(); Исключение ТекстСообщения = КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); Предупреждение(НСтр("ru = 'Операція не може бути виконана з причини:'") + Символы.ПС + ТекстСообщения); КонецПопытки;

2. Якщо є деяка клієнтська бізнес-логіка:

&НаКлиенте Процедура СоздатьФайлНаДиске() // код, що призводить до виклику винятку .... КонецПроцедуры

то рекомендується зробити додатковий серверний виклик для протоколювання невдалого результату операції в журналі реєстрації:

Попытка // код, що призводить до виклику винятку СоздатьФайлНаДиске(); Исключение ТекстСообщения = КраткоеПредставлениеОшибки(ИнформацияОбОшибке()); Предупреждение(НСтр("ru = 'Операція не може бути виконана з причини:'") + Символы.ПС + ТекстСообщения); ЗаписатьОшибкуРаботыСФайлами(ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()))); КонецПопытки; &НаСервере Процедура ЗаписатьОшибкуРаботыСФайлами(...) ЗаписьЖурналаРегистрации(НСтр("ru = 'Виконання операції'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки); КонецПроцедуры

3. Неприпустимо перехоплювати будь-які винятки безслідно для системного адміністратора:

Попытка // код, що призводить до виклику винятку .... Исключение // перехоплення будь-яких винятків КонецПопытки;

Як правило, подібна конструкція приховує реальну проблему, яку згодом неможливо діагностувати.
Правильно:

Попытка // код, що призводить до виклику винятку .... Исключение // Пояснення причин перехоплення всіх винятків «непомітно» для користувача. // .... // І запис події до журналу реєстрації для системного адміністратора. ЗаписьЖурналаРегистрации(НСтр("ru = 'Виконання операції'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); КонецПопытки;

Див. також Доступ до файлової системи з коду конфігурації, видалення тимчасових файлів

4. Неприпустимо перевіряти наявність у об’єкта реквізитів, методів, макетів тощо, використовуючи для цього винятки, оскільки це може призвести до складних для діагностики помилок, а також ускладнює налагодження в режимі «Зупинятися за помилкою».
Замість перехоплення винятків у цьому випадку рекомендується:

  • використовувати механізми роботи з метаданими, щоб явно перевіряти наявність або відсутність реквізиту (макета тощо);
  • якщо відмінності пов’язані з особливостями вбудовування бібліотек — описувати особливості явно в перевизначуваних модулях (див. Перевизначувані та постачувані об’єкти);
  • переглянути логіку роботи методів, що використовують перехоплення винятків. Наприклад, можна передбачити параметри, які визначаються у коді, що викликає, і вказують, чи потрібно звертатися до будь-якого методу або властивості об’єкта.

Наприклад, неправильно:

Попытка КонтекстЭДОСервер.ПолучитьМакет("КомпонентаОбмена"); ПутьВК = КонтекстЭДОСервер.ПутьКОбъекту + ".Макет.КомпонентаОбмена"; Исключение КонецПопытки;

Правильно:

МакетКомпонентыОбмена = КонтекстЭДОСервер.Метаданные().Макеты.Найти("КомпонентаОбмена"); Если МакетКомпонентыОбмена <> Неопределено Тогда ПутьКМакету = КомпонентаОбмена.ПолноеИмя() КонецЕсли;

5. Під час використання транзакцій слід дотримуватися такої схеми обробки винятків у коді на сервері:

НачатьТранзакцию(); Попытка Запрос = Новый Запрос("..."); Выборка = Запрос.Выполнить().Выбрать(); Пока Выборка.Следующий() Цикл ... КонецЦикла; ЗафиксироватьТранзакцию(); Исключение ОтменитьТранзакцию(); ЗаписьЖурналаРегистрации(НСтр("ru = 'Виконання операції'"), УровеньЖурналаРегистрации.Ошибка,,, ПодробноеПредставлениеОшибки(ИнформацияОбОшибке())); ВызватьИсключение; КонецПопытки;

Оскільки виняток не скасовує транзакцію відразу, але забороняє успішне завершення транзакції, то всі виклики НачатьТранзакцию, з одного боку, і ЗафиксироватьТранзакцию або ОтменитьТранзакцию, з іншого боку, мають бути парними.

6. Неправильно використовувати винятки для приведення значення до типу. Для таких операцій необхідно використовувати можливості об’єкта ОписаниеТипов.

Наприклад, неправильно:

Попытка КоличествоДнейРазрешения = Число(Значение); Исключение КоличествоДнейРазрешения = 0; // значення за замовчуванням КонецПопытки;

Правильно:

ОписаниеТипа = Новый ОписаниеТипов("Число"); КоличествоДнейРазрешения = ОписаниеТипа.ПривестиЗначение(Значение);
Записатися телефоном