You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何避免多if/else并重构ngOnChanges将认知复杂度降至15?

降低认知复杂度&重构ngOnChanges的方案

一、通用方法:减少if/else、降低认知复杂度

认知复杂度衡量的是代码的理解难度,核心关联分支嵌套、流程跳转的频次。要降低它,核心是让逻辑更扁平、单一职责:

  • 用默认值替代存在性判断:用obj.key ?? 默认值或解构赋值带默认值,替代if (!obj.hasOwnProperty('key'))这类重复判断
  • 拆分逻辑到独立函数:把不同功能块抽成小函数,每个函数只做一件事,避免大函数里堆一堆分支
  • 简化嵌套条件:把嵌套的if拆成扁平判断,或用提前返回减少嵌套层级
  • 用对象映射替代多分支if/else:如果是根据不同值执行不同操作,把对应关系存在对象里,直接通过键取值调用,替代一堆else if

二、针对你的ngOnChanges代码的重构步骤

你的代码里大量重复使用hasOwnProperty判断,加上嵌套分支,导致认知复杂度居高不下。下面是具体重构方案:

步骤1:提前合并chartData默认值

先给chartData补全默认值,避免后续重复做存在性判断:

const defaultChartData = {
  rotation: -90,
  circumference: 360,
  cutoutPercentage: 90,
  legendPosition: "bottom",
  chartTitleFontSize: 20,
  aspectRatio: 3,
};
// 合并用户传入的配置和默认值
this.chartData = { ...defaultChartData, ...this.chartData };

步骤2:抽离颜色配置逻辑

把颜色相关的判断拆成独立函数,单一职责更清晰:

private getChartColors(): Array<{ backgroundColor?: string[] }> {
  if (this.chartData.color) {
    return [this.chartData.color];
  }
  return [
    {
      backgroundColor: [
        LEDSColorPalette.purple[500],
        LEDSColorPalette.purple[50],
      ]
    }
  ];
}

步骤3:拆分options构建逻辑

把options的构建拆成多个小函数,每个子函数负责一个细分功能:

// 处理tooltips回调
private buildTooltipsCallbacks() {
  if (!this.chartData.tooltipsCallbacks) return {};
  const callbacks: Record<string, Function> = {};
  Object.keys(this.chartData.tooltipsCallbacks).forEach(key => {
    const config = this.chartData.tooltipsCallbacks[key];
    callbacks[key] = new Function(config.arguments, config.body);
  });
  return callbacks;
}

// 处理中心文本格式
private processCenterText() {
  if (!this.chartData.centerText) return false;
  
  let centerText: Array<{ text: string, font?: any, color?: string }> = [];
  // 统一转为数组对象格式
  if (typeof this.chartData.centerText === 'string') {
    centerText = [{ text: this.chartData.centerText }];
  } else if (Array.isArray(this.chartData.centerText)) {
    centerText = this.chartData.centerText.map(elem => 
      typeof elem === 'object' ? elem : { text: elem }
    );
  } else if (typeof this.chartData.centerText === 'object') {
    centerText = [this.chartData.centerText];
  }

  // 补全文本默认配置
  return centerText.map((label, index) => {
    label.text = String(label.text);
    label.font = label.font || {};
    label.font.family = label.font.family || '"Myriad Set Pro",Arial';
    if (index === 0) {
      label.font.size = label.font.size || "40";
      label.color = label.color || "#000";
    }
    return label;
  });
}

// 构建完整的options配置
private buildChartOptions() {
  const centerText = this.processCenterText();
  
  return {
    rotation: this.chartData.rotation * (Math.PI / 180),
    responsiveAnimationDuration: 3000,
    maintainAspectRatio: false,
    circumference: this.chartData.circumference * (Math.PI / 180),
    responsive: true,
    cutoutPercentage: this.chartData.cutoutPercentage,
    tooltips: {
      enabled: this.chartData.tooltips ?? false,
      callbacks: this.buildTooltipsCallbacks()
    },
    animation: { duration: 3000 },
    legend: {
      position: this.chartData.legendPosition,
      labels: { usePointStyle: true }
    },
    title: {
      display: this.chartData.chartTitle,
      text: this.chartData.chartTitle,
      fontSize: this.chartData.chartTitleFontSize,
      fontColor: this.chartData.chartTitleFontColor,
    },
    plugins: {
      dataLabels: this.chartData.dataLabels ?? false,
      doughnutlabel: centerText ? { labels: centerText } : false,
    },
    layout: this.chartData.layout || {},
    aspectRatio: this.chartData.aspectRatio,
  };
}

步骤4:重构后的ngOnChanges

现在ngOnChanges变得极度简洁,逻辑一目了然:

ngOnChanges() {
  // 基础数据赋值
  this.dataset.data = this.chartData.data;
  this.labels = this.chartData.labels;
  this.legend = this.chartData.legend;
  this.chartStyle = this.chartData.chartStyle || {};

  // 处理数据缺失场景
  if (this.chartData.dataPresent === false) {
    this.dataAbsent = true;
    this.chartStyle = { display: "none" };
  }

  // 合并默认配置
  const defaultChartData = {
    rotation: -90,
    circumference: 360,
    cutoutPercentage: 90,
    legendPosition: "bottom",
    chartTitleFontSize: 20,
    aspectRatio: 3,
  };
  this.chartData = { ...defaultChartData, ...this.chartData };

  // 赋值颜色和最终配置
  this.colors = this.getChartColors();
  this.options = this.buildChartOptions();
}

重构后的效果

  • 所有嵌套分支被拆成扁平的独立函数,每个子函数的认知复杂度都远低于15
  • ngOnChanges本身仅负责调用各子函数,认知复杂度降到个位数
  • 代码职责划分清晰,新人接手时能快速定位各功能模块

内容的提问来源于stack exchange,提问作者rahul-kola

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 11:45:36