low-complexity
npx skills add https://github.com/mryll/skills --skill low-complexity
Agent 安装分布
Skill 文档
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 Quick Reference
+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).
Cyclomatic Complexity Quick Reference
+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.
Mandatory Reduction Techniques
Apply these in order of preference:
- 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.
- Early return / guard clause â Invert condition, return early, reduce nesting by 1 level.
- Replace nested conditions with flat logic â
if A { if B {becomesif A && B {(saves nesting penalty). - Replace if/else chains with polymorphism, strategy pattern, or lookup table â Eliminates branching entirely.
- Replace loop + condition with declarative pipeline â
filter/map/reduceor LINQ or streams instead offor+if. - Decompose boolean expressions â Extract complex conditions into named boolean variables or predicate functions.
- Replace flag variables with early exit â Eliminate boolean flags that control flow later.
- 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).
How to Apply
When writing any function/method:
- Write the logic
- 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 - If score > 5, refactor using the techniques above before finalizing
- Prefer multiple small functions over one large function
- Nesting depth > 2 is a smell â extract immediately
Bad vs Good Examples
Bad: Nested conditionals (CogC = 9)
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)
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)
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)
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;
}