在 PHP 函数/方法中返回的最佳实践

Posted

技术标签:

【中文标题】在 PHP 函数/方法中返回的最佳实践【英文标题】:Best practice for returning in PHP function/method 【发布时间】:2015-07-27 04:20:09 【问题描述】:

我正在加班重构大量代码库。从长远来看,我们将在课堂上开发整个系统,但与此同时,我正在利用这个机会来提高我的 php 技能并改进我们在数百个网站上使用的一些遗留代码。

随着时间的推移,我已经阅读了关于如何最好地从自定义函数返回数据的相互矛盾的文章,通常争论分为两类,一类关注最佳技术实践,另一类关注易于阅读和演示。

对于从自定义 PHP 函数返回时您认为最佳实践的意见(详细说明),我很感兴趣。

例如,使用这个基本理论函数,我不确定以下哪一个作为更好的标准;

接近a。

填充一个返回变量并在函数结束时返回它:

<?php
function theoreticalFunction( $var )

    $return = '';
    if( $something > $somethingelse )
       $return = true;
    else
       $return = false;
    
    return $return;

?>

方法 b。

在每个端点返回:

<?php
function theoreticalFunction( $var )

    if( $something > $somethingelse )
       return true;
    else
       return false;
    

?>

一个可能的重复项可能是What is the PHP best practice for using functions that return true or false?,但这并不限于简单的真或假,尽管我上面的基本示例。

我查看了 PSR 指南,但没有看到任何内容(但我可能错过了它,所以请随时将我指向 PSR 并提供参考 :))。

扩展原来的问题:

用于返回的方法是否因预期/期望的输出类型而异?

此方法是否会因使用过程或面向对象的编程方法而改变?正如这个问题所示,面向对象带来了自己的怪癖,以进一步扩展可能的格式/呈现选项Best practices for returns methods in PHP

请尽量在您的解释中明确说明,我对您为什么选择您喜欢的方法以及是什么(如果有的话)让您选择它而不是其他方法感兴趣。

【问题讨论】:

我更喜欢使用方法 B。例如,我有一个用户需要登录的功能,所以我的第一行会检查它。我不想构建一个巨大的 if 语句来确保脚本不执行其余部分。所以这就是为什么我更喜欢使用方法 B 有人主张函数中的单一出口点(最后只有一个return),还有人主张失败/早退我>。这只是根据具体情况的意见和可读性/可理解性问题。几乎没有任何客观的技术答案。 我认为这最终会是:主要基于意见,因为这取决于你想做什么;编码员的经验; 这是有道理的@deceze,我确实想知道我是否会得到主要“这取决于所讨论的功能,具体情况”的答案。也许这里没有辩论?这可以解释 PSR 指南中缺少有关此主题的信息,或者至少就我所见而言。 顺便说一句,我们甚至不要开始讨论你对空格和括号的可怕使用...... ;-P 【参考方案1】:

我知道这个问题很老,但它很有趣,据我说 关于它有很多话要说。 首先要说的是,在函数或方法中返回没有真正的标准。 它通常由您的团队决定遵循的规则来决定,但如果您是此重构中唯一的人,您可以做您认为更好的事情。

在返回值的情况下,我猜重要的是 可读性。有时放松一点会更好 代码的可读性和可维护性更高。 我将尝试展示一些具有优缺点的示例。

方法 A

<?php
function getTariableType($var = null)

    if (null === $var) 
        return 0;
     elseif (is_string($var)) 
        return 1;
     else 
        return -1;
    

优点:

明确性。每个案例都能自我解释,即使没有任何 cmets。 结构。每个案例都有一个分支,每个案例都划分清楚 并且很容易为新案例添加语句。

缺点:

可读性。所有这些带括号的if..else 使代码难以阅读和 我们真的必须注意每个部分才能理解。 不需要代码。最后一个else 语句不是必需的,代码为 如果 return -1 只是函数的最后一条语句,则更易于阅读, 在任何 else 之外。

方法 B

<?php
function isTheVariableNull($var)

    return (null === $var);

优点:

可读性。代码易于阅读和理解,乍一看我们 知道该函数正在检查变量是否为空。 简洁。只有一个陈述,在这种情况下它很好而且很清楚。

缺点:

限制。这种符号仅限于非常小的功能。使用这个符号 甚至三元运算符在更复杂的情况下变得更难理解 功能。

方法 C.1

<?php
function doingSomethingIfNotNullAndPositive($var)

    if (null !== $var) 
        if (0 < $var) 
            //Doing something
         else 
            return 0;
        
     else 
        return -1;
    

优点:

明确性。每个案例都是明确的,我们可以重构 阅读时的功能。

缺点:

可读性。当添加许多 if..else 语句时,代码真的少了 可读。然后代码缩进很多次,看起来很脏。想象一下代码 有六个嵌套的if。 难以添加代码。因为逻辑看起来很复杂(即使不是), 很难在函数中添加代码或逻辑。 大量的逻辑。如果你有很多 if..else 嵌套可能是因为你 应该创建第二个函数。例如,NetBeans IDE 建议您创建 另一个处理所有嵌套块逻辑的函数。一个函数 应该是atomic,它应该只做一件事。如果它做太多的工作,有 太多的逻辑,很难维护和理解。创建其他功能 可能是个不错的选择。

方法 C.2

此方法旨在提供 C.1 表示法的替代方案。

