Agent skill
refactoring-patterns
Martin Fowler's refactoring catalog with incremental change patterns and test-driven refactoring discipline
Install this agent skill to your Project
npx add-skill https://github.com/vineethsoma/agent-packages/tree/main/skills/refactoring-patterns
SKILL.md
Refactoring Patterns
Comprehensive refactoring guide based on Martin Fowler's "Refactoring: Improving the Design of Existing Code."
Core Principle
Small Change → Test → Commit → Repeat
Every refactoring must preserve existing behavior while improving code structure.
The Refactoring Cycle
-
Identify One Small, Isolated Change
- Extract a single method/function
- Rename one variable for clarity
- Eliminate one piece of duplication
- Simplify one conditional
- ONE change at a time (< 10 lines affected)
-
Make the Change
- Preserve existing behavior (no new features)
- Keep scope minimal
-
Run All Tests Immediately
- ✅ Green? → Proceed to step 4
- ❌ Red? → Revert immediately, try smaller change
-
Commit the Change
- Descriptive message: "Refactor: extract calculateDiscount method"
- Creates safety checkpoint for rollback
-
Repeat - Build on the previous improvement
Safety Rules (Non-Negotiable)
- NEVER refactor without passing tests
- NEVER combine refactoring with new features
- NEVER make "just one more small change" without testing
- ALWAYS commit after each successful step
- ALWAYS have a working state to revert to
- Maximum 15 minutes per refactoring step (break down if longer)
Red-Green-Refactor Discipline
RED → Write failing test for new feature
GREEN → Minimal code to pass test (can be ugly)
REFACTOR → Improve code in tiny increments (test after each)
→ ONLY when all tests are green
→ Commit after each improvement
Refactoring Catalog
Composing Methods
Extract Method - Create well-named method from code fragment
- Use when: Semantically dense code, different abstraction levels, replacing comments
- Don't use if: Cannot give a better name than current method
- Steps: Copy block → create method → test → replace with call → test → rename → test
Inline Method - Replace method call with method body
- Use when: Needless indirection, preparing for larger refactoring
- Don't use if: Subclass overrides the method
Inline Temp - Replace temp variable with direct method call
- Use when: Temp assigned from method call only once
- Often leads to: Replace Temp with Query
Replace Temp with Query - Extract expression to method, remove temp
- Use when: Expression used once, temp assigned once
- Benefit: Reduces method size, enables reuse
Introduce Explaining Variable - Put complex expression in temp with clear name
- Use when: Complex conditionals need clarity
- Alternative: Prefer Extract Method for recurring checks
Split Temporary Variable - Create separate temp for each assignment
- Use when: Temp reused for different purposes (not loop/accumulator)
- Identifies: Variables named temp, foo, x (poor names)
Remove Assignments to Parameters - Use temp instead of assigning to parameter
- Avoids: Confusion between pass-by-value and pass-by-reference
- Exception: Output parameters (use sparingly)
Replace Method with Method Object - Turn method into its own class
- Introduces: Command Pattern
- Use when: Long method with local variables preventing Extract Method
Substitute Algorithm - Replace algorithm with clearer/simpler one
- Select based on: Performance, succinctness, expressiveness
- Must have tests before substituting
Moving Features Between Objects
Move Method - Move method to class that uses it most
- Use when: Method uses more features of another class
Move Field - Move field to class that uses it most
Extract Class - Create new class for subset of responsibilities
- Use when: Class doing work of two classes
Inline Class - Merge class into another when it's no longer pulling weight
Hide Delegate - Create method to hide delegation
- Encapsulates: Knowledge of other objects
Remove Middle Man - Call delegate directly when middle man is thin wrapper
Organizing Data
Replace Magic Number with Symbolic Constant
- Turn literal numbers into named constants
Encapsulate Field - Make field private, provide accessors
Encapsulate Collection - Return read-only view, provide add/remove methods
Replace Type Code with Class - Replace integer codes with class
- Alternative: Use enums or type-safe enums
Replace Type Code with Subclasses - Turn codes into inheritance
- Use when: Behavior varies by type code
Replace Type Code with State/Strategy - Use State/Strategy pattern
- Use when: Type code changes during lifetime, or can't use subclasses
Simplifying Conditional Expressions
Decompose Conditional - Extract condition and branches into methods
- Example:
if (date.before(SUMMER_START))→if (notSummer(date))
Consolidate Conditional Expression - Combine conditions with same result
- Use logical operators to unify checks
Consolidate Duplicate Conditional Fragments - Move identical code outside conditional
Remove Control Flag - Use break, continue, or return instead of flag variable
Replace Nested Conditional with Guard Clauses - Use early returns
- Example:
if (!valid) return; // rest of method
Replace Conditional with Polymorphism - Move conditional to subclass methods
Introduce Null Object - Replace null checks with null object
- Null object implements interface with do-nothing methods
Introduce Assertion - Make assumptions explicit
- Example:
assert(balance >= 0, "Balance cannot be negative")
Making Method Calls Simpler
Rename Method - Make name explain purpose
Add Parameter / Remove Parameter - Adjust parameter list
Separate Query from Modifier - Split methods that return value and change state
Parameterize Method - Use parameter instead of multiple similar methods
Replace Parameter with Explicit Methods - Create separate method for each value
Preserve Whole Object - Pass entire object instead of multiple values
Replace Parameter with Method - Remove parameter by calling method
Introduce Parameter Object - Group parameters into object
Remove Setting Method - Make field immutable after construction
Hide Method - Make method private if not used outside class
Replace Constructor with Factory Method - Return polymorphic type
Replace Error Code with Exception - Throw exception instead of returning code
Replace Exception with Test - Check condition first to avoid exception
Dealing with Generalization
Pull Up Field / Pull Up Method - Move to superclass when identical in subclasses
Push Down Field / Push Down Method - Move to subclass when used only there
Extract Subclass - Create subclass for features used in some instances
Extract Superclass - Create superclass for common features
Extract Interface - Create interface when classes share subset of features
Collapse Hierarchy - Merge subclass into superclass when too similar
Form Template Method - Move invariant steps to superclass, override variants
Replace Inheritance with Delegation - Use composition when subclass uses only part of superclass
Replace Delegation with Inheritance - Make delegate a subclass if using all features
Example: Incremental Application
Bad Approach (risky - batched changes):
// Extract 3 methods + rename 5 variables + reorganize imports
// Run tests → many failures → hard to debug
Good Approach (safe - incremental):
1. Extract calculateSubtotal() → test → commit
2. Extract calculateTax() → test → commit
3. Extract calculateTotal() → test → commit
4. Rename 'amt' to 'amount' → test → commit
5. Rename 'calc' to 'calculate' → test → commit
References
Based on Martin Fowler's "Refactoring: Improving the Design of Existing Code"
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
mcp-specialist
MCP server lifecycle management, catalog maintenance, and agent tool provisioning Use when working with management, provision, server, specialist.
agent-package-manager
Agent for creating and managing APM agent packages with kebab-case naming enforcement Use when working with agent, compliance, create, lifecycle, manager.
docker-compose
Docker Compose management for orchestrating MCP servers and multi-container applications. Use when deploying MCP servers, managing container lifecycles, or configuring service dependencies.
retrospective-workflow
Systematic post-story retrospective process with automated metrics gathering, structured feedback collection, and Agent Package Manager handoff generation
vector-search
Semantic search using vector embeddings and similarity metrics. Apply when implementing search with embeddings (OpenAI, Sentence Transformers) or distance-based ranking. Covers cosine similarity, Euclidean distance, dot product, and threshold selection.
secure-development
Security best practices for production applications including PII protection, input validation, SQL injection prevention, XSS mitigation, and secure logging. Apply when handling user data, authentication, or external inputs.
Didn't find tool you were looking for?