plugins/autonomous-dev/skills/refactoring-patterns/SKILL.md
Safe refactoring techniques — extract, inline, rename, move, simplify conditionals, and decompose functions. Use when restructuring code without changing behavior. TRIGGER when: refactor, extract method, rename, inline, simplify, decompose, clean up, code smell. DO NOT TRIGGER when: adding features, fixing bugs, writing tests, documentation.
npx skillsauth add akaszubski/autonomous-dev refactoring-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Safe techniques for restructuring code without changing its behavior. Every refactoring follows: test green -> refactor -> test green.
Never refactor and change behavior in the same commit. Refactoring = same behavior, different structure. Feature work = different behavior. Mixing them makes bugs untraceable.
Before any refactoring:
When: A code block does one identifiable thing, or you need to add a comment explaining what a block does.
# BEFORE
def process_order(order):
# Validate order
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Negative total")
if not order.customer_id:
raise ValueError("Missing customer")
# Apply discounts
total = order.total
if order.is_member:
total *= 0.9
if len(order.items) > 10:
total *= 0.95
return total
# AFTER
def process_order(order):
validate_order(order)
return apply_discounts(order)
def validate_order(order):
if not order.items:
raise ValueError("Empty order")
if order.total < 0:
raise ValueError("Negative total")
if not order.customer_id:
raise ValueError("Missing customer")
def apply_discounts(order):
total = order.total
if order.is_member:
total *= 0.9
if len(order.items) > 10:
total *= 0.95
return total
Verification: Run tests. Output must be identical.
When: A function's body is as clear as its name, or it's only called once and adds indirection without value.
# BEFORE
def is_valid_age(age):
return age >= 0
def process(age):
if is_valid_age(age):
...
# AFTER (if is_valid_age is only used once and obvious)
def process(age):
if age >= 0:
...
When NOT to inline: If the function is called from multiple places, or if the name adds clarity that the body doesn't.
When: A name doesn't describe what the thing does, or uses abbreviations/jargon.
# BEFORE
def proc(d, f=True):
...
x = get_data()
tmp = transform(x)
# AFTER
def process_invoice(invoice_data, *, validate=True):
...
raw_invoices = fetch_invoices()
normalized_invoices = normalize(raw_invoices)
Rules:
When: A function/class is in the wrong module — it's more closely related to another module's concerns.
Process:
When: Nested if/else chains, complex boolean expressions, or repeated condition checks.
# BEFORE: Nested guards
def get_price(product, user):
if product is not None:
if product.is_available:
if user is not None:
if user.is_member:
return product.price * 0.9
else:
return product.price
else:
return product.price
else:
return None
else:
return None
# AFTER: Early returns (guard clauses)
def get_price(product, user):
if product is None or not product.is_available:
return None
if user is not None and user.is_member:
return product.price * 0.9
return product.price
When: A function is longer than ~30 lines or has multiple levels of abstraction.
Process:
# BEFORE
if response.status_code == 429:
time.sleep(60)
# AFTER
RATE_LIMIT_STATUS = 429
DEFAULT_RETRY_DELAY_SECONDS = 60
if response.status_code == RATE_LIMIT_STATUS:
time.sleep(DEFAULT_RETRY_DELAY_SECONDS)
| Smell | Refactoring | |-------|-------------| | Long function (>30 lines) | Extract Function, Decompose | | Deeply nested conditionals | Guard Clauses, Extract Function | | Duplicated code blocks | Extract Function, parameterize | | Feature envy (method uses another class's data more than its own) | Move Method | | Long parameter list (>4 params) | Introduce Parameter Object | | Comments explaining "what" (not "why") | Rename, Extract Function | | Boolean parameters | Split into two functions | | Dead code | Delete it |
# 1. Confirm tests pass BEFORE refactoring
python -m pytest tests/ -x --tb=short
# 2. Make the refactoring change
# 3. Confirm tests STILL pass
python -m pytest tests/ -x --tb=short
# 4. Verify no behavioral change
git diff # Review: structure changes only, no logic changes
| Scope | Approach | |-------|----------| | Single function | Refactor inline, same commit | | Single file | Refactor in dedicated commit | | Multiple files | Plan first, dedicated branch | | Module/package boundary | ADR required, phased approach |
development
GenAI-first testing with structural assertions, congruence validation, and tier-based test structure. Use when writing tests, setting up test infrastructure, or validating coverage. TRIGGER when: test, pytest, coverage, TDD, test patterns, congruence, validation. DO NOT TRIGGER when: production code implementation, documentation, config-only changes.
development
One topic, one home. Routes content to its canonical store (CLAUDE.md, PROJECT.md, MEMORY.md, docs/, memory/) and audits for duplication. TRIGGER when: auditing CLAUDE.md/PROJECT.md/MEMORY.md sizes, deduplicating docs, applying the content-allocation pattern to a new repo, running /align --content. DO NOT TRIGGER when: implementing features, writing tests, routine code edits, debugging.
testing
Prompt engineering patterns for writing agent prompts and skill files — constraint budgets, register shifting, HARD GATE patterns, anti-personas. Use when writing or reviewing agents/*.md or skills/*/SKILL.md. TRIGGER when: agent prompt, skill file, prompt engineering, model-tier compensation, HARD GATE, prompt quality. DO NOT TRIGGER when: user-facing docs, README, CHANGELOG, config files.
testing
JSON persistence, atomic writes, file locking, crash recovery, and state versioning patterns. Use when implementing stateful libraries or features requiring persistent state. TRIGGER when: state persistence, atomic write, file locking, crash recovery, checkpoint. DO NOT TRIGGER when: stateless utilities, pure functions, config reads, documentation.