<?php
function doingSomethingIfNotNullAndPositive($var)

    if (null === $var) 
        return -1;
     elseif (0 >= $var) 
        return 0;
    
    //Doing something

优点:

可读性。这个符号非常易读。它是 容易理解根据给定值我们会得到什么结果。 明确性。作为 C.1,这种方法在每个分支中都是明确的 条件。

缺点:

难以添加逻辑。如果函数变得有点复杂, 添加逻辑会很困难,因为我们可能需要移动 条件。

方法 D

<?php
function kindOfStrlen($var)

    $return = -1;
    if (is_string($var)) 
        $return = strlen($var);
    
    return $return;

优点:

默认值。在这个结构中我们可以看到处理了默认值 从一开始就。我们的函数中有逻辑,但是如果我们输入 no 无论如何,分支我们都有一个值。 易于添加逻辑。如果我们需要添加一个分支if,这很简单,但它不会 改变函数的结构。

常量:

不是必需的变量。在这种情况下,$return 变量不是必需的,我们 将编写相同的函数而不使用它。解决方案是 return -1 在最后,并在 if 中返回 strlen($var),它不会 可读性差。

结论

我没有在这里列出所有可能的符号,只是其中的一些。我们能做什么 想想他们是没有完美的,但在某些情况下,一种方法似乎 比另一个更好。例如 is_null 函数可以使用 方法 B。

使用方法或其他方法完全取决于您,重要的是 选择一个逻辑并在您的所有项目中保留它。

【讨论】:

【参考方案2】:
<?php
function theoreticalFunction( $var )

    if( $something > $somethingelse )
       return true;
    
    return false;

?>

这种方式也可以作为on RETURN 语句使用,返回程序光标,不执行下一条语句。

【讨论】:

【参考方案3】:

我倾向于提前返回 - 一旦你知道发生了什么就离开这个函数。如果称为“Guard Clause”,则这种用法的一种类型

我经常做的其他事情包括删除最终的else 作为默认值:

if ($something > $somethingelse) 
   return true;

return false;

事实上,if (boolean) return true; else return false 形式的条件可以进一步缩短(如果您更清楚的话)为 return ($something &gt; $somethingelse);。从这样的代码中提取一个复杂的 if 子句到一个有用的命名函数可以帮助清楚代码的含义。

【讨论】:

我想我通过使用你自己和 deceze 这样的基本示例回答了我自己的问题,他们都说过要使用非常干净、简短的 PHP 来缩短我的具体示例。现在很明显,每种方法会有多么不同,尤其是在朝着更加面向对象的方法(简单、单一用途的函数)工作时。【参考方案4】:

有人主张在函数中单个退出点(最后只有一个return),还有人主张失败/提前返回。这只是根据具体情况的意见和可读性/可理解性问题。几乎没有任何客观的技术答案。

现实情况是,这根本不是可以教条规定的东西。一些算法更好地表示为 A,而另一些算法更好地表示为 B。

在您的具体情况下,两者都不是“最好的”;你的代码应该写成:

return $something > $somethingelse;

这有望成为一个例子,说明根本不存在普遍适用的规则。

【讨论】:

这很有意义,对我来说是合乎逻辑的。感谢您回答对您来说可能是一个愚蠢/显而易见的问题:)。 确实如此。我为你提出的一个措辞恰当的问题喝彩,我也很高兴今天这个问题普遍受到欢迎。 @deceze 通常我会说现在有一个接近投票的理由:主要基于意见。但是答案本身写得很好,我可以看到将来如何问这个问题/帮助其他 SO 访问者。正如你所说:meta.***.com/questions/293931/… :) 公平地说,我从一开始就知道这将是更多的意见,并忽略了 SO 通常对基于意见的问题并不满意,尽管有时引发一些辩论会很好。我想我应该为此寻找一个论坛 :) 虽然这个演示可以很好地接触到有经验的开发人员,但我真的很重视有机会听到你对我的问题的诚实和友好的意见,它为我和其他人提供了价值,可惜它不是***上可接受的格式:) @John 这对于 cmets 来说有点元,但我完全赞成在网站上收到更多这样的问题,特别是针对常规的 debug-my-codez 内容。它只需要措辞得当,才能邀请到好的答案,这是棘手的部分。【参考方案5】:

我更喜欢变体 b。它不仅更具可读性(您确切知道在return 语句之后不需要考虑任何剩余代码),而且它也更安全。

如果您在剩余代码中存在错误,或者您在设计系统时遇到了一组您没有考虑到的情况,那么您的结果可能会发生变化。当您使用return [$someVariable] 退出函数时,不会发生这种情况;

【讨论】:

【参考方案6】:

使用方法 b 对我来说更好,因为在方法 a 中你只写了很少的代码行,但是如果有很多代码行和许多返回语句,那么我很可能会在某个地方使用错误的返回类型,其中 $return 被分配到其他地方,我没有注意到。

【讨论】:

以上是关于在 PHP 函数/方法中返回的最佳实践的主要内容,如果未能解决你的问题,请参考以下文章

使用返回 true 或 false 的函数的 PHP 最佳实践是啥?

关于引用参数或显式返回值的 PHP 方法的最佳实践

温习《PHP 核心技术与最佳实践》这本书

JDK 8 函数式编程最佳实践

JDK 8 函数式编程最佳实践

JDK 8 函数式编程最佳实践