2012-05-08 155 views
3

这是一个普遍的排序问题,但解释它我会用一个具体的例子。PHP短路评估(好/坏?)

我有一个加载文档的函数。如果该文档不存在,它将创建它,如果它存在,它会将其转换为JSON数组。我总是希望这个函数返回一个某种类型的数组,无论json_decode()是否存在问题,或者文件不存在。目前,我做这件事是这样的...

function load($file) { 
    if(! file_exists($file)) { 
     $handle = fopen($file, 'w'); 
     fclose($handle); 
    } 

    $raw = file_get_contents($file); 
    $contents = json_decode($raw, TRUE); 

    return(! $contents ? array() : $contents); 
    //cant use ternary shorthand "?:" in PHP 5.2, otherwise this would be shorter 
} 

现在,有没有错,上面的代码(至少我不觉得有什么,它工作正常)。不过,我一直在寻找方法来改善我的代码并在保持完美清晰的同时对其进行压缩。这个回归声明一直困扰着我,因为它看起来效率很低。所以今天我开始思考和发生了一些事情。我记得看到mysql教程做了一些connect() or die();的效果,所以我想,为什么不json_decode() or array();?这甚至会工作吗?所以我重写了我的功能找出...

function load($file) { 
    if(! file_exists($file)) { 
     $handle = fopen($file, 'w'); 
     fclose($handle); 
    } 

    $raw = file_get_contents($file); 
    return json_decode($raw, TRUE) or array(); 
} 

它似乎,它甚至读取愉快足够。因此,我的下一轮问题。这是好的做法吗?我明白,但是会有其他人吗?它真的有效吗?或者这是一个有一个快乐结局的错误?我得四处看看,发现我问的是短路评估,而不是一个错误。这很好知道。我用这个新术语来改进我的搜索,并提出了一些更多的材料。

Blog Entry

Wikipedia

没有太多,我发现大多数的一切,谈到了我询问总是提到的MySQL连接的方式使用短路。现在,我知道大多数人反对使用术语,但仅仅是因为它是处理错误的一种不雅的方式。这不是我询问的方法的问题,因为我不打算使用or die()。有没有其他的理由不使用它?维基百科似乎认为是这样,但只是参考C.我知道PHP是用C编写的,所以这是绝对有用的信息。但是这个问题在PHP编译中已经出现了吗?如果不是这样,它和维基百科一样糟糕吗?

这是维基百科的片段。 “短路会导致现代处理器的分支预测出现错误,并且会大大降低性能(一个值得注意的例子是高度优化的射线跟踪中与轴对齐的盒子相交代码的光线)[需要澄清]。一些编译器可以检测到这种情况并发出更快的代码,但由于可能违反C标准,并不总是可能的。高度优化的代码应该使用其他方式来执行此操作(如手动使用汇编代码)“

什么你们都在想吗?

编辑

我调查的另一个论坛,并得到了一些好成绩出现。普遍的共识似乎是,这种形式的变量赋值虽然有效,但并不是首选,甚至可能被认为是现实世界中的不良形式。我会继续留心,如果有新事物出现,我会更新它。感谢Corbin和Matt提供的信息,尤其是Corbin为了解决一些问题。 Here的链接到论坛帖子,如果你有兴趣。

+3

@DaveRandom反对php的人的典型答案 – Matt

+3

在您的原始返回声明中,为什么要烘焙消极? '返回$内容? $ contents:array();'。也不需要父母。 – Madbreaks

+0

@Madbreaks:这实际上是从我之前删除的一个条件。它最初看起来像'return(!isset($ contents)||!$ contents?array():$ contents);'这可能会让我更加明白为什么它是这样的,我只是忽略了在我休息时重新定位改变了它。 – mseancole

回答

2

您提出了几个不同的问题,所以我会尽力解决所有问题。

错过的分支预测:除非您使用C语言或汇编语言编写代码,否则不要担心。在PHP中,你远离硬件,因此关于分支预测的想法不会对你有所帮助。无论哪种方式,这将是一个非常微观的优化,尤其是在开始进行大量字符串分析的函数中。

