/refactoring-patterns
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
$ npx -y skills add akaszubski/autonomous-dev --skill refactoring-patterns --agent claude-codeHow it fires
How this skill gets triggered: by you, by Claude, or both.
- Fires itselfAuto-invocation. Claude auto-loads it when your prompt matches the work.
- You can call itInvoke it directly when you want it.
- Slash command
/refactoring-patterns
Context preview
The summary Claude sees to decide when to auto-load this skill.
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
SKILL.md
refactoring-patterns.SKILL.mdname: refactoring-patterns
description: "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."
allowed-tools: [Read, Grep, Glob]
Refactoring Patterns
Safe techniques for restructuring code without changing its behavior. Every refactoring follows: test green -> refactor -> test green.
Golden Rule
**Never refactor and change behavior in the same commit.** Refactoring = same behavior, different structure. Feature work = different behavior. Mixing them makes bugs untraceable.
Pre-Refactoring Checklist
Before any refactoring:
- [ ] Tests exist and pass for the code being refactored
- [ ] You can describe what the code does WITHOUT reading it line by line
- [ ] The refactoring has a clear motivation (not "it could be cleaner")
- [ ] The scope is bounded — you know exactly which files/functions change
Core Refactorings
1. Extract Function
**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.
2. Inline Function
**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.
3. Rename
**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**:
- Search for ALL usages before renaming (Grep across entire codebase)
- Update imports, tests, documentation, and config files
- If it's a public API, this is a BREAKING CHANGE — requires version bump
4. Move
**When**: A function/class is in the wrong module — it's more closely related to another module's concerns.
**Process**: 1. Grep for all imports of the function/class 2. Move to new location 3. Update all import statements 4. Add re-export from old location if it's a public API (temporary, with deprecation warning) 5. Run tests
5. Simplify Conditionals
**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.price6. Decompose Large Functions
**When**: A function is longer than ~30 lines or has multiple levels of abstraction.
**Process**: 1. Identify logical sections (often marked by comments or blank lines) 2. Extract each section into a named function 3. The parent function should read like a table of contents 4. Each extracted function should work at one level of abstraction
7. Replace Magic Values
# 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)Code Smells That Signal Refactoring
| 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 |
Refactoring Safety
Test-First Verification
# 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 chang
Read more
name: refactoring-patterns description: "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." allowed-tools: [Read, Grep, Glob]
Refactoring Patterns
Safe techniques for restructuring code without changing its behavior. Every refactoring follows: test green -> refactor -> test green.
Golden Rule
**Never refactor and change behavior in the same commit.** Refactoring = same behavior, different structure. Feature work = different behavior. Mixing them makes bugs untraceable.
Pre-Refactoring Checklist
Before any refactoring:
- [ ] Tests exist and pass for the code being refactored
- [ ] You can describe what the code does WITHOUT reading it line by line
- [ ] The refactoring has a clear motivation (not "it could be cleaner")
- [ ] The scope is bounded — you know exactly which files/functions change
Core Refactorings
1. Extract Function
**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.
2. Inline Function
**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.
3. Rename
**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**:
- Search for ALL usages before renaming (Grep across entire codebase)
- Update imports, tests, documentation, and config files
- If it's a public API, this is a BREAKING CHANGE — requires version bump
4. Move
**When**: A function/class is in the wrong module — it's more closely related to another module's concerns.
**Process**: 1. Grep for all imports of the function/class 2. Move to new location 3. Update all import statements 4. Add re-export from old location if it's a public API (temporary, with deprecation warning) 5. Run tests
5. Simplify Conditionals
**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.price6. Decompose Large Functions
**When**: A function is longer than ~30 lines or has multiple levels of abstraction.
**Process**: 1. Identify logical sections (often marked by comments or blank lines) 2. Extract each section into a named function 3. The parent function should read like a table of contents 4. Each extracted function should work at one level of abstraction
7. Replace Magic Values
# 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)Code Smells That Signal Refactoring
| 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 |
Refactoring Safety
Test-First Verification
# 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 chang
Showing the first part of this file.
A harness that wraps Claude Code with enforcement, specialist agents, and alignment gates to deliver consistent, production-grade software engineering outcomes.
Repo: akaszubski/autonomous-dev
Other skills on autonomous-dev.
- /api-design
REST API design best practices covering versioning, error handling, pagination, and OpenAPI documentation. Use when designing or implementing REST APIs or HTTP endpoints. TRIGGER when: API design, REST endpoint, HTTP route, OpenAPI, swagger, pagination. DO NOT TRIGGER when:
Open skill - /api-integration-patterns
Subprocess safety, GitHub CLI integration, retry logic, authentication, rate limiting, and timeout handling. Use when integrating external APIs or CLI tools. TRIGGER when: subprocess, gh cli, API call, retry logic, rate limiting, authentication. DO NOT TRIGGER when: internal
Open skill - /architecture-patterns
File-by-file architecture planning with ADR format, dependency ordering, and testability gates. Use when designing system architecture or creating ADRs. TRIGGER when: architecture plan, system design, ADR, file breakdown, component design. DO NOT TRIGGER when: simple config
Open skill - /code-review
10-point code review checklist covering correctness, tests, error handling, type hints, naming, security, and performance. Use when reviewing PRs or evaluating code quality. TRIGGER when: code review, PR review, review checklist, code quality check. DO NOT TRIGGER when: writing
Open skill - /content-allocation
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,
Open skill - /debugging-workflow
Systematic debugging methodology — reproduce, isolate, bisect, fix, verify. Use when diagnosing failures, tracing errors, or investigating unexpected behavior. TRIGGER when: debug, error, traceback, stack trace, bisect, breakpoint, failing test, unexpected behavior. DO NOT
Open skill

