PHP(或其他):处理“不可能发生”的异常的策略

don*_*ote 2 php exception-handling exception try-catch

考虑以下代码。

class C {}

/**
 * @throws \InvalidArgumentException
 */
function classCreateInstance($class) {
  if (!is_string($class)) {
    throw new \InvalidArgumentException("Class name must be a string.");
  }
  if (!class_exists($class)) {
    throw new \InvalidArgumentException("Class '$class' does not exist.");
  }
  return new $class();
}

/**
 * @return C
 */
function foo() {
  return classCreateInstance(C::class);
}
Run Code Online (Sandbox Code Playgroud)

有一个函数可能会抛出异常,因为它对$class参数一无所知。

另一方面,调用代码知道“C”是一个有效的类名,因此它会假设“InvalidArgumentException”永远不会发生。它希望避免冗长的 try/catch,并且希望避免拥有自己的@throws标签。特别是如果它不被“允许”拥有一个,因为它正在实现一个不注释异常的接口。

但是,从 IDE/自动代码验证的角度来看,忽略此异常是不安全的。

那么..从调用代码的角度处理“几乎不可能”的异常的正确方法是什么?

don*_*ote 5

在爪哇。“已检查”异常类和“未检查”异常类之间存在区别。只有经过检查的异常是接口契约的一部分,而即使接口没有声明它,也允许抛出“未经检查的”异常。

在 Java 中,在“不应该发生”的情况下,会抛出未经检查的异常 - 例如“RuntimeException”。

在 PHP 中,这都是基于约定的。方法可以抛出它们想要的任何异常。@throws在文档注释中添加标签很好,但它不是由语言强制执行的。

但是,可以将 IDE 或其他可能的代码审查工具配置为基于已检查与未检查异常的 Java 模型来分析代码。

例如,PhpStorm 可以选择不需要@throwsRuntimeException 和 LogicException的doc 标记。因此,这将允许将这些视为“未检查”,然后编写自定义异常类并将它们视为 Java 中的“已检查”异常。

PHP 中的原生异常类:http : //php.net/manual/en/spl.exceptions.php#spl.exceptions.tree 并不是说​​这些都继承自 LogicException 或 RuntimeException,因此它们都将被视为“未检查”。只有根类Exception(和自定义子类)会被视为“已检查”。

这种区别还意味着,如果您调用一个没有声明/注释异常的方法/函数,您仍然需要考虑可能会抛出异常。例如,这可以通过应用程序顶层的 try/catch 来覆盖。(例如一个 index.php)