函数中的 PHP 异常 VS 返回用法(最佳实践)

标签 php function exception return return-value

在我们的团队中,我们经常讨论在函数 VS 某种返回数组中使用异常,但我仍然不确定如何以正确的方式做到这一点。所以让我们试着从头开始问这个问题:

何时使用返回数组的异常 VS,其中包含有关结果的所有信息?

示例 #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...
}

那么哪个版本是“更好”的错误处理方式,#1 还是#2?这只是品味问题还是对两个版本中的一个有真正的争论?

对于方法或函数,有一个简单的最佳实践“规则”,它告诉您在函数中具有单个退出点。这已经是答案了吗,这意味着它将是 v2?

我真的很感激关于这个话题的所有想法:-)

最佳答案

多年前,当我读到它时,我得到了很多关于这个问题的信息。首先是“告诉,不要问”的原则( herehere )以及 Robert C. Martin 撰写的 Clean Code 的整个第 3 章和第 7 章。

有了这个,您可以实现一些很好的东西,以了解该方法应该做什么和不应该做什么。

一个方法应该只返回,并且只在询问或请求某事时返回。询问某事的方法具有以下前缀:

  • get ;//混合
  • has ;// bool 值
  • is ;// bool 值
  • can .// bool 值

  • 或者,可以有字return (不需要作为前缀):
  • doSomethingAwesomeAndReturn .//混合

  • 姓名 create是一个异常(exception),因为 create not 必须返回一些东西:
  • createSomethingAwesomeAndReturn .//混合

  • 如果您的方法没有这些内容,则不应返回任何内容。

    在第 3 章中,您可以找到名为“Prefer Exceptions to Returning Error Codes”的部分,在第 7 章中,您可以找到“Don’t Return Null”。这解释了返回某些东西所产生的一些问题。很多验证链,空对象等......这些问题可以通过返回异常来解决。

    你的第二个例子很好,但就像方法名称所说的那样,它做了很棒的事情,不应该返回。如果没有异常(exception),它做了很棒的事情。如果真的需要返回,您必须重构或至少重命名您的方法以匹配预期。

    毕竟,这只是指导您编码的大量建议,而不是不灵活的规则。

    更新

    我忘记了前缀 add .这是一个异常(exception)。前缀为 add 的方法应该返回与 fluent interface 匹配的相同对象。 , 没有其他的。作为Fluent Interface,它不应该与上述规则匹配,方法的名称/前缀/后缀无关紧要,因为它只是为了流畅而不是内聚。

    关于函数中的 PHP 异常 VS 返回用法(最佳实践),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40466512/

    相关文章:

    php - 下拉设置 session 变量

    php - 在 Fuelphp 查询生成器中使用 "()"

    javascript - javascript 'if' 语句中使用的 Posted 变量立即消失

    python - 如何将函数的文档字符串放入变量中?

    C 程序在使用 scanf 获取用户输入时显示垃圾值

    PHP选择具有相同id的不同列

    bash - 使用别名覆盖内置命令

    c++ - 在 C++ 中处理浮点异常

    java - 如何处理java代码的错误

    java - 为什么 "catch" block 一定需要异常类型?