PHP编码风格回归;在开关/ shell 中

1qczuiv0  于 2023-03-11  发布在  PHP
关注(0)|答案(7)|浏览(104)

我们正在尝试为我们的团队实施新的编码风格指导方针,php codesniffer在switch case语句上打印一个警告,当没有找到“break”时,如下所示:

switch ($foo) {   
    case 1:
      return 1;   
    case 2:
      return 2;   
   default:
       return 3; 
}

是否有充分理由用途:

switch ($foo) {
       case 1:
         return 1;
         break;
   }

??始终未达到断点?

bxgwgixi

bxgwgixi1#

当您从switch中删除return时,忽略break是完全有效的。
但是,将显式break添加到每个case作为defensive programming实践是相当常见的做法。

switch ($foo) {
    case 1:
        return 1;
        break;

    case 2:
        return 2;
        break;
}

这样做的目的是,如果以后更改case 1中的代码并删除return语句,则可能会忘记添加break
这会意外地导致程序流掉到case 2

switch ($foo) {
    case 1:
        somethingDifferent();

    case 2:
        return 2;
        break;
}

在case语句中失败是不常见的,当你这样做的时候,你应该在代码中添加一个注解,以表明这是故意的。

switch ($foo) {
    case 1:
        somethingDifferentAndWeWantToDoCase2AsWell();
        // fallthrough

    case 2:
        return 2;
        break;
}

与许多防御性编程实践一样,您必须权衡代码膨胀(它可能会使代码混乱并降低可读性)是否值得。

5ssjco0h

5ssjco0h2#

如果你的“php codesniffer is printing a warning”,尝试另一个更好的codesniffer,不要忘记尝试使用最新的PHP稳定版本。当然,你可以在一个return之后写一个break,但这没有意义,因为它根本不会被读取。你的代码是可以的。
看看这个

$fun = function(int $argument): string {
    switch ($argument) {
        case 1:
            return "one";
        case 2:
            return "two";
        default:
            return "more than two";
    }
};
$str = $fun(4); // return "more than two"

在我看来,这样更简单,也更好:更少的行=〉需要维护的代码更少:-)

yhxst69z

yhxst69z3#

回答你的问题,不,没有好的理由拥有什么都不做的东西。这样想一想,在return之后的注解而不是break说“不要忘记”将具有相同的效果-没有。这样说听起来很傻,对吗?
除非你需要设置一个变量以便以后使用,否则我建议你的方法是完全正确的。我在看代码的2秒钟内就知道了它的意图。使用break只会造成混乱。
实际上没有万能的。正确的方法取决于哪种方法适合场景。在每个case中设置一个变量,然后拥有一个break可能是正确的方法,或者只是返回可能是有意义的。

对答复中提出的其他建议的一些看法:

**1)***在return之后没有break意味着如果以后更改代码可能会出现问题 *

只要有可能,代码应该是明确的,可读的和清晰的。我们也可以用一种方式编写代码,使未来的更改更容易。但在像switch这样简单的东西中,它应该没有问题,并且不需要安全网来重构case,以添加或删除returnbreak
事实上,如果你删除了一个return,而“* 没有注意到break *”,那么这是一个很糟糕的错误,可能会在编码的任何部分犯。没有任何gotcha检查可以保存你。一个人应该非常小心地为未来的可能性编写代码,因为这种可能性可能永远不会发生,或者其他事情可能会发生,你最终会维护过时的代码多年。
同样,这被认为是未来更改的安全网-如果您删除了return,但在应该删除它的时候意外地留在了安全网break中,该怎么办?
即使这条switch语句是生死攸关的场景,是非常严肃的代码,我也反对在return后添加“无意义”的break,只要确保编写代码的人知道他们在做什么,并且代码经过了足够多的人的审查和充分的测试。
如果它是那么严重,那么你会有额外的检查到位比建议的安全网,以赶上草率的开发人员。
认为break after return增加了一个安全网,意味着你没有正确地编码或测试,如果这个安全网被认为是有用的,那么代码中可能有大量的错误,而且可能是更严重的错误。
维基文章“Defensive Programming”被链接到,但在这里不相关:
防御性编程是一种防御性设计,旨在确保软件在不可预见的情况下继续运行。
留下一个安全网break并不是一个不可预见的情况,也不是防御性的编程。这只是糟糕的编码,**你不能把你的代码和备份代码乱丢在一起,以防你在修改一些东西时没有正确编码。**这是一个非常糟糕的编码方法。“如果有人删除了return,它就不起作用”的论点,嗯,你也可能在case var中有错字,或者忘记写case,或者...
return返回,并且您没有编写“防御性”代码来避免返回失败。这将意味着PHP被破坏,并且您不会用安全网填充您的代码来满足这种情况。这是您在更高级别上所拥有的。

2)*return之后的break保持显式 *

但它显然是错误的。return返回,所以中断不会发生。对我来说,这是一个挠头的时间,怀疑我是否错过了意图-只要不清楚 * 将 * 发生什么,但会有一个时刻,我思考它,以确保我没有错过什么。
虽然在同一个case中包含一个return和一个break并不是无效的或错误的,但是这完全是毫无意义的,因为break什么也不做。这是毫无意义的代码,需要被看到、维护和理解,因为它不符合逻辑。
如果 explicit 是核心目标 return之后有break会让你感到困惑,因为这是毫无意义的,那么我会说最好设置一个变量和break,然后在从开关断开后返回变量。
像@RageZ一样回答https://stackoverflow.com/a/1437476/2632129

**3)***设置变量并在switch语句完成后返回 *

这种方法完全没有错,但是如果没有理由将值存储在变量中(稍后使用etc),那么在不需要等待做任何其他事情的时候立即返回是很好的。
这表明了明确的意图--只要大小写匹配就返回一个值。

ovfsdjhp

ovfsdjhp4#

我有更好的解决方案。请按照下面的代码为上述开关状态:

$result = 3; // for default case
switch ($foo) {   
    case 1:
      $result = 1;
      break;  
    case 2:
      $result = 2;
      break;    
   default:
      // do nothing
}
return $result;

它不会导致任何错误,代码也符合概念。

d8tt03nd

d8tt03nd5#

从PHP 8.0开始,您可以使用match表达式:

return match ($foo) {
    1 => 1,
    2 => 2,
    default => 3,
};
3z6pesqy

3z6pesqy6#

我不是完美编码方面的Maven,但我认为验证程序更喜欢这样的代码

switch ($foo) {   
    case 1:
      $ret =  1;   
      break;
    case 2:
      $ret = 2;
      break;   
   default:
       $ret = 3

}
return $ret

我认为使用return in case语句来中断代码流并不是一个真正的最佳实践。所以这就是为什么验证器说没有break ...
对于你关于分类的问题,我不知道...对不起

pepwfjgg

pepwfjgg7#

来自PHP手册(http://us3.php.net/manual/en/control-structures.switch.php):
PHP会继续执行语句,直到switch块结束,或者第一次看到break语句。如果你不在case语句列表的末尾写break语句,PHP会继续执行下面case的语句。例如:

<?php
switch ($i) {
    case 0:
        echo "i equals 0";
    case 1:
        echo "i equals 1";
    case 2:
        echo "i equals 2";
}
?>

这里,如果$i等于0,PHP将执行所有的echo语句!如果$i等于1,PHP将执行最后两个echo语句。只有当$i等于2时,您才会得到预期的行为('i等于2'将被显示)。因此,不要忘记break语句是很重要的(即使在某些情况下您可能想故意避免提供它们)。

相关问题