Receber por email
← Voltar para o catálogo

refactoring-patterns

Use esta skill ao refatorar código para melhorar a legibilidade, reduzir a duplicação ou simplificar a lógica complexa. Ela é acionada em refatorações como extrair método, substituir condicional por polimorfismo e outras transformações sistemáticas de código que não alteram o comportamento.

185estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: MIT

Como adicionar

/plugin marketplace add AbsolutelySkilled/AbsolutelySkilled

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/refactoring-patterns-absolutelyskilled/svg)](https://www.skillteca.com.br/skills/refactoring-patterns-absolutelyskilled)

Skills relacionadas

Ver todas de Desenvolvimento →

Alerta por categoria

Receba novas skills de Desenvolvimento toda segunda

1 email curto, só com as skills novas de Desenvolvimento. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

When this skill is activated, always start your first response with the 🧢 emoji.

Refactoring Patterns

Refactoring is the discipline of restructuring existing code without changing its observable behavior. The goal is to make code easier to understand, cheaper to modify, and less likely to harbor bugs. Each refactoring move is a named, repeatable transformation - applying them in small, tested steps keeps the codebase safe. This skill gives an agent the vocabulary and judgment to recognize structural problems, choose the right refactoring move, and execute it correctly.

When to use this skill

Trigger this skill when the user:

  • Asks to extract a method, function, or block into a named helper
  • Has a long if/else chain or switch that grows with every new case
  • Wants to simplify a function with too many parameters
  • Asks to replace magic numbers or string literals with named constants
  • Wants to break apart a large class that does too many things
  • Has complex conditional logic that is hard to read at a glance
  • Asks for "systematic" code improvement without changing behavior
  • Wants to eliminate duplication across multiple files or classes

Do NOT trigger this skill for:

  • Performance optimization - refactoring targets readability, not speed
  • Architecture decisions that change system boundaries (use clean-architecture instead)

Key principles

  1. Small steps with tests - Apply one refactoring at a time and verify tests pass

after each step. A failing test means the refactoring changed behavior.

  1. Preserve observable behavior - Callers must not notice the change. Return

values, side effects, and thrown errors must remain identical.

  1. One refactor at a time - Don't mix Extract Method with Rename Variable in one

commit. Each commit should contain exactly one named refactoring move.

  1. Refactor before adding features - Fowler's rule: make the change easy, then

make the easy change. Restructure first, add the feature second.

  1. Code smells signal refactoring need - Smells like long functions, duplicated

code, and large parameter lists are symptoms pointing to the correct refactoring move. See references/code-smells.md for the full catalog.

Core concepts

Code smells taxonomy

Code smells are categories of structural problems, each suggesting specific moves:

| Smell | Signal | Primary Refactoring | |---|---|---| | Long method | Function over 20 lines, section comments | Extract Method | | Large class | Class does many unrelated things | Extract Class | | Long parameter list | 4+ parameters | Introduce Parameter Object | | Duplicated code | Same logic in 2+ places | Extract Method / Pull Up Method | | Switch statements | switch/if-else grows with each case | Replace Conditional with Polymorphism | | Primitive obsession | Strings/numbers standing in for domain concepts | Replace with Value Object | | Feature envy | Method uses another class's data more than its own | Move Method | | Temporary field | Instance variable only set in some code paths | Extract Class | | Data clumps | Same group of variables travel together | Introduce Parameter Object | | Speculative generality | Abstractions with no second use case | Collapse Hierarchy / Remove |

Refactoring safety net

Never refactor without tests. If tests don't exist, write characterization tests first - tests that capture the current behavior before you change anything. The test suite is the contract that proves the refactoring preserved behavior.

Common tasks

Extract method

Apply when a function contains a section that can be given a meaningful name.

Before:

function printOrderSummary(order: Order): void {
  // print header
  console.log("=".repeat(40));
  console.log(`Order #${order.id} - ${order.customer.name}`);
  console.log(`Date: ${order.createdAt.toLocaleDateString()}`);
  console.log("=".repeat(40));

  // print line items
  for (const item of order.items) {
    const lineTotal = item.price * item.quantity;
    console.log(`  ${item.name} x${item.quantity} @ $${item.price} = $${lineTotal}`);
  }

  // print totals
  const subtotal = order.items.reduce((sum, i) => sum + i.price * i.quantity, 0);
  const tax = subtotal * 0.08;
  console.log(`Subtotal: $${subtotal.toFixed(2)}`);
  console.log(`Tax (8%): $${tax.toFixed(2)}`);
  console.log(`Total:    $${(subtotal + tax).toFixed(2)}`);
}

After:

function printOrderSummary(order: Order): void {
  printOrderHeader(order);
  printLineItems(order.items);
  printOrderTotals(order.items);
}

function printOrderHeader(order: Order): void {
  console.log("=".repeat(40));
  console.log(`Order #${order.id} - ${order.customer.name}`);
  console.log(`Date: ${order.createdAt.toLocaleDateString()}`);
  console.log("=".repeat(40));
}

function printLineItems(items: OrderItem[]): void {
  for (const item of items) {
    const lineTotal = item.price * item.quantity;
    console.log(`  ${item.name} x${item.quantity} @ $${item.price} = $${lineTotal}`);
  }
}

function printOrderTotals(items: OrderItem[]): void {
  const subtotal = items.reduce((sum, i) => sum + i.price * i.quantity, 0);
  const tax = subtotal * 0.08;
  console.log(`Subtotal: $${subtotal.toFixed(2)}`);
  console.log(`Tax (8%): $${tax.toFixed(2)}`);
  console.log(`Total:    $${(subtotal + tax).toFixed(2)}`);
}

Replace conditional with polymorphism

Apply when a switch or if/else dispatches behavior by type, and new types keep getting added. Each new case is a modification to existing code - a violation of OCP.

Before:

function calculateShipping(order: Order): number {
  switch (order.shippingMethod) {
    case "standard": return order.weight * 0.5;
    case "express":  return order.weight * 1.5 + 5;
    case "overnight": return order.weight * 3.0 + 15;
    default: throw new Error(`Unknown shipping method: ${order.shippingMethod}`);
  }
}

After:

interface ShippingStrategy {
  calculate(order: Order): number;
}

class StandardShipping implements ShippingStrategy {
  calculate(order: Order): number { return order.weight * 0.5; }
}

class ExpressShipping implements ShippingStrategy {
  calculate(order: Order): number { return order.weight * 1.5 + 5; }
}

class OvernightShipping implements ShippingStrategy {
  calculate(order: Order): number { return order.weight * 3.0 + 15; }
}

// Adding a new method = new class only, no modification to existing code
function calculateShipping(order: Order, strategy: ShippingStrategy): number {
  return strategy.calculate(order);
}

Introduce parameter object

Apply when a function receives 4+ related parameters that travel together.

Before:

function createReport(
  title: string,
  startDate: Date,
  endDate: Date,
  authorId: string,
  format: "pdf" | "csv",
  includeCharts: boolean
): Report { ... }

After:

interface ReportOptions {
  title: string;
  dateRange: { start: Date; end: Date };
  authorId: string;
  format: "pdf" | "csv";
  includeCharts: boolean;
}

function createReport(options: ReportOptions): Report { ... }

Replace magic numbers with named constants

Apply when numeric or string literals appear in logic without explanation.

Before:

function isEligibleForDiscount(user: User): boolean {
  return user.totalPurchases > 500 && user.accountAgeDays > 90;
}

function calculateLateFee(daysLate: number): number {
  return daysLate * 2.5;
}

After:

const DISCOUNT_PURCHASE_THRESHOLD = 500;
const DISCOUNT_ACCOUNT_AGE_DAYS = 90;
const LATE_FEE_PER_DAY = 2.5;

function isEligibleForDiscount(user: User): boolean {
  return (
    user.totalPurchases > DISCOUNT_PURCHASE_THRESHOLD &&
    user.accountAgeDays > DISCOUNT_ACCOUNT_AGE_DAYS
  );
}

function calculateLateFee(daysLate: number): number {
  return daysLate * LATE_FEE_PER_DAY;
}

Decompose conditional

Apply wh

Compartilhar X LinkedIn