首页 > 解决方案 > 降低功能的认知复杂性

问题描述

我有一个认知复杂度为 24 的函数,但我们只允许它最大为 15。

export function parameterValueParser<T extends Structure>(
  structure: T
): (parameterValue: Value) => Parsed<T> | null {
  return (parameterValue: Value): Parsed<T> | null => {
    if (isParameterValueNumber(structure)) {
      return parseNumber(parameterValue) as Parsed<T> | null;
    }
    if (isParameterValueStruct(structure)) {
      const parameterValueChildren = parseStruct(parameterValue);
      if (parameterValueChildren == null) {
        return null;
      }
      const result = {} as { [_: string]: Parsed<Structure> };
      for (const key in structure) {
        if (structure.hasOwnProperty(key)) {
          const child = parameterValueChildren[key];
          if (child == null) {
            return null;
          }
          const parsedChild = parameterValueParser(structure[key])(child);
          if (parsedChild == null) {
            return null;
          }
          result[key] = parsedChild;
        }
      }
      return result as Parsed<T>;
    }
    return null;
  };
}

高认知复杂性的一个原因是嵌套的 ifs,并且许多在 for..of 循环下。所以即使我将代码提取到一个单独的函数中,认知复杂度也会太高。如何降低其复杂性?

标签: javascripttypescript

解决方案


这可能更适合代码审查,但我会开始重构

分解文字类型

- export function parameterValueParser<T extends Structure>(structure: T): (parameterValue: Value) => Parsed<T> | null
+ type Parser<T> = (val: Value) => Parsed<T> | null;
+ export function parameterValueParser<T extends Structure>(structure: T): Parser<T>

删除所有类型断言

- return parseNumber(parameterValue) as Parsed<T> | null;
+ return parseNumber(parameterValue);

使用有意义的变量名(太长的名字和太短的名字一样糟糕)

- const parameterValueChildren = parseStruct(parameterValue);
+ const children = parseStruct(val);

一旦准备好,您就可以开始重构您的逻辑,这将更简单“由内而外”:不是在解析器中检查结构类型,而是在外部进行并为每种类型返回一个特定的解析器:

export function parameterValueParser<T extends Structure>(struct: T): Parser<T> {
    if (isParameterValueNumber(struct)) {
        return parseNumber;
    }
    if (isParameterValueStruct(struct)) {
        return structValueParser(struct);
    }
    etc....
}

推荐阅读