بنقرة واحدة
refactoring
Refactoring patterns - improving code design without changing behavior
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Refactoring patterns - improving code design without changing behavior
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Read-only quality scan of components. Reports problems without making changes. Uses software-base + domain profile skills.
Read-only quality scan of components. Reports problems without making changes. Uses software-base + domain profile skills.
Internal phase: independent Codex review + targeted fixes. Not user-facing.
Find duplicated code and consolidate into shared utilities. Fixes all duplicates.
Reference templates for Codex evaluation. Used by build/improve orchestrators — not executed directly.
Hard-ass code review via Gemini. ALL issues must be fixed. No exceptions.
| name | refactoring |
| description | Refactoring patterns - improving code design without changing behavior |
Channel Martin Fowler, Michael Feathers, and Joshua Kerievsky.
"Refactoring is a disciplined technique for restructuring an existing body of code, altering its internal structure without changing its external behavior." — Fowler
The Two Hats:
Never wear both hats at once.
Smell-driven, not pattern-driven. Identify a smell first. Pick the minimum refactoring to fix it. Never scan for opportunities to introduce patterns.
| Smell | Refactoring |
|---|---|
| Long Method | Extract Method, Replace Temp with Query |
| Large Class | Extract Class, Extract Subclass |
| Long Parameter List | Introduce Parameter Object, Preserve Whole Object |
| Data Clumps | Extract Class, Introduce Parameter Object |
| Primitive Obsession | Replace Primitive with Object, Replace Type Code with Class |
| Smell | Refactoring |
|---|---|
| Switch Statements | Replace Conditional with Polymorphism |
| Parallel Inheritance | Move Method, Move Field |
| Lazy Class | Inline Class, Collapse Hierarchy |
| Speculative Generality | Collapse Hierarchy, Inline Class, Remove Parameter |
| Temporary Field | Extract Class, Introduce Null Object |
| Smell | Refactoring |
|---|---|
| Divergent Change | Extract Class |
| Shotgun Surgery | Move Method, Move Field, Inline Class |
| Parallel Inheritance | Move Method, Move Field |
| Smell | Refactoring |
|---|---|
| Comments (as deodorant) | Extract Method, Rename Method |
| Duplicate Code | Extract Method, Pull Up Method, Form Template Method |
| Dead Code | Remove Dead Code |
| Lazy Class | Inline Class |
| Speculative Generality | Collapse Hierarchy, Remove Parameter |
| Smell | Refactoring |
|---|---|
| Feature Envy | Move Method, Extract Method |
| Inappropriate Intimacy | Move Method, Move Field, Hide Delegate |
| Message Chains | Hide Delegate, Extract Method, Move Method |
| Middle Man | Remove Middle Man, Inline Method |
Apply patterns only when a smell justifies the destination. The smell is the trigger — the pattern is the minimum fix.
| Smell | Refactoring to Pattern | Justification Gate |
|---|---|---|
| Repeated conditional on type | Replace Conditional with Strategy | 3+ branches on same discriminator |
| Constructor with many combos | Replace Constructors with Builder | 4+ optional parameters, callers use different subsets |
| Notification spaghetti | Replace Hard-Coded Notifications with Observer | 3+ listeners or listeners change at runtime |
| Embedded algorithm varies | Replace Algorithm with Strategy | 2+ variants exist or are imminent |
| Composite structure with type checks | Replace Implicit Tree with Composite | Recursive structure with uniform operations |
| Accumulating decorations | Replace Layered Behavior with Decorator | Behaviors compose independently |
| State-dependent conditionals | Replace State-Altering Conditionals with State | 3+ states with transition logic spread across methods |
| Complex object creation | Replace Constructor with Factory Method | Creation varies by context or subtype |
When code has no tests, you cannot safely refactor. Use these techniques to get tests in place first.
Write tests that document current behavior, not intended behavior:
Characterization tests are not aspirational. They describe what the code does, not what it should do.
A seam is a place where you can alter behavior without editing the source. Three types:
| Seam Type | How It Works | When to Use |
|---|---|---|
| Object seam | Override method in subclass or pass different implementation | Class with injectable dependency |
| Link seam | Swap module/import at build or test time | Module-level dependency |
| Preprocessing seam | Conditional compilation or feature flags | Build-time variation |
Use these to get legacy code under test:
| Technique | What It Does |
|---|---|
| Extract Interface | Create interface from class to enable substitution |
| Parameterize Constructor | Pass dependency in instead of creating internally |
| Subclass and Override Method | Override the problematic method in a test subclass |
| Extract and Override Call | Move a hard-to-test call into its own method, override in test |
| Replace Global Reference with Getter | Wrap global access in a method you can override |
| Introduce Instance Delegator | Replace static method with instance method that delegates to it |
To refactor safely, you need tests. To add tests, you often need to refactor. Break the deadlock:
// Before
function printOwing() {
printBanner();
// print details
console.log("name: " + name);
console.log("amount: " + getOutstanding());
}
// After
function printOwing() {
printBanner();
printDetails(getOutstanding());
}
function printDetails(outstanding) {
console.log("name: " + name);
console.log("amount: " + outstanding);
}
// Before
function getSpeed() {
switch (this.type) {
case 'european': return getBaseSpeed();
case 'african': return getBaseSpeed() - getLoadFactor() * numberOfCoconuts;
case 'norwegian_blue': return isNailed ? 0 : getBaseSpeed();
}
}
// After
class European extends Bird {
getSpeed() { return this.getBaseSpeed(); }
}
class African extends Bird {
getSpeed() { return this.getBaseSpeed() - this.getLoadFactor() * this.numberOfCoconuts; }
}
class NorwegianBlue extends Bird {
getSpeed() { return this.isNailed ? 0 : this.getBaseSpeed(); }
}
// Before
function amountInvoiced(startDate, endDate) { ... }
function amountReceived(startDate, endDate) { ... }
function amountOverdue(startDate, endDate) { ... }
// After
class DateRange {
constructor(start, end) { this.start = start; this.end = end; }
}
function amountInvoiced(dateRange) { ... }
function amountReceived(dateRange) { ... }
function amountOverdue(dateRange) { ... }
// Before — related code is scattered
const price = order.basePrice;
sendConfirmation(order);
const discount = calculateDiscount(price);
// After — related code is together
const price = order.basePrice;
const discount = calculateDiscount(price);
sendConfirmation(order);
// Before
const result = [];
for (const person of people) {
if (person.age > 18) {
result.push(person.name);
}
}
// After
const result = people
.filter(p => p.age > 18)
.map(p => p.name);
// Before — parsing and calculation interleaved
function priceOrder(product, quantity, shippingMethod) {
const basePrice = product.basePrice * quantity;
const discount = Math.max(quantity - 500, 0) * product.basePrice * 0.05;
const shippingCost = calcShipping();
return basePrice - discount + shippingCost;
}
// After — separated into pricing phase and shipping phase
function priceOrder(product, quantity, shippingMethod) {
const priceData = calculatePricingData(product, quantity);
return applyShipping(priceData, shippingMethod);
}