четверг, 7 апреля 2016 г.

Cache': Политика обработки ошибок в приложениях

Данный документ представляет собой пример "политики по обработке ошибок". Сформулированные здесь правила представляют собой свод проверенных на практике приемов и решений по обработке ошибок в Cache приложениях. Вы можете использовать ее в качестве примера для разработки правил обработки ошибок в своем коллективе.


Более подробную информацию по обработке ошибок можно найти в документации (Developing Applications with Cache -> Using Cache ObjectScript -> Error Processing, Developing Applications with Cache -> Using Cache ObjectScript -> Command-Line Routine Debugging -> Error Trap Utilities, Developing Applications with Cache -> Using Cache Basic -> Error Handling).

%Status и объекты

В объектных приложениях основой обработки ошибок является класс %Library.Status (Смотрите документацию класса в Cache Class Reference).

Нужно создавать методы так, чтобы они возвращали тип данных %Library.Status с информацией о выполнении метода. Для генерации и анализа статуса используется объект $system.Status (Смотрите документацию класса %SYSTEM.Status в Cache Class Reference).

ClassMethod TestMethod() As %Library.Status
{
 //do something
 If success {
  Quit $system.Status.OK()
 }
 else {
  Quit $system.Status.Error(5001, "can not perform requested action")
 }
}

Для просмотра ошибки используйте $system.Status.DisplayError(status), для анализа в вашей программе

$system.Status.IsError(status),$system.Status.IsOK(status) 
$system.Status.DecomposeStatus(status,.temp).

Также допускается использовать макросы, объявленные в %occStatus.INC:

$$$OK - success status
$$$ERR(%code) - error status, with error code
$$$ERROR(%code,%message)- error status, with 
                          error code plus description
$$$ISOK(%sc) - return 1/0, 1 if status is successful
$$$ISERR(%sc) - return 1/0, 0 if status is error
$$$ADDSC(%sc1,%sc2) - append 2 status codes together

С помощью %Library.Status Вы можете проверить результат выполнения методов и в случае ошибки предпринять какие-либо действия.

Do ##class(Test.Class).TestMethod()
If $system.Status.IsOK(status) 
{
 //do something
} 
else 
{
 Do $system.Status.DisplayError(res)
}

Если невозможно создать "безопасные" методы, возвращающие данные, выделяйте свойство или специальное значение - маркер ошибки.

Если Ваш метод должен возвращать значения, Вы можете использовать передачу переменных по ссылке, а в качестве результата выполнения метода возвращать %Library.Status.

Для возврата прикладных ошибок вашего приложения используйте статус код 5001 ($$$GeneralError).

Если Вы перехватили системную ошибку Cache - используйте код 5002 ($$$CacheError)

Также Вы можете создать свой собственный набор кодов ошибок. Номера пользовательских ошибок должны начинаться с 10000. Для добавления кода ошибки используйте:

AddError^%oueError(errorname,,errorcode,errortext,locale)

Перехват системных ошибок

В Cache реализовано два механизма для перехвата системных ошибок - основанный на $ETrap и основанный на $ZTrap. Если не вдаваться в детали, то по своему назначению и принципам работы они равнозначны. Мы будем рассматривать механизм, основанный на $ZTrap.

myroutine(n)
 set $ztrap="onerror"
 write 1/n
 quit
onerror
 set $ztrap=""
 write "Error :"_$zerror
 quit

Если вышеприведенную программу вызвать с аргументом 0 - во второй строке произойдет ошибка деления на ноль .

Переменная $ztrap содержит метку обработчика ошибок. В случае возникновения ошибки управление будет передано этой метке. Переменная $zerror содержит описание последней возникшей ошибки: код и строка, в которой она произошла.

Обязательно в начале кода обработки ошибки устанавливайте $ztrap="". В противном случае - при возникновении ошибки в коде обработчика ошибки вы вновь попадете на начало обработчика и, в конечном счете, в бесконечный цикл.

Очень важно окружить каждый "потенциально опасный" участок кода локальным перехватчиком ошибок. Не допускайте использования "глобальных" перехватчиков ошибок - единственного на всю программу или класс универсального обработчика. Код, написанный подобным образом, очень тяжело поддается отладке и служит источником других, трудно обнаруживаемых ошибок.

Перехват системных ошибок в методах объектов

Если в коде метода возможно возникновение системной ошибки, в теле метода создайте локальный перехватчик ошибки.

ClassMethod Divide(n) As %Library.Status
{
 set $ztrap="onerrordivide"
 write 1/n
 Quit $system.Status.OK()
onerrordivide
 set $ztrap=""
 Quit $system.Status.Error(5002,$zerror)
}

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

Программа %ETN

В своем обработчике ошибок Вы можете использовать программу %ETN. Утилита сохраняет ценную информацию о состоянии процесса (стек вызовов, значения системных и пользовательских переменных и т.д.), в котором случилась ошибка, на момент ошибки. Вы можете позже исследовать эту информацию с помощью утилиты %ERN или Панели управления (Панель Управления -> Журнал Регистрации -> Ошибки приложения -> Namespace Вашего приложения -> Ошибка).

ClassMethod Divide(n) As %Library.Status
{
 set $ztrap="onerrordivide"
 write 1/n
 Quit $system.Status.OK()
onerrordivide
 set $ztrap=""
 Do BACK^%ETN
 Quit $system.Status.Error(5002,$zerror)
}

Краткий свод правил
  1. Используйте %Status при реализации методов классов
  2. Для перехвата системных ошибок используйте $ZTrap
  3. Для каждого опасного участка - свой локальный обработчик
  4. Если нужна подробная информация об ошибке, используйте %ETN

Антон Умников
консультант Интерсистемс
Источник статьи: форум www.sql.ru 

Комментариев нет:

Отправить комментарий