当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
答案 0 :(得分:4)
您的代码实际上相对简单,结构不合理。我建议创建一个子函数,它接受两个参数并处理-1/1的返回,然后遍历一个字段数组来检查,因为这样会更容易,但是一些东西注意:
你的方式还可以。它不干净,但它很清楚,如果它有效,就没有迫切需要改变它 - 任何看过它的程序员都能够理解你在做什么,即使他们嘲笑你的实现。
复杂性不是圣杯。这很重要,作为一名程序员,他做了大量的维护编程,我认为编写我保持的代码的人知道复杂性是非常重要的,但你不能完全避免复杂性,有时候复杂解决方案(使用McCabe的复杂性)是最容易阅读的。
我真正建议你做的唯一改变是只有一次回电。做类似的事情:
$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;
}