有没有其他理由不使用它?维基百科似乎认为是这样,但只是参考C.我知道PHP是用C编写的,所以这是绝对有用的信息。

PHP可能会将其解析为不同的执行结构。除非你计划数百万次运行这个函数,或者你知道这是一个瓶颈,否则我不会担心。在2012年,我发现使用or进行短路的可能性很小,甚至会导致第十亿分之一秒的差异。

至于格式,我发现$a or $b相当丑陋。我的思想不能理解它在if语句中看到的短路。

if (a() || b()) 

对我而言,b()只有在a()不计算为真时才会执行。

但是:

return a() or b(); 

不具有相同的清晰度给我。

这显然只是一个意见,但我会提供两种选择,我怎么可能会写它(这是,在我看来,一个非常小的更清楚一点):

function load($file) { 
    if (!file_exists($file)) { 
     touch($file); 
     return array(); 
    } 

    $raw = file_get_contents($file); 

    $contents = json_decode($raw, true); 

    if (is_array($contents)) { 
     return $contents; 
    } else { 
     return array(); 
    } 

} 

如果你不”不在乎如果文件实际上被创建,你可以把它一步更远:

function load($file) { 

    $raw = file_get_contents($file); 

    if ($raw !== false) { 
     $contents = json_decode($raw, true); 
     if ($contents !== null) { 
      return $contents; 
     } 
    } 

    return array(); 

} 

我想真的这些代码段中归结为个人喜好。第二个片段可能是我想要的片段。关键路径可能会更清晰一些,但我觉得它保持简洁而不牺牲可理解性。

编辑:如果你是一个1-返回每个函数的类型的人,下面可能是一个比较理想一点:

function load($file) { 

    $contents = array(); 

    $raw = file_get_contents($file); 

    if ($raw !== false) { 
     $contents = json_decode($raw, true); 
     if ($contents === null) { 
      $contents = array(); 
     } 
    } 

    return $contents; 

} 
+1

我为每个函数投票一个return语句。 – Madbreaks

+3

@Madbreaks我期待有人这样说。如果您尽早解决错误案例,我会发现它更加清晰。为什么还要通过函数的其余部分处理错误?而且,您可以浏览它并立即查看该功能在顶部检查的内容。 (尽管我提供的替代方案都不是这方面的特例。) – Corbin

+0

我实际上与Madbreaks达成协议。我认为一个退出点比许多更好。很多人只喜欢一个入口点。它的概念是一样的。不必跟踪多个回报意味着我可以更轻松地控制什么退出该功能以及如何处理它。谢谢您的回答。将它改为'return a()|| b()'对你更有意义?两者都是有效的,我也更喜欢后面的,我只用'或'来保留前面的例子。 – mseancole

1

凝代码为简约的线条可能的,你可以得到它并不是总是最好的方法,因为通常压缩代码看起来很酷,但通常难以阅读。如果您对代码和可读性有任何疑问,我建议您在代码中添加一些标准注释,以便任何人都可以从您的注释中理解代码。

在最佳实践方面,那是见仁见智的,如果你喜欢它,然后去用它,你总是可以稍后再讲代码下的项目的生活,如果需求是

+0

是的,我知道,如果我想澄清一点,我通常会添加评论。我确实喜欢确保我的代码仍然清晰易读,这就是为什么我不总是浓缩它,只有当我认为它很容易理解。 – mseancole

0

我喜欢短路声明是进行单线变量检查的一种方式。

我喜欢:

isset($value) or $value = 0; 

不是:

if (!isset($value)) { 
    $value = 0; 
} 

但我还没有在收益直接使用它,这篇文章提出想试试。

可悲的是,它不能正常工作,至少对我来说:

return $data[$key] or $data[1]; 

将返回值1在所有情况下,而我在等一个阵列。

下工程进展顺利:

// Make sure $key is valid. 
$data[$key] or $key = 1; 

return $data[$key]; 

但我很惊讶,当$关键不在$数据存在PHP不抛出任何错误。