Install
$ agentstack add skill-mickeyyaya-refactoring-skills-refactor-composing-methods ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Refactor: Composing Methods
Overview
These 9 techniques break down complex methods into smaller, readable pieces and eliminate duplication. Most frequently used refactoring techniques and the first defense against Bloater smells.
When to Use
- Method exceeds ~20 lines
- Comments explaining sections (each should be its own method)
- Same code block in multiple places
- Complex expressions hard to understand at a glance
- Temporary variables accumulate and obscure logic
Quick Reference
| Technique | Problem | Solution | |-----------|---------|----------| | Extract Method | Code fragment that can be grouped | Move into a named method | | Inline Method | Method body is as clear as its name | Replace calls with body | | Extract Variable | Complex expression hard to understand | Assign to descriptive variable | | Inline Temp | Temp assigned once from simple expression | Replace references with expression | | Replace Temp with Query | Temp holds reusable expression result | Extract to method, replace temp with call | | Split Temporary Variable | Temp assigned more than once (not loop var) | Separate variable per assignment | | Remove Assignments to Parameters | Method assigns to its parameters | Use a local variable instead | | Replace Method with Method Object | Tangled locals prevent extraction | Turn method into its own class | | Substitute Algorithm | Algorithm replaceable with clearer one | Swap the body |
Techniques in Detail
1. Extract Method
The most important refactoring. When in doubt, extract.
Before:
function printOwing(invoice: Invoice): void {
let outstanding = 0;
// print banner
console.log("***********************");
console.log("*** Customer Owes ***");
console.log("***********************");
// calculate outstanding
for (const order of invoice.orders) {
outstanding += order.amount;
}
// print details
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
After:
function printOwing(invoice: Invoice): void {
printBanner();
const outstanding = calculateOutstanding(invoice);
printDetails(invoice, outstanding);
}
function printBanner(): void {
console.log("***********************");
console.log("*** Customer Owes ***");
console.log("***********************");
}
function calculateOutstanding(invoice: Invoice): number {
return invoice.orders.reduce((sum, order) => sum + order.amount, 0);
}
function printDetails(invoice: Invoice, outstanding: number): void {
console.log(`name: ${invoice.customer}`);
console.log(`amount: ${outstanding}`);
}
Smells fixed: Long Method, Duplicate Code, Comments (excessive)
2. Inline Method
Reverse of Extract Method -- use when the body is already perfectly clear.
Before:
function getRating(driver: Driver): number {
return moreThanFiveLateDeliveries(driver) ? 2 : 1;
}
function moreThanFiveLateDeliveries(driver: Driver): boolean {
return driver.numberOfLateDeliveries > 5;
}
After:
function getRating(driver: Driver): number {
return driver.numberOfLateDeliveries > 5 ? 2 : 1;
}
3. Extract Variable
Before:
function price(order: Order): number {
return order.quantity * order.itemPrice -
Math.max(0, order.quantity - 500) * order.itemPrice * 0.05 +
Math.min(order.quantity * order.itemPrice * 0.1, 100);
}
After:
function price(order: Order): number {
const basePrice = order.quantity * order.itemPrice;
const quantityDiscount = Math.max(0, order.quantity - 500) * order.itemPrice * 0.05;
const shipping = Math.min(basePrice * 0.1, 100);
return basePrice - quantityDiscount + shipping;
}
4. Inline Temp / Replace Temp with Query
Inline Temp removes a trivial temp; Replace Temp with Query promotes a meaningful expression to a reusable method.
Replace Temp with Query:
// Before
const basePrice = order.quantity * order.itemPrice;
if (basePrice > 1000) return basePrice * 0.95;
return basePrice * 0.98;
// After
if (basePrice(order) > 1000) return basePrice(order) * 0.95;
return basePrice(order) * 0.98;
function basePrice(order: Order): number {
return order.quantity * order.itemPrice;
}
Rule: Trivial, used once -> Inline Temp. Meaningful and reusable -> Replace Temp with Query.
5. Split Temporary Variable
Before:
let temp = 2 * (height + width);
console.log(temp);
temp = height * width;
console.log(temp);
After:
const perimeter = 2 * (height + width);
console.log(perimeter);
const area = height * width;
console.log(area);
6. Remove Assignments to Parameters
Critical for immutability.
Before:
function discount(inputVal: number, quantity: number): number {
if (quantity > 50) inputVal -= 2; // mutating parameter!
return inputVal;
}
After:
function discount(inputVal: number, quantity: number): number {
const result = quantity > 50 ? inputVal - 2 : inputVal;
return result;
}
7. Replace Method with Method Object
Use when Extract Method is impossible due to tangled local variables.
Before:
class Order {
price(): number {
let primaryBasePrice: number;
let secondaryBasePrice: number;
let tertiaryBasePrice: number;
// ... long computation using all three variables intertwined ...
}
}
After:
class PriceCalculator {
constructor(
private readonly order: Order,
private primaryBasePrice: number = 0,
private secondaryBasePrice: number = 0,
private tertiaryBasePrice: number = 0
) {}
compute(): number {
this.calculatePrimary();
this.calculateSecondary();
this.calculateTertiary();
return this.primaryBasePrice + this.secondaryBasePrice + this.tertiaryBasePrice;
}
private calculatePrimary(): void { /* ... */ }
private calculateSecondary(): void { /* ... */ }
private calculateTertiary(): void { /* ... */ }
}
8. Substitute Algorithm
Before:
function foundPerson(people: string[]): string {
for (let i = 0; i candidates.has(p)) ?? "";
}
Decision Flowchart
digraph composing {
rankdir=TB;
start [label="Method too complex?" shape=diamond];
q1 [label="Can you identify\na code fragment\nto name?" shape=diamond];
q2 [label="Is a temp variable\nobscuring things?" shape=diamond];
q3 [label="Are local variables\ntoo tangled to\nextract methods?" shape=diamond];
q4 [label="Is a trivial method\njust adding\nindirection?" shape=diamond];
em [label="Extract Method" shape=box];
ev [label="Extract Variable" shape=box];
rtq [label="Replace Temp\nwith Query" shape=box];
rmmo [label="Replace Method\nwith Method Object" shape=box];
im [label="Inline Method" shape=box];
sa [label="Substitute Algorithm" shape=box];
start -> q1 [label="yes"];
start -> sa [label="whole algorithm\ncan be replaced"];
q1 -> em [label="yes"];
q1 -> q2 [label="no"];
q2 -> ev [label="expression complex\nbut single use"];
q2 -> rtq [label="temp reused\nor method-worthy"];
q2 -> q3 [label="no"];
q3 -> rmmo [label="yes"];
q3 -> q4 [label="no"];
q4 -> im [label="yes"];
}
Common Mistakes
| Mistake | Fix | |---------|-----| | Extracting methods that are too small (single-line getters) | Only extract when the name adds clarity beyond the code itself | | Naming extracted methods by implementation (calcStep1) | Name by intent (calculateDiscount) | | Extracting but creating Long Parameter Lists | If 4+ params needed, consider Extract Class or Parameter Object | | Inlining methods that provide useful abstraction | Only inline when the body is as clear as the name | | Forgetting to run tests after each extraction | Every refactoring step should be followed by a test run |
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: mickeyyaya
- Source: mickeyyaya/refactoring-skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.