如何重构代码将认知复杂度从19降至SonarQube允许的15
解决SonarQube认知复杂度过高的时间格式化重构方案
问题背景
在SonarQube中收到提示:"重构此方法以将认知复杂度从19降至允许的15",其中daysPassed为分钟格式的时间,以下是原代码及尝试重构但未成功的代码:
原代码
let output = ""; if (daysPassed < 60) { output = this.formatOutput(daysPassed, "min"); } else if (daysPassed < 60 * 24) { output = this.formatOutput(Math.floor(daysPassed / 60), "hour"); } else if (daysPassed < 60 * 24 * 30) { output = this.formatOutput(Math.floor(daysPassed / (60 * 24)), "day"); } else { output = this.formatOutput(Math.floor(daysPassed / (60 * 24 * 30)), "month"); } formatOutput(value, unit) { return `${value} ${unit}${value === 1 ? '' : 's'} ago`; }
尝试的重构代码(未成功)
let output = ""; if (daysPassed < 60) { output = `${Math.floor(daysPassed)} mins ago`; } else if (daysPassed < 60 * 24) { output = `${Math.floor(daysPassed / 60)} hours ago`; } else { const timeUnits = [ { unit: "day", duration: 60 * 24 }, { unit: "month", duration: 60 * 24 * 30 } ]; for (const unit of timeUnits) { if (daysPassed < unit.duration * 30) { output = `${Math.floor(daysPassed / unit.duration)} ${unit.unit}${Math.floor(daysPassed / unit.duration) === 1 ? '' : 's'} ago`; break; } } }
可行的重构方案
核心思路是把所有时间单位的转换规则整理成有序数组,通过遍历数组匹配符合条件的单位,彻底移除多层if-else分支,直接降低认知复杂度。
重构后代码(简洁版)
// 按时间范围从小到大定义规则:阈值、除数、单位 const timeUnitRules = [ { threshold: 60, divisor: 1, unit: 'min' }, { threshold: 60 * 24, divisor: 60, unit: 'hour' }, { threshold: 60 * 24 * 30, divisor: 60 * 24, unit: 'day' }, { threshold: Infinity, divisor: 60 * 24 * 30, unit: 'month' } // 兜底处理所有超出前面范围的情况 ]; let output = ''; for (const rule of timeUnitRules) { if (daysPassed < rule.threshold) { const value = Math.floor(daysPassed / rule.divisor); output = `${value} ${rule.unit}${value === 1 ? '' : 's'} ago`; break; } }
重构说明
- 消除分支嵌套:用数组遍历替代多层
if-else,认知复杂度大幅降低,轻松满足SonarQube的要求。 - 可维护性提升:后续新增时间单位(如年),只需在数组中添加一条规则,无需修改核心逻辑。
- 逻辑统一复用:所有单位的数值计算和格式化逻辑统一,避免重复代码,减少出错概率。
内容的提问来源于stack exchange,提问作者anonymous
相关产品推荐
相关产品推荐

