low-complexity

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Low Complexity Code

低复杂度代码

Every function/method written or modified MUST target:
  • Cognitive Complexity <= 5 (SonarSource metric). Acceptable up to 10 for inherently complex logic. Never exceed 15.
  • Cyclomatic Complexity <= 5. Acceptable up to 10. Never exceed 15.
For full scoring rules, see cognitive-complexity-spec.md.
所有编写或修改的函数/方法必须满足以下目标:
  • Cognitive Complexity <= 5(SonarSource 指标)。对于本身逻辑复杂的场景,可接受上限为10,但绝对不能超过15。
  • Cyclomatic Complexity <= 5。可接受上限为10,绝对不能超过15。
完整评分规则请参考 cognitive-complexity-spec.md

Cognitive Complexity Quick Reference

Cognitive Complexity 快速参考

+1 for each:
if
, ternary (
? :
),
switch
(whole),
for
,
while
,
do while
,
catch
,
else if
,
else
,
goto LABEL
,
break/continue LABEL
, each method in a recursion cycle, each sequence of like boolean operators (
&&
/
||
).
+1 nesting penalty on top of structural increment for:
if
, ternary,
switch
,
for
,
while
,
catch
— when nested inside another flow-break structure.
Free (no increment): method calls,
try
,
finally
,
case
labels, null-coalescing (
?.
,
??
), early
return
, simple
break
/
continue
, lambdas (but lambdas increase nesting level).
以下每种情况加1分:
if
、三元运算符(
? :
)、
switch
(整个语句)、
for
while
do while
catch
else if
else
goto LABEL
break/continue LABEL
、递归循环中的每个方法、连续的同类布尔运算符(
&&
/
||
)。
额外加1分嵌套惩罚(在结构加分基础上):
if
、三元运算符、
switch
for
while
catch
嵌套在另一个流程中断结构内时。
不加分的情况: 方法调用、
try
finally
case
标签、空合并运算符(
?.
??
)、提前
return
、简单的
break
/
continue
、lambda表达式(但lambda会增加嵌套层级)。

Cyclomatic Complexity Quick Reference

Cyclomatic Complexity 快速参考

+1 for the method entry, +1 for each:
if
,
else if
,
for
,
while
,
do while
,
case
,
catch
,
&&
,
||
, ternary
?
. Core definition; some analyzers may vary by language.
方法入口加1分,以下每种情况加1分:
if
else if
for
while
do while
case
catch
&&
||
、三元运算符
?
。这是核心定义;部分分析工具可能因语言不同而有所差异。

Mandatory Reduction Techniques

强制降低复杂度的技巧

