我有这个函数负责将文件名和 mime 类型转换为更“人性化”的东西(例如 file.png、image/png 到 [Image, PNG])。我发现有趣的是,if() elseif()
语句组的 NPath 复杂度高于 switch(true)
语句。
使用以下代码,PHP Mess Detector 输出 4410 的 NPath:
public function humanKind()
{
$typeRA = explode("/", strtolower($this->type));
$fileRA = explode(".", $this->name);
$fileType = strtoupper($fileRA[count($fileRA) - 1]);
switch($typeRA[0]) {
case "image":
$humanType = "Image";
break;
case "video":
$humanType = "Video";
break;
case "audio":
$humanType = "Sound";
break;
case "font":
$humanType = "Font";
break;
default:
$humanType = "File";
}
switch ($this->type) {
case "application/msword":
case "application/pdf":
case "applicaiton/wordperfect":
case "text/plain":
case "text/rtf":
case "image/vnd.photoshop":
case "image/psd":
case "image/vnd.adobe.photoshop":
case "image/x-photoshop":
case "application/xml":
case "application/x-mspublisher":
case "text/html":
case "application/xhtml+xml":
case "text/richtext":
case "application/rtf":
case "application/x-iwork-pages-sffpages":
case "application/vnd.apple.pages":
$humanType = "Document";
break;
case "application/vnd.ms-excel":
case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
case "application/x-iwork-numbers-sffnumbers":
case "application/vnd.apple.numbers":
$humanType = "Spreadsheet";
break;
case "application/vnd.ms-powerpoint":
case "application/vnd.openxmlformats-officedocument.presentationml.presentation":
case "application/vnd.openxmlformats-officedocument.presentationml.slideshow":
case "application/x-iwork-keynote-sffkey":
case "application/vnd.apple.keynote":
$humanType = "Slideshow";
break;
case "application/zip":
case "application/x-zip-compressed":
case "application/x-compressed":
case "application/x-compress":
case "application/x-rar-compressed":
case "applicaiton/x-7z-compressed":
case "application/x-ace-compressed":
$humanType = "Archive";
break;
case "text/x-vcard":
case "text/x-ms-contact":
$humanType = "Contact";
break;
case "text/x-php":
case "application/x-dosexec":
case "application/x-xpinstall":
case "application/x-opera-extension":
case "application/x-chrome-extension":
case "application/x-perl":
case "application/x-shockwave-flash":
case "application/java-archive":
$humanType = "Program";
break;
case "application/vnd.ms-fontobject":
case "application/font-woff":
case "application/x-font-truetype":
case "application/x-font-opentype":
case "application/x-font-ttf":
case "application/font-sfnt":
$humanType = "Font";
break;
}
// Special Cases
if ($humanType == "Archive" && $fileType == "APK") { // Android App
$humanType = "App";
} elseif ($humanType == "Archive" && $fileType == "XPS") {
$humanType = "Document";
} elseif ($this->type == "application/xml" && $fileType == "CONTACT") {
$humanType = "Contact";
} elseif ($this->type == "application/octet-stream" && $fileType == "JNT") {
$humanType = "Document";
}
if (strlen($fileType) > 4) {
$fileType = "";
}
return array($humanType, $fileType);
如果我们将特殊情况 if elseif
替换为以下内容:
// Special Cases
switch(true) {
case ($humanType == "Archive" && $fileType == "APK"): // Android App
$humanType = "App";
break;
case ($humanType == "Archive" && $fileType == "XPS"):
$humanType = "Document";
break;
case ($this->type == "application/xml" && $fileType == "CONTACT"):
$humanType = "Contact";
break;
case ($this->type == "application/octet-stream" && $fileType == "JNT"):
$humanType = "Document";
break;
}
PHP Mess Detector 报告 1960 年的 NPath 复杂度。
这是为什么?是什么让 switch(true) 比我看来的几乎相同的控制结构更简单?
最佳答案
由于 NPath 复杂性衡量完成所需的单元测试数量 coverage of your code您的 2 个“特例”实现应该没有区别。
但是在计算上有些差异。让我们逐步完成 2 个“特例”实现并手动计算 NPath 复杂度:
NPath 复杂度与 if .. elseif ..
if ($humanType == "Archive" && $fileType == "APK") { // Android App
$humanType = "App";
}
elseif ($humanType == "Archive" && $fileType == "XPS") {
$humanType = "Document";
}
elseif ($this->type == "application/xml" && $fileType == "CONTACT") {
$humanType = "Contact";
}
elseif ($this->type == "application/octet-stream" && $fileType == "JNT") {
$humanType = "Document";
}
此语句的 NPath 复杂度为 9:if .. else
为 1 分,每个 if(expr)
为 1 分,并且每个 &&
运算符得 1 分。 (1 + 4 + 4 = 9)
NPath 复杂度与 switch(true)
switch(true) {
case ($humanType == "Archive" && $fileType == "APK"): // Android App
$humanType = "App";
break;
case ($humanType == "Archive" && $fileType == "XPS"):
$humanType = "Document";
break;
case ($this->type == "application/xml" && $fileType == "CONTACT"):
$humanType = "Contact";
break;
case ($this->type == "application/octet-stream" && $fileType == "JNT"):
$humanType = "Document";
break;
}
并且此语句导致 NPath 复杂度仅为 4:switch(true)
为 0 分,因为它不包含 &&
或 ||
运算符,每个 case
标签得 1 分。 (0 + 4 = 4)
humanKind
函数的 NPath 复杂度
为每个语句计算 NPath 值,然后将这些值相乘。没有“特殊情况”语句的函数的 NPath 复杂度为 490。乘以 9 的 if .. else if ..
语句的 NPath 值,您得到 4410 的 NPath 复杂度。并相乘使用 4 的 switch(true)
语句的 NPath 值,您得到的复杂度仅为 1960。这就是全部!
现在我们知道:NPath Complexity 不衡量 switch
语句中 case
标签的表达式复杂性!
关于php - 为什么 switch(true) 的 NPath 复杂度比 if() elseif() 小?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21146409/