refactorability

star 279

Review code for refactorability — surface concrete, prioritized refactoring opportunities grounded in Martin Fowler's smell catalog and SOLID, augmented with static analysis tools (gocyclo, gocognit, dupl, etc.) when available. Go-first, polyglot-aware. Defaults to the current diff. Produces a High/Med/Low report with specific refactoring moves and a "Do NOT refactor" section to prevent over-eager suggestions. Triggers: /refactorability, "review for refactorability", "what should I refactor", "refactorability review", "find refactoring opportunities", "is this refactorable", "review this code for refactoring"

meain By meain schedule Updated 6/9/2026

name: refactorability description: > Review code for refactorability — surface concrete, prioritized refactoring opportunities grounded in Martin Fowler's smell catalog and SOLID, augmented with static analysis tools (gocyclo, gocognit, dupl, etc.) when available. Go-first, polyglot-aware. Defaults to the current diff. Produces a High/Med/Low report with specific refactoring moves and a "Do NOT refactor" section to prevent over-eager suggestions. Triggers: /refactorability, "review for refactorability", "what should I refactor", "refactorability review", "find refactoring opportunities", "is this refactorable", "review this code for refactoring" metadata: author: meain version: "1.0.0"

/refactorability — Refactorability Review

Surface concrete, prioritized refactoring opportunities in code. The goal is not generic "clean code" feedback — it is to point at specific smells, name the refactoring move that fixes them, and rank by impact so the user knows what to actually touch.

The review is opinionated about restraint: it must call out cases where refactoring would be premature, speculative, or net-negative.

Process

1. Pick the scope

In order of preference:

  1. Explicit target the user named (file, function, package).
  2. Current diff (default when no target given):
    • jj repo: jj diff --name-only -r @ (fallback to jj diff --name-only)
    • git repo: git diff --name-only HEAD (plus --cached if there's nothing unstaged)
    • PR context: gh pr diff if a PR is being reviewed
  3. Whole package/module only if the user explicitly asks for it.

Print the resolved scope before continuing so the user can correct it.

2. Detect language and tools

Look at file extensions in scope. For each language present, check which of the tools below are on PATH and run them only on files in scope (not the whole repo).

Go (primary)

Tool Invocation (per file or dir) What it gives you
gocyclo gocyclo -over 15 <files> Cyclomatic complexity > 15
gocognit gocognit -over 15 <files> Cognitive complexity > 15
dupl dupl -threshold 50 <dirs> Duplicated token sequences
revive revive -formatter friendly <files> Style + some smell rules
golangci-lint golangci-lint run --no-config --disable-all --enable=gocyclo,gocognit,dupl,gocritic,revive <pkg> Aggregated, if standalone tools are missing

Also do a quick grep/AST scan for: functions > ~80 lines, > 5 params, deep nesting (> 3 levels), interface{}/any over-use, and large switch/if ladders on type.

Python

ruff check, radon cc -s -a <files>, radon mi <files>, vulture <files>, pylint --disable=all --enable=R <files> for refactor-class warnings.

JS/TS

eslint with eslint-plugin-sonarjs if configured, jscpd <dirs> for duplication, tsc --noEmit for type smells.

Polyglot fallback

semgrep --config=p/code-smells if installed; otherwise lean on LLM reading.

If no tools are available, proceed with LLM-only reading and say so in the report (so the user knows the quantitative pass was skipped).

3. Apply the lens

Read the code in scope and map findings to the Fowler smell catalog + SOLID. Use references/code-smells.md as the authoritative list. Do not invent smell names — pick from the catalog. For each finding, pick a concrete refactoring move from the same catalog (e.g. "Extract Method", "Replace Conditional with Polymorphism", "Introduce Parameter Object").

4. Score severity

Assign each finding a severity:

  • High — actively blocks change/test/understand. Examples: function with cyclomatic > 20 in a hot path, duplicated business logic across files, god-object that everything imports, shotgun-surgery pattern around a single concept.
  • Medium — measurable maintenance tax but localized. Examples: long parameter list on a helper, feature envy across two files, modest duplication.
  • Low — taste / future-proofing. Examples: primitive obsession on one type, slightly long method, comments hiding an obvious extract.

If a finding could be either, prefer the lower severity. The bar for High is "the next person changing this will get hurt."

5. Decide what NOT to refactor

Before writing the report, explicitly identify code that could look refactorable but should be left alone for this review. Put these in a dedicated section (see below). Common cases:

  • Working, stable code with no upcoming change — refactoring is pure risk.
  • Code that's verbose because of a clear API contract (e.g. protobuf gen, handler boilerplate).
  • A single duplication (rule of three not met).
  • Abstraction that would only have one caller.
  • Tests — they're allowed to be repetitive and explicit.
  • Generated code.

6. Write the report

Use the output format below. Keep it terse and scannable — bullets, tables, file:line references. No motivational filler.

Output format

# Refactorability Review

**Scope:** <files / diff / package being reviewed>
**Tools run:** gocyclo, gocognit, dupl  (or: "none — LLM-only pass")
**Overall:** <one sentence. e.g. "Two High-severity hotspots in user-management/handlers,
the rest is healthy.">

## High

### 1. <Smell name from catalog> — `path/to/file.go:123`
- **What:** <1 sentence describing the smell concretely>
- **Signal:** <metric or quote, e.g. "gocyclo=24, 142 LOC, 6 params">
- **Why it matters:** <1–2 sentences on change/test/understand cost>
- **Move:** <Refactoring name from catalog> — <1–2 sentence sketch>
- **Effort / Risk:** S/M/L — <1 short note on risk>

### 2. ...

## Medium

### 1. ...

## Low

### 1. ...

## Do NOT refactor

- `path/to/file.go:45` — Looks like primitive obsession, but it's a single call site behind
  a stable API. Wait until a second caller appears.
- `path/to/gen_pb.go` — Generated.
- ...

## Notes (optional)
Anything the user should know but isn't a finding (e.g. "gocognit not installed, skipped
cognitive complexity pass").

Guidelines

  • Cite the catalog. Every finding's smell name and refactoring move must come from references/code-smells.md. If you want to flag something not in the catalog, call it a "Note" instead of a finding.
  • Always include file:line. No "in some handler somewhere".
  • Quote a signal. A metric (gocyclo=24), a count (6 parameters), or 2–4 lines of code. Without a signal it's just opinion.
  • One paragraph per finding, max. This is a triage tool, not a design doc.
  • Resist these temptations:
    • Style / naming nits (use a linter for those)
    • "Add tests" — that's a separate review
    • Rewrites — only suggest local refactoring moves
    • "Use design pattern X" without a smell to justify it
    • Speculative generality ("what if we need to swap the DB later?")
    • Performance — separate review unless the smell causes the perf issue
  • High-severity ceiling. Aim for ≤ 3 High findings per review. If everything is High, nothing is.
  • Honor existing project conventions. If the codebase is consistently structured a certain way (e.g. Veeam VDC handlers), don't flag conformance to that style as a smell.

When to fail loudly

  • If the scope is empty (no diff, no target), ask the user what to review.
  • If the user asks to review > ~50 files in one go, push back and propose narrowing.
  • If running a tool errors out (e.g. gocyclo not installed), note it in "Notes" — do not silently skip.

Reference

Install via CLI
npx skills add https://github.com/meain/dotfiles --skill refactorability
Repository Details
star Stars 279
call_split Forks 10
navigation Branch main
article Path SKILL.md
More from Creator