# Refactoring Patterns

> Refactoring teknikleri ve pattern'ları. REFACTORING, KOD İYİLEŞTİRME veya TEKNİK BORÇ temizleme işlerinde otomatik uygula.

- Skill: `erhankaraarslan/refactoring-patterns` (Agent Skill)
- Install (CLI): `npx skillmds@latest add erhankaraarslan/refactoring-patterns`
- Raw SKILL.md: https://api.skillmd.com/api/skills/erhankaraarslan/refactoring-patterns/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: erhankaraarslan (https://skillmd.com/u/erhankaraarslan)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/erhankaraarslan/refactoring-patterns

---


# Refactoring Patterns

## Temel Prensipler

1. **Küçük adımlar** - Her seferinde bir değişiklik
2. **Testler ile güvence** - Refactoring öncesi test yaz
3. **Commit sık** - Her başarılı refactoring'i commit et
4. **Davranışı koruma** - Fonksiyonalite değişmemeli

## Extract Method

```typescript
// ❌ Uzun fonksiyon
async function processOrder(order: Order) {
  // Validate
  if (!order.items.length) throw new Error('Empty order')
  if (!order.userId) throw new Error('No user')
  
  // Calculate totals
  let subtotal = 0
  for (const item of order.items) {
    subtotal += item.price * item.quantity
  }
  const tax = subtotal * 0.18
  const total = subtotal + tax
  
  // Save
  order.subtotal = subtotal
  order.tax = tax
  order.total = total
  await orderRepository.save(order)
  
  // Notify
  await emailService.send(order.userId, 'Order confirmed', { orderId: order.id })
}

// ✅ Refactored
async function processOrder(order: Order) {
  validateOrder(order)
  const totals = calculateTotals(order.items)
  await saveOrder(order, totals)
  await notifyUser(order)
}

function validateOrder(order: Order): void {
  if (!order.items.length) throw new ValidationError('Empty order')
  if (!order.userId) throw new ValidationError('No user')
}

function calculateTotals(items: OrderItem[]): OrderTotals {
  const subtotal = items.reduce((sum, item) => sum + item.price * item.quantity, 0)
  const tax = subtotal * 0.18
  return { subtotal, tax, total: subtotal + tax }
}
```

## Replace Conditional with Polymorphism

```typescript
// ❌ Switch/if-else chain
function calculateDiscount(customer: Customer): number {
  switch (customer.type) {
    case 'gold':
      return customer.total * 0.20
    case 'silver':
      return customer.total * 0.10
    case 'bronze':
      return customer.total * 0.05
    default:
      return 0
  }
}

// ✅ Strategy Pattern
interface DiscountStrategy {
  calculate(total: number): number
}

class GoldDiscount implements DiscountStrategy {
  calculate(total: number) { return total * 0.20 }
}

class SilverDiscount implements DiscountStrategy {
  calculate(total: number) { return total * 0.10 }
}

const discountStrategies: Record<string, DiscountStrategy> = {
  gold: new GoldDiscount(),
  silver: new SilverDiscount(),
  bronze: new BronzeDiscount(),
}

function calculateDiscount(customer: Customer): number {
  const strategy = discountStrategies[customer.type]
  return strategy?.calculate(customer.total) ?? 0
}
```

## Replace Magic Numbers/Strings

```typescript
// ❌ Magic values
if (user.role === 'admin') { ... }
if (order.status === 1) { ... }
const timeout = 30000

// ✅ Constants/Enums
enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  GUEST = 'guest',
}

enum OrderStatus {
  PENDING = 1,
  PROCESSING = 2,
  COMPLETED = 3,
}

const CONFIG = {
  TIMEOUT_MS: 30000,
  MAX_RETRIES: 3,
  PAGE_SIZE: 20,
} as const

if (user.role === UserRole.ADMIN) { ... }
if (order.status === OrderStatus.PENDING) { ... }
```

