refactor

star 0

Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than rewriting; use for gradual improvements.

jahales By jahales schedule Updated 2/6/2026

name: refactor description: 'Surgical code refactoring to improve maintainability without changing behavior. Covers extracting functions, renaming variables, breaking down god functions, improving type safety, eliminating code smells, and applying design patterns. Less drastic than rewriting; use for gradual improvements.' source: github/awesome-copilot source_file: skills/refactor/SKILL.md source_sha: a5b3af024f7ea7ea4758b3e3cda07c51fa547337 adopted: 2026-01-29 customizations: Condensed from 16KB original; focused on TypeScript patterns license: MIT

Refactor Skill

Overview

Improve code structure and readability without changing external behavior. Refactoring is gradual evolution, not revolution. Use this for improving existing code, not rewriting from scratch.

When to Use

  • Code is hard to understand or maintain
  • Functions/classes are too large
  • Code smells need addressing
  • Adding features is difficult due to code structure
  • User asks "clean up this code", "refactor this", "improve this"

Refactoring Principles

The Golden Rules

  1. Behavior is preserved — Refactoring doesn't change what the code does, only how
  2. Small steps — Make tiny changes, test after each
  3. Version control is your friend — Commit before and after each safe state
  4. Tests are essential — Without tests, you're not refactoring, you're editing
  5. One thing at a time — Don't mix refactoring with feature changes

When NOT to Refactor

  • Code that works and won't change again
  • Critical production code without tests (add tests first)
  • When you're under a tight deadline
  • "Just because" — need a clear purpose

Common Code Smells & Fixes

1. Long Method/Function

// BAD: 200-line function that does everything
async function processOrder(orderId: string) {
  // 50 lines: fetch order
  // 30 lines: validate order
  // 40 lines: calculate pricing
  // etc.
}

// GOOD: Broken into focused functions
async function processOrder(orderId: string) {
  const order = await fetchOrder(orderId);
  validateOrder(order);
  const pricing = calculatePricing(order);
  await updateInventory(order);
  return { order, pricing };
}

2. Duplicated Code

// BAD: Same logic in multiple places
function calculateUserDiscount(user: User) {
  if (user.membership === 'gold') return user.total * 0.2;
  if (user.membership === 'silver') return user.total * 0.1;
  return 0;
}

// GOOD: Extract common logic
const DISCOUNT_RATES: Record<string, number> = { gold: 0.2, silver: 0.1 };

function getMembershipDiscountRate(membership: string): number {
  return DISCOUNT_RATES[membership] ?? 0;
}

3. Large Class/Module

// BAD: God object
class UserManager {
  createUser() { }
  updateUser() { }
  sendEmail() { }
  generateReport() { }
  handlePayment() { }
  // 50 more methods...
}

// GOOD: Single responsibility per class
class UserService { create() { } update() { } }
class EmailService { send() { } }
class ReportService { generate() { } }

4. Long Parameter List

// BAD: Too many parameters
function createUser(email: string, password: string, name: string, age: number, address: string) { }

// GOOD: Group related parameters
interface CreateUserData {
  email: string;
  password: string;
  name: string;
  age?: number;
  address?: Address;
}

function createUser(data: CreateUserData) { }

5. Magic Numbers/Strings

// BAD: Unexplained values
if (user.status === 2) { }
const discount = total * 0.15;
setTimeout(callback, 86400000);

// GOOD: Named constants
const UserStatus = { ACTIVE: 1, INACTIVE: 2, SUSPENDED: 3 } as const;
const DISCOUNT_RATES = { STANDARD: 0.1, PREMIUM: 0.15 } as const;
const ONE_DAY_MS = 24 * 60 * 60 * 1000;

if (user.status === UserStatus.INACTIVE) { }

6. Nested Conditionals

// BAD: Arrow code
function process(order: Order) {
  if (order) {
    if (order.user) {
      if (order.user.isActive) {
        if (order.total > 0) {
          return processOrder(order);
        }
      }
    }
  }
  return { error: 'Invalid' };
}

// GOOD: Guard clauses / early returns
function process(order: Order) {
  if (!order) return { error: 'No order' };
  if (!order.user) return { error: 'No user' };
  if (!order.user.isActive) return { error: 'User inactive' };
  if (order.total <= 0) return { error: 'Invalid total' };
  return processOrder(order);
}

7. Dead Code

// BAD: Unused code lingers
function oldImplementation() { /* ... */ }
const DEPRECATED_VALUE = 5;
// Commented out code blocks

// GOOD: Delete it
// If you need it again, git history has it

Extract Method Pattern

Before

function printReport(users: User[]) {
  console.log('USER REPORT');
  console.log('============');
  console.log(`Total: ${users.length}`);
  const active = users.filter(u => u.isActive);
  active.forEach(u => console.log(`- ${u.name}`));
  console.log(`Active: ${active.length}`);
  // ... more inline code
}

After

function printReport(users: User[]) {
  printHeader('USER REPORT');
  console.log(`Total: ${users.length}\n`);
  printUserSection('ACTIVE USERS', users.filter(u => u.isActive));
  printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));
}

function printHeader(title: string) {
  console.log(title);
  console.log('='.repeat(title.length));
}

function printUserSection(title: string, users: User[]) {
  console.log(title);
  users.forEach(u => console.log(`- ${u.name}`));
  console.log(`Count: ${users.length}\n`);
}

Type Safety Improvements

// Before: No types
function calculateDiscount(user, total, membership) {
  if (membership === 'gold') return total * 0.2;
  return total * 0.1;
}

// After: Full type safety
type Membership = 'bronze' | 'silver' | 'gold';

interface DiscountResult {
  original: number;
  discount: number;
  final: number;
}

function calculateDiscount(user: User, total: number): DiscountResult {
  const rate = user.membership === 'gold' ? 0.2 : 0.1;
  const discount = total * rate;
  return { original: total, discount, final: total - discount };
}

Strategy Pattern for Conditionals

// Before: Conditional logic
function calculateShipping(order: Order, method: string) {
  if (method === 'standard') return order.total > 50 ? 0 : 5.99;
  if (method === 'express') return order.total > 100 ? 9.99 : 14.99;
  if (method === 'overnight') return 29.99;
  return 0;
}

// After: Strategy pattern
interface ShippingStrategy {
  calculate(order: Order): number;
}

const shippingStrategies: Record<string, ShippingStrategy> = {
  standard: { calculate: (o) => o.total > 50 ? 0 : 5.99 },
  express: { calculate: (o) => o.total > 100 ? 9.99 : 14.99 },
  overnight: { calculate: () => 29.99 },
};

function calculateShipping(order: Order, method: string): number {
  return shippingStrategies[method]?.calculate(order) ?? 0;
}

Refactoring Checklist

  • Tests exist and pass before starting
  • Making one change at a time
  • Running tests after each change
  • Committing after each successful refactoring
  • Not mixing refactoring with feature changes
  • Code duplication eliminated
  • Names are clear and intention-revealing
  • Functions have single responsibility
  • No magic numbers or strings
  • Nested conditionals flattened
  • Dead code removed

References

  • Refactoring (Martin Fowler)
  • Clean Code (Robert C. Martin)
  • github/awesome-copilot refactor skill
Install via CLI
npx skills add https://github.com/jahales/etude-story --skill refactor
Repository Details
star Stars 0
call_split Forks 0
navigation Branch main
article Path SKILL.md
More from Creator