修复具有高NPath复杂度的代码

时间:2011-12-05 16:25:39

标签: php phpmd

当PHPMD报告我的一些代码具有高NPath复杂度时,我正在使用PHP Mess Detector分析我的代码。一个例子是:

function compareDates($date1, $date2){
    if($date->year < $date2->year){
        return -1;
    }
    if($date->year > $date2->year){
        return 1;
    }
    if($date->month < $date2->month){
        return -1;
    }
    if($date->month > $date2->month){
        return 1;
    }
    if($date->day < $date2->day){
        return -1;
    }
    if($date->day > $date2->day){
        return 1;
    }
    // etc.. same for hour, minute, second.
    return 0;
}

结果是该函数具有非常高的NPath复杂度。是否有一种通用的编码方式来减少这种控制结构和NPath的复杂性?

源代码:http://code.google.com/p/phpraise/source/browse/trunk/phpraise/core/datetime/RaiseDateTime.php#546

3 个答案:

答案 0 :(得分:4)

您的代码实际上相对简单,结构不合理。我建议创建一个子函数,它接受两个参数并处理-1/1的返回,然后遍历一个字段数组来检查,因为这样会更容易,但是一些东西注意:

  1. 你的方式还可以。它不干净,但它很清楚,如果它有效,就没有迫切需要改变它 - 任何看过它的程序员都能够理解你在做什么,即使他们嘲笑你的实现。

  2. 复杂性不是圣杯。这很重要,作为一名程序员,他做了大量的维护编程,我认为编写我保持的代码的人知道复杂性是非常重要的,但你不能完全避免复杂性,有时候复杂解决方案(使用McCabe的复杂性)是最容易阅读的。

  3. 我真正建议你做的唯一改变是只有一次回电。做类似的事情:

    $compare_val = 0;
    

    在文件的顶部,然后更改后续if调用elseifs而不是返回值,只需更新$ compare_val并在函数结束时返回它。

答案 1 :(得分:2)

一种常见的误解是排序函数必须返回-1,0,1。你可以做到

function compareDates($date1, $date2)
{
    return strtotime("{$date1->year}-{$date1->month}-{$date1->day}")
         - strtotime("{$date2->year}-{$date2->month}-{$date2->day}");
}

请注意,如果整数限制是一个问题,您可以使用DateTime,但没有这个限制,例如。

function compareDates($date1, $date2)
{
    return new DateTime("{$date1->year}-{$date1->month}-{$date1->day}")
         < new DateTime("{$date2->year}-{$date2->month}-{$date2->day}");
}

至于减少一般的NPath复杂性:你必须减少可能的执行路径的数量。从福勒的重构书开始,先看一下关于Simplifying Conditional Expressions的章节。

在旁注中,我想知道RaiseDateTime有什么好处?它可以执行本机DateTime API无法执行的任何操作吗?如果没有,我为什么要使用它?

答案 2 :(得分:-1)

我是PHP新手并不是这个代码做的相同但只是简单吗?

function compareDates($date1, $date2){
if(($date->year < $date2->year) || ($date->month < $date2->month) || ($date->day < $date2->day) {
    return -1;
}
 if($date->year > $date2->year) || ($date->month > $date2->month) || ($date->day > $date2->day) {
    return 1;
}
// etc.. same for hour, minute, second.
return 0;
}