想知道在创建异常消息时,我应该花多少精力来强制提供有用的调试信息,还是应该相信用户提供正确的信息,或者将信息收集推迟到异常处理程序?
我看到很多人做他们的例外,比如:
throw new RuntimeException('MyObject is not an array')
或者使用自定义异常扩展默认异常,这些自定义异常不做太多事情,但会更改异常的名称:
throw new WrongTypeException('MyObject is not an array')
但这并没有提供太多的调试信息…并且不强制对错误消息进行任何格式设置。因此,您可能会得到完全相同的错误,从而产生两个不同的错误消息…例如“数据库连接失败”vs“无法连接到数据库”
当然,如果它冒泡到顶部,它会打印堆栈跟踪,这很有用,但它并不总是告诉我需要知道的一切,通常我最终不得不开始射击var_dump()语句来发现哪里出错了。尽管这可以用适当的异常处理程序来稍微补偿。
我开始考虑类似下面的代码,其中我 * 要求 * 异常抛出器提供必要的参数以生成正确的错误消息。我在想这可能是个办法:
- 必须提供最低限度的有用信息
- 产生某种程度上一致的错误消息
- 异常消息的模板都在一个位置(异常类),所以更容易更新消息...
但我认为缺点是它们更难使用(需要您查找异常定义),因此可能会阻止其他程序员使用提供的异常...
我想对这个想法发表一些评论,以及一个一致的、灵活的异常消息框架的最佳实践。
/**
* @package MyExceptions
* MyWrongTypeException occurs when an object or
* datastructure is of the incorrect datatype.
* Program defensively!
* @param $objectName string name of object, eg "\$myObject"
* @param $object object object of the wrong type
* @param $expect string expected type of object eg 'integer'
* @param $message any additional human readable info.
* @param $code error code.
* @return Informative exception error message.
* @author secoif
*/
class MyWrongTypeException extends RuntimeException {
public function __construct($objectName, $object, $expected, $message = '', $code = 0) {
$receivedType = gettype($object)
$message = "Wrong Type: $objectName. Expected $expected, received $receivedType";
debug_dump($message, $object);
return parent::__construct($message, $code);
}
}
....
/**
* If we are in debug mode, append the var_dump of $object to $message
*/
function debug_dump(&$message, &$object) {
if (App::get_mode() == 'debug') {
ob_start();
var_dump($object);
$message = $message . "Debug Info: " . ob_get_clean();
}
}
然后像这样使用:
// Hypothetical, supposed to return an array of user objects
$users = get_users(); // but instead returns the string 'bad'
// Ideally the $users model object would provide a validate() but for the sake
// of the example
if (is_array($users)) {
throw new MyWrongTypeException('$users', $users, 'array')
// returns
//"Wrong Type: $users. Expected array, received string
}
我们可能会在自定义异常处理程序中做一些类似nl2br的事情,以使HTML输出更好。
一直在阅读:http://msdn.microsoft.com/en-us/library/cc511859.aspx#
但却没有提到这件事,所以也许这是个坏主意...
5条答案
按热度按时间eivgtgni1#
我强烈推荐关于Krzysztof's blog的建议,并会注意到,在你的情况下,你似乎在试图处理他所说的使用错误。
在这种情况下,需要的不是一个新的类型来指示它,而是一个更好的错误消息,说明是什么导致了它。作为这样的辅助函数,可以:
1.生成要放入异常的文本字符串
1.生成整个异常和消息
这才是必需的。
方法1更清晰,但可能会导致更冗长的用法,2则相反,用更简洁的语法换取更不清晰的语法。
请注意,这些函数必须非常安全(它们本身永远不会导致不相关的异常),并且不会强制提供在某些合理使用中可选的数据。
通过使用这两种方法中的任何一种,您可以更轻松地在以后需要时国际化错误消息。
堆栈跟踪至少会提供函数,可能还有行号,因此您应该专注于提供不容易从中得出的信息。
hxzsmxv22#
我不会贬低关于Krzysztof博客的建议,但这里有一个非常简单的方法来创建自定义异常。
更新为PHP 8.1
PHP 5-7
示例:
这背后的代码(我从某个地方借来的,向任何人道歉)
ct3nt3jp3#
请参阅Krzysztof Cwalina博客上的How to Design Exception Hierarchies,他是“框架设计指南”的合著者。
t5zmwmid4#
永远不要相信用户会“做正确的事情”,并包含调试信息。如果你需要信息,你需要自己收集它,并把它存储在一个可以访问的地方。
同样如前所述,如果很难(呃)做某件事,用户会避免这样做,所以再次,不要依赖他们的善意和他们对他们需要发送什么的了解。
这种想法意味着您可以通过一种方法来收集信息并将其记录下来,这意味着在某处使用var_dump()。
此外,正如Mark Harrison所说,一个可以轻松发送错误消息的按钮对您和用户来说都是非常棒的。这使得他们很容易报告错误。您(作为收件人)会收到很多重复的信息,但重复的信息总比没有信息好。
piok6c0g5#
无论您添加了多少细节,请确保