PHP 异常 VS Return 函数中的用法(最佳实践)
PHP Exceptions VS Return usage in Functions (best practice)
在我们的团队中,我们经常讨论函数内部异常的使用 VS 某种 return 数组,但我仍然不确定如何以正确的方式进行。那么让我们试着从头开始问这个问题:
何时使用异常 VS returning 数组,包含有关结果的所有信息?
示例 #1
function doAwesomeStuff($foo) {
// prepare return values...
$result = [
'success' => true,
'infoMessage' => '',
'stuffDetails' => []
];
// check params...
if (!is_numeric($foo)) {
$result['success'] = false;
$result['infoMessage'] = 'Something went wrong...';
return $result;
}
// do something else...
if ($somethingElseWentWrong) {
$result['success'] = false;
$result['infoMessage'] = 'Something else went wrong...';
return $result;
}
// add new data...
$result['stuffDetails'] = [
'foo' => 'bar'
];
// done...
return $result;
}
$foo = 42;
$awesomeStuff = doAwesomeStuff($foo);
if ($awesomeStuff['success'] === false) {
echo $awesomeStuff['infoMessage'];
// some error handling stuff...
}
// do some other awesome stuff
// ...
示例 2
function doAwesomeStuff($foo) {
// prepare return value...
$stuffDetails = [];
// check params...
if (!is_numeric($foo)) {
throw new InvalidArgumentException('Something went wrong...');
}
// do something else...
if ($somethingElseWentWrong) {
throw new AnotherException('Something else went wrong...');
}
// add new data...
$stuffDetails = [
'foo' => 'bar'
];
// done...
return $stuffDetails;
}
try {
$foo = 42;
$awesomeStuff = doAwesomeStuff($foo);
// do some other awesome stuff...
// ...without caring about error handling at this point (it's all done in catch blocks)
} catch InvalidArgumentException($e) {
echo $e->getMessage();
// some error handling stuff...
} catch AnotherException($e) {
echo $e->getMessage();
// some error handling stuff...
}
那么 "better" 错误处理方式是哪个版本,#1 还是#2?这只是一个品味问题,还是对这两个版本之一有真正的争论?
对于方法或函数,有一个简单的最佳实践 "rule" 告诉您在函数中有一个出口点。这已经是答案了吗,这意味着它将是 v2?
我非常感谢关于这个主题的所有想法:-)
我会推荐 #2 with Exceptions,因为如果你使用 return 值进行错误处理,你就不能真正将它用于它的实际用途,returning 东西。此外,您可以使用预定义的异常类型或创建新的单独异常-类 来区分异常并根据需要处理它们。
Whosebug 上的其他人已经写了关于异常或 Return Codes/Errors:
- Which, and why, do you prefer Exceptions or Return codes?
- Exceptions or error codes
多年前,当我读到它时,我得到了很多关于这个问题的信息。首先,“告诉,不要问”原则 (here and here) 以及 Robert C. Martin 编写的 Clean Code 的整个第 3 章和第 7 章之后。
有了这个,你可以实现一些好的东西来理解这个方法应该做什么,不应该做什么。
一个方法应该 return 只,而且只在询问或要求某事时。询问某事的方法的前缀为:
get
; //混合
has
; //布尔值
is
; //布尔值
can
。 //布尔值
或者,可以有单词 return
(不需要作为前缀):
doSomethingAwesomeAndReturn
。 //混合
名字create
是个例外,因为创建不需要return东西:
createSomethingAwesomeAndReturn
。 //混合
如果你的方法没有任何这些,它不应该 return 任何东西。
在第 3 章中,您可以找到名为 "Prefer Exceptions to Returning Error Codes" 的部分,在第 7 章中,您可以找到 "Don’t Return Null"。这解释了一些由 returning 产生的问题。大量验证链、空对象等...只需 return 异常即可解决这些问题。
你的第二个例子很好,但就像方法名称所说的那样,它做了很棒的事情,不应该 return。如果没有例外,它做了很棒的事情。如果确实需要 return,您必须重构或至少重命名您的方法以匹配预期。
毕竟,这只是指导你编码的很多建议,而不是死板的规则。
更新
我忘了前缀 add
。这是一个例外。以 add 为前缀的方法应该 return 与 fluent interface 匹配的相同对象,没有别的。作为 Fluent Interface,它不应该与上述规则匹配,方法的 name/prefix/suffix 无关紧要,因为它只是为了流畅,而不是为了内聚。
在我们的团队中,我们经常讨论函数内部异常的使用 VS 某种 return 数组,但我仍然不确定如何以正确的方式进行。那么让我们试着从头开始问这个问题:
何时使用异常 VS returning 数组,包含有关结果的所有信息?
示例 #1
function doAwesomeStuff($foo) {
// prepare return values...
$result = [
'success' => true,
'infoMessage' => '',
'stuffDetails' => []
];
// check params...
if (!is_numeric($foo)) {
$result['success'] = false;
$result['infoMessage'] = 'Something went wrong...';
return $result;
}
// do something else...
if ($somethingElseWentWrong) {
$result['success'] = false;
$result['infoMessage'] = 'Something else went wrong...';
return $result;
}
// add new data...
$result['stuffDetails'] = [
'foo' => 'bar'
];
// done...
return $result;
}
$foo = 42;
$awesomeStuff = doAwesomeStuff($foo);
if ($awesomeStuff['success'] === false) {
echo $awesomeStuff['infoMessage'];
// some error handling stuff...
}
// do some other awesome stuff
// ...
示例 2
function doAwesomeStuff($foo) {
// prepare return value...
$stuffDetails = [];
// check params...
if (!is_numeric($foo)) {
throw new InvalidArgumentException('Something went wrong...');
}
// do something else...
if ($somethingElseWentWrong) {
throw new AnotherException('Something else went wrong...');
}
// add new data...
$stuffDetails = [
'foo' => 'bar'
];
// done...
return $stuffDetails;
}
try {
$foo = 42;
$awesomeStuff = doAwesomeStuff($foo);
// do some other awesome stuff...
// ...without caring about error handling at this point (it's all done in catch blocks)
} catch InvalidArgumentException($e) {
echo $e->getMessage();
// some error handling stuff...
} catch AnotherException($e) {
echo $e->getMessage();
// some error handling stuff...
}
那么 "better" 错误处理方式是哪个版本,#1 还是#2?这只是一个品味问题,还是对这两个版本之一有真正的争论?
对于方法或函数,有一个简单的最佳实践 "rule" 告诉您在函数中有一个出口点。这已经是答案了吗,这意味着它将是 v2?
我非常感谢关于这个主题的所有想法:-)
我会推荐 #2 with Exceptions,因为如果你使用 return 值进行错误处理,你就不能真正将它用于它的实际用途,returning 东西。此外,您可以使用预定义的异常类型或创建新的单独异常-类 来区分异常并根据需要处理它们。
Whosebug 上的其他人已经写了关于异常或 Return Codes/Errors:
- Which, and why, do you prefer Exceptions or Return codes?
- Exceptions or error codes
多年前,当我读到它时,我得到了很多关于这个问题的信息。首先,“告诉,不要问”原则 (here and here) 以及 Robert C. Martin 编写的 Clean Code 的整个第 3 章和第 7 章之后。
有了这个,你可以实现一些好的东西来理解这个方法应该做什么,不应该做什么。
一个方法应该 return 只,而且只在询问或要求某事时。询问某事的方法的前缀为:
get
; //混合has
; //布尔值is
; //布尔值can
。 //布尔值
或者,可以有单词 return
(不需要作为前缀):
doSomethingAwesomeAndReturn
。 //混合
名字create
是个例外,因为创建不需要return东西:
createSomethingAwesomeAndReturn
。 //混合
如果你的方法没有任何这些,它不应该 return 任何东西。
在第 3 章中,您可以找到名为 "Prefer Exceptions to Returning Error Codes" 的部分,在第 7 章中,您可以找到 "Don’t Return Null"。这解释了一些由 returning 产生的问题。大量验证链、空对象等...只需 return 异常即可解决这些问题。
你的第二个例子很好,但就像方法名称所说的那样,它做了很棒的事情,不应该 return。如果没有例外,它做了很棒的事情。如果确实需要 return,您必须重构或至少重命名您的方法以匹配预期。
毕竟,这只是指导你编码的很多建议,而不是死板的规则。
更新
我忘了前缀 add
。这是一个例外。以 add 为前缀的方法应该 return 与 fluent interface 匹配的相同对象,没有别的。作为 Fluent Interface,它不应该与上述规则匹配,方法的 name/prefix/suffix 无关紧要,因为它只是为了流畅,而不是为了内聚。