Apply these in order of preference:
  1. Extract method/function — Move a coherent block into a named function. Resets nesting to 0. First choice when the extracted block forms a coherent unit.
  2. Early return / guard clause — Invert condition, return early, reduce nesting by 1 level.
  3. Replace nested conditions with flat logic
    if A { if B {
    becomes
    if A && B {
    (saves nesting penalty).
  4. Replace if/else chains with polymorphism, strategy pattern, or lookup table — Eliminates branching entirely.
  5. Replace loop + condition with declarative pipeline
    filter/map/reduce
    or LINQ or streams instead of
    for
    +
    if
    .
  6. Decompose boolean expressions — Extract complex conditions into named boolean variables or predicate functions.
  7. Replace flag variables with early exit — Eliminate boolean flags that control flow later.
  8. Use language idioms — Null-coalescing, optional chaining, pattern matching, destructuring. These are often lower-cost than equivalent if/else chains (destructuring is free; pattern matching is +1 for the whole match vs +1 per branch in if/else).
按优先级顺序应用以下技巧:
  1. Extract method/function — 将连贯的代码块移至一个命名函数中。将嵌套层级重置为0。当待提取的代码块构成一个连贯单元时,这是首选方案。
  2. Early return / guard clause — 反转条件,提前返回,将嵌套层级降低1级。
  3. Replace nested conditions with flat logic — 将
    if A { if B {
    改为
    if A && B {
    (避免嵌套惩罚)。
  4. Replace if/else chains with polymorphism, strategy pattern, or lookup table — 完全消除分支。
  5. Replace loop + condition with declarative pipeline — 使用
    filter/map/reduce
    、LINQ或流替代
    for
    +
    if
  6. Decompose boolean expressions — 将复杂条件提取为命名布尔变量或谓词函数。
  7. Replace flag variables with early exit — 移除用于后续控制流程的布尔标志。
  8. Use language idioms — 使用空合并运算符、可选链、模式匹配、解构赋值。这些通常比等效的if/else链成本更低(解构赋值不加分;整个pattern matching语句加1分,而if/else每个分支加1分)。

How to Apply

应用方法

When writing any function/method:
  1. Write the logic
  2. Mentally count: each
    if/else if/else/for/while/switch/catch/ternary
    = +1, each nesting level on structural ones = +1 more, each boolean operator sequence = +1
  3. If score > 5, refactor using the techniques above before finalizing
  4. Prefer multiple small functions over one large function
  5. Nesting depth > 2 is a smell — extract immediately
编写任何函数/方法时:
  1. 编写逻辑代码
  2. 手动计算分数:每个
    if/else if/else/for/while/switch/catch/三元运算符
    加1分,结构语句的每个嵌套层级额外加1分,连续的布尔运算符加1分
  3. 如果分数>5,在定稿前使用上述技巧进行重构
  4. 优先选择多个小函数,而非一个大函数
  5. 嵌套深度>2属于代码坏味道——立即进行提取重构

Bad vs Good Examples

反面示例 vs 正面示例

Bad: Nested conditionals (CogC = 9)

反面示例:嵌套条件语句(CogC = 9)

python
def process(user, order):
    if user.is_active:                    # +1
        if order.is_valid:                # +2 (nesting=1)
            if order.total > 100:         # +3 (nesting=2)
                apply_discount(order)
            else:                         # +1
                charge_full(order)
        else:                             # +1
            raise InvalidOrder()
    else:                                 # +1
        raise InactiveUser()              # Total: 1+2+3+1+1+1 = 9
python
def process(user, order):
    if user.is_active:                    # +1
        if order.is_valid:                # +2 (nesting=1)
            if order.total > 100:         # +3 (nesting=2)
                apply_discount(order)
            else:                         # +1
                charge_full(order)
        else:                             # +1
            raise InvalidOrder()
    else:                                 # +1
        raise InactiveUser()              # Total: 1+2+3+1+1+1 = 9

Good: Guard clauses + extraction (process CogC=2, charge CogC=2)

正面示例:守卫子句 + 提取重构(process 函数CogC=2,charge函数CogC=2)

python
def process(user, order):               # CogC = 2
    if not user.is_active:                # +1
        raise InactiveUser()
    if not order.is_valid:                # +1
        raise InvalidOrder()
    charge(order)

def charge(order):                       # CogC = 2
    if order.total > 100:                 # +1
        apply_discount(order)
    else:                                 # +1
        charge_full(order)
python
def process(user, order):               # CogC = 2
    if not user.is_active:                # +1
        raise InactiveUser()
    if not order.is_valid:                # +1
        raise InvalidOrder()
    charge(order)

def charge(order):                       # CogC = 2
    if order.total > 100:                 # +1
        apply_discount(order)
    else:                                 # +1
        charge_full(order)

Bad: Loop with nested conditions (CogC = 10)

反面示例:带嵌套条件的循环(CogC = 10)

javascript
function findFirst(items, criteria) {
  for (const item of items) {              // +1
    if (item.active) {                     // +2 (nesting=1)
      if (item.type === criteria.type) {   // +3 (nesting=2)
        if (item.score > criteria.min) {   // +4 (nesting=3)
          return item;
        }
      }
    }
  }                                        // Total: 1+2+3+4 = 10
  return null;
}
javascript
function findFirst(items, criteria) {
  for (const item of items) {              // +1
    if (item.active) {                     // +2 (nesting=1)
      if (item.type === criteria.type) {   // +3 (nesting=2)
        if (item.score > criteria.min) {   // +4 (nesting=3)
          return item;
        }
      }
    }
  }                                        // Total: 1+2+3+4 = 10
  return null;
}

Good: Flat filter + early continue (findFirst CogC=5, matches CogC=1)

正面示例:扁平化过滤 + 提前continue(findFirst 函数CogC=5,matches函数CogC=1)

javascript
function findFirst(items, criteria) {      // CogC = 5
  for (const item of items) {              // +1
    if (!item.active) continue;            // +2 (nesting=1)
    if (matches(item, criteria)) return item; // +2 (nesting=1)
  }
  return null;
}

function matches(item, criteria) {         // CogC = 1
  return item.type === criteria.type       // +1 (&& sequence)
    && item.score > criteria.min;
}
javascript
function findFirst(items, criteria) {      // CogC = 5
  for (const item of items) {              // +1
    if (!item.active) continue;            // +2 (nesting=1)
    if (matches(item, criteria)) return item; // +2 (nesting=1)
  }
  return null;
}

function matches(item, criteria) {         // CogC = 1
  return item.type === criteria.type       // +1 (&& sequence)
    && item.score > criteria.min;
}