前端代码质量

550 阅读2分钟

前端代码质量

如何使前端代码变得可维护可读, 如何量化定义代码的复杂度

现状

  • 团队代码风格不一致,无法进行整体质量把控
  • 没办法量化代码复杂度

圈复杂度

定义

圈复杂度用来衡量一个模块判定结构的复杂程度,数量上表现为线性无关的路径条数,即合理的预防错误所需测试的最少路径条数。圈复杂度大说明程序代码可能质量低且难于测试和维护,根据经验,程序的可能错误和高的圈复杂度有着很大关系。

衡量标准

计算方法

采用判定节点数+1

  • 判断
  • if - else
  • switch - case
  • 一个case数量+1
  • 三元
  • 循环
  • for
  • 条件
  • && ||
function getComplexity(value) {
  let result = 1;
  if (value < 0) {
    result--;
  }

  for (let i = 0; i < 10; i++) {
    result += Math.random();
  }  

  switch (+result) {
    case 1:
      result += 20;
      break;
    case 2:
      result += 30;
      break;
    default:
      result += 10;
      break;
   }

  return result > 20 ? result : result;
}

complexity = 1(if) + 1(for) + 2(case) + 1(三目) + 1 = 6

点边计算

M = E - N + 2P
  • E: 控制流图中边的数量
  • N: 控制流中点的数量
  • P: 独立组件数量

降低圈复杂度

抽象配置

  • 优化前
function doSomething(payload) {
  if (payload.type === "EAT") {
    eat(payload.value);
  } else if (payload.type === "WRITE") {
    write(payload.value);
  } else if (payload.type === "SING") {
    sing(payload.type);
  }
}

// 圈复杂度 4
  • 优化后
const ACTIONS = {
  "EAT": eat,
  "WRITE": write,
  "SING": sing
};

function doSomething(payload) {
  ACTIONS[payload.type](payload.value);
}

// 圈复杂度 1

提炼函数

一个功能函数只做一件事

  • 优化前
function doSomething(v, u) {
  if (v < u) {
    v = v + u;
    u = v - u;
    v = v - u;
} 

doOther(v, u);
}
  • 优化后
const getOrdered(v, u) {
  if (v < u) {
    v = v + u;
    u = v - u;
    v = v - u;
}

return [v, u];
}

function doSomething(v, u) { 
  ([v, u] = getOrdered(v, u))

  doOther(v, u);
}

判断条件简化和提取

重判断提取使用Array.includes()

  • 优化前
function check(name) {
  if (name === "wuw" || name === "polm") {
    console.log("good");
  }
}
  • 优化后
const NAMES = ["wuw", "polm"];

function checkout(name) {
  if (NAMES.includes(name)) {
    console.log("good")
  }
}

使用returnbreak代替标记位

  • 优化前
function doSomething() {

  let flag = false;
  for (let i = 0, len = arr.length; i < len; i++) {
    if (arr[i].isNew) {
      flag = false;
    } 
  }

  !flag && doSomething()
}

filter(Boolean)技巧

  • 优化前

  • 优化后

includes优化()

如果你怕 includes 的兼容性不佳,可以改成 [89,91,92].indexOf(this.appId) >= 0

  • 优化前

  • 优化后