## Introduce Parameter Object

```typescript
// ❌ Çok parametre
function searchUsers(
  query: string,
  page: number,
  limit: number,
  sortBy: string,
  sortOrder: 'asc' | 'desc',
  filters: Record<string, unknown>
) { ... }

// ✅ Parameter object
interface SearchParams {
  query: string
  pagination: {
    page: number
    limit: number
  }
  sort?: {
    field: string
    order: 'asc' | 'desc'
  }
  filters?: Record<string, unknown>
}

function searchUsers(params: SearchParams) { ... }
```

## Replace Nested Conditionals with Guard Clauses

```typescript
// ❌ Deep nesting
function processPayment(payment: Payment) {
  if (payment) {
    if (payment.amount > 0) {
      if (payment.method) {
        if (isValidMethod(payment.method)) {
          // actual logic
          return processTransaction(payment)
        } else {
          throw new Error('Invalid method')
        }
      } else {
        throw new Error('No method')
      }
    } else {
      throw new Error('Invalid amount')
    }
  } else {
    throw new Error('No payment')
  }
}

// ✅ Guard clauses (Early return)
function processPayment(payment: Payment) {
  if (!payment) {
    throw new ValidationError('No payment')
  }
  if (payment.amount <= 0) {
    throw new ValidationError('Invalid amount')
  }
  if (!payment.method) {
    throw new ValidationError('No method')
  }
  if (!isValidMethod(payment.method)) {
    throw new ValidationError('Invalid method')
  }
  
  return processTransaction(payment)
}
```

## Extract Class

```typescript
// ❌ God class
class User {
  // User data
  id: string
  name: string
  email: string
  
  // Address (should be separate)
  street: string
  city: string
  country: string
  zipCode: string
  
  // Preferences (should be separate)
  theme: string
  language: string
  notifications: boolean
  
  getFullAddress() { ... }
  formatAddress() { ... }
  updatePreferences() { ... }
}

// ✅ Separated concerns
class User {
  id: string
  name: string
  email: string
  address: Address
  preferences: UserPreferences
}

class Address {
  street: string
  city: string
  country: string
  zipCode: string
  
  format(): string { ... }
}

class UserPreferences {
  theme: string
  language: string
  notifications: boolean
  
  update(changes: Partial<UserPreferences>): void { ... }
}
```

## Rename for Clarity

```typescript
// ❌ Belirsiz isimler
const d = new Date()
const temp = users.filter(u => u.a)
function calc(x, y) { return x + y }

// ✅ Açıklayıcı isimler
const currentDate = new Date()
const activeUsers = users.filter(user => user.isActive)
function calculateTotal(subtotal, tax) { return subtotal + tax }
```

## Remove Dead Code

```bash
# Kullanılmayan export'ları bul
npx ts-prune

# Kullanılmayan dependencies
npx depcheck

# ESLint no-unused-vars
npm run lint
```

## Refactoring Checklist

### Önce
- [ ] Mevcut testler geçiyor
- [ ] Değişiklik scopu belirlendi
- [ ] Commit yapılmış (clean state)

### Sırasında
- [ ] Küçük adımlarla ilerleniyor
- [ ] Her adımda testler çalıştırılıyor
- [ ] Davranış korunuyor

### Sonra
- [ ] Tüm testler geçiyor
- [ ] Code review yapıldı
- [ ] Dokümantasyon güncellendi

## Code Smells → Refactoring Mapping

| Smell | Refactoring |
|-------|-------------|
| Long Method | Extract Method |
| Large Class | Extract Class |
| Long Parameter List | Introduce Parameter Object |
| Switch Statements | Replace with Polymorphism |
| Nested Conditionals | Guard Clauses |
| Magic Numbers | Replace with Constants |
| Duplicate Code | Extract Method/Class |
| Feature Envy | Move Method |
| Data Clumps | Introduce Parameter Object |

