Рекомендации: использование @throws в php-doc и как его можно обрабатывать
предположим, у меня есть класс с таким методом:
/*
*
* Loads the user from username.
*
* @param string $username The username
*
* @return UserInterface
*
* @throws userNotFoundException if the user is not found
*/
public function getUser($username)
{
// someFunction return an UserInterface class if found, or null if not.
$user = someFunction('SELECT ....', $username);
if ($user === null) {
throw new userNotFoundException();
}
return $user
}
теперь скажем, что someFunction
могу кинуть InvalidArgumentException
/ RuntimeException
/ PDOException
по причинам XYZ. Что мне делать? а что нет?
номер 1
добавить все возможные исключения, которые может бросать someFunction
в php-документах.
/*
*
* Loads the user from username.
*
* @param string $username The username
*
* @return UserInterface
*
* @throws userNotFoundException if the user is not found
* @throws InvalidArgumentException
* @throws ...
*/
номер 2
добавьте блок try-catch, чтобы гарантировать, что метод должен выдавать только исключения документально
/*
*
* Loads the user from username.
*
* @param string $username The username
*
* @return UserInterface
*
* @throws userNotFoundException if the user is not found
* @throws RuntimeException
*/
public function getUser($username)
{
try {
$user = someFunction('SELECT ....', $username);
} catch (Exception $e) {
throw new RuntimeException();
}
if ($user === null) {
throw new userNotFoundException();
}
return $user
}
число 3
ничего не делай.
3 ответов
лично я бы рассматривать @throws
подобно проверенным исключениям Java
способ, которым это работает в Java, заключается в том, что в основном исключения, наследуемые от RuntimeException, могут быть брошены и не должны обрабатываться. Любые другие типы исключений должны иметь блок try-catch для их обработки. Этот код обработки должен быть в вызывающем объекте.
в основном, в PHP вроде этого:
когда метод имеет @throws
аннотация обязательно добавьте код для обработки исключений.
любые исключения, которые не упоминаются, являются необязательными для обработки в вызывающем коде.
теперь я сам не на 100% следую этому принципу. Вся обработка исключений зависит от предпочтений программиста, но это всего лишь некоторые мысли о том, как я думаю, что это может быть обработано разумным образом.
что касается документации, если функция явно создает исключение, затем оно должно быть включено в документацию функции. Таким образом, для каждого throw
оператор, должен быть соответствующий @throws
в документации PHP.
что касается обработки, если есть некоторые операции, которые должны выполняться при возникновении исключения, то поймайте его. В противном случае пусть он пузырится-при условии, что есть catch
заявление будут обрабатывать это потом.
обновление:
несколько лет спустя я изменил мнение, что нужно только позволить исключению "пузыриться" немодифицированным, когда исключение все еще имеет отношение к уровню абстракции модуля. Стратегии перехвата и повторного броска должны использоваться, чтобы сделать исключение более значимым. Он также должен сделать обработку ошибок более безопасной, избегая ненужного раскрытия информации о модулях, лежащих в основе абстракции.
/**
* @throws UserNotFoundException
*/
public function getUser($username)
{
try {
$user = someFunction('SELECT ....', $username);
} catch (DatabaseException $dbe) {
/* Re-throw since a database exception may no longer be
* meaningful to the caller.
*/
throw new UserNotFoundException();
}
return $user
}
с точки зрения обслуживания документации я бы только добавил строки @throw для исключений, которые специально брошены, иначе вы быстро получите свою документацию устаревшей.