Возврат сообщений об ошибках из подпрограмм perl
Это хороший способ вернуть сообщения об ошибках из подпрограммы в perl?
sub some_subroutine{
# do something
$something = 14;
if(1 == 2){
$_ = "This should not be happening!";
return undef;
}
return $something;
}
my $ret=some_subroutine();
print "ERROR: $_" unless(defined $ret);
Код работает нормально (в параллельном мире, где 1 == 2
), но с помощью $_
для возврата сообщения об ошибке является хорошим способом? Я не нашел никакой документации относительно использования $_
для таких целей.
Спасибо!
Ответы
Ответ 1
$_
не является хорошим механизмом, так как многие другие используют и устанавливают его.
Вы можете установить другую глобальную переменную, например $Error, но лучший способ - это исключение. Тогда пользователь не должен всегда проверять и забывать, это просто происходит. В Perl исключения генерируются с помощью die ". die возьмет строку или объект. Существует несколько модулей, облегчающих исключения броска, включая Exception::Class, Exception::Simple, Ouch и autodie.
Вы можете поймать исключение с eval {}, но есть ряд проблем с этим, поэтому вы должны использовать что-то вроде Try::Tiny.
Ответ 2
Нельзя использовать глобальную переменную для хранения сообщения об ошибке. Например, встроенная функция использует $!
, а DBI использует $DBI::errstr
. Но тогда вы наследуете все проблемы использования глобальных переменных. Обработчики сигналов должны локализовать их, деструкторы могут сжимать их, многопоточные проблемы и т.д.
Мне кажется, что выбор исключений (например, использование die
) является более распространенным выбором.
Что бы вы ни делали, не используйте $_
. Он часто сглаживается чем-то, поэтому его использование может иметь непреднамеренные последствия.
Ответ 3
Одна вещь, которую вы можете сделать, чтобы сделать это немного лучше, - просто return;
на ошибке /undefined. Существуют контексты, где return undef;
можно оценить как true
. Вы можете проверить главу Perl Best Practices об обработке ошибок, поскольку она охватывает это и имеет другие хорошие указатели.
Например, если:
my $ret=some_subroutine();
print "ERROR: $_" unless(defined $ret);
становится
my @ret=some_subroutine(); # oops!
print "ERROR: $_" unless(defined $ret);
У вас есть странная ошибка (не поймать ошибку), которую трудно отследить, тогда как если вы return;
от some_subroutine
, вы получите:
my @ret=some_subroutine(); # oops!
print "ERROR: $_" unless($ret); # but error is still caught
Кроме того, в случае функции, которая должна возвращать список:
my @ret=some_other_subroutine(); # OK
print "ERROR: $_" unless($ret); # error will be caught if you "return;"
# ... but later ...
my $ret=some_other_subroutine(); # oops!
print "ERROR: $_" unless($ret); # if you "return;" $ret will equal 0
# (the length of the returned list)
# and the error will be caught
Итак, хотя существуют другие шаблоны для возврата статуса ошибки / undefined из функции, всегда используя return;
позволяет использовать один шаблон для почти всех функций, как для возврата соответствующего значения, так и при наступлении времени проверьте состояние ошибки.
Ответ 4
Это полностью зависит от того, какое поведение вы ожидаете увидеть от обработчика ошибок. В perl очень часто используется die
или warn
, если возникает ошибка/предупреждение о запуске.
Взгляните на этот учебник по обработке ошибок в perl: http://www.tutorialspoint.com/perl/perl_error_handeling.htm
Ответ 5
Для веб-службы вы можете написать подпрограмму для печати пользовательских ответов об ошибках (ошибки 40x и т.д.).