code-refactoring

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Code Refactoring

代码重构

When to use this skill

何时使用该技能

  • 코드 리뷰: 복잡하거나 중복된 코드 발견
  • 새 기능 추가 전: 기존 코드 정리
  • 버그 수정 후: 근본 원인 제거
  • 기술 부채 해소: 정기적인 리팩토링
  • 代码评审:发现复杂或重复代码时
  • 添加新功能前:整理现有代码
  • 修复Bug后:消除问题根源
  • 解决技术债务:定期进行重构

Instructions

操作步骤

Step 1: Extract Method (메서드 추출)

步骤1:提取方法(Extract Method)

Before (긴 함수):
typescript
function processOrder(order: Order) {
  // 검증
  if (!order.items || order.items.length === 0) {
    throw new Error('Order must have items');
  }
  if (!order.customerId) {
    throw new Error('Order must have customer');
  }

  // 가격 계산
  let total = 0;
  for (const item of order.items) {
    total += item.price * item.quantity;
  }
  const tax = total * 0.1;
  const shipping = total > 100 ? 0 : 10;
  const finalTotal = total + tax + shipping;

  // 재고 확인
  for (const item of order.items) {
    const product = await db.product.findUnique({ where: { id: item.productId } });
    if (product.stock < item.quantity) {
      throw new Error(`Insufficient stock for ${product.name}`);
    }
  }

  // 주문 생성
  const newOrder = await db.order.create({
    data: {
      customerId: order.customerId,
      items: order.items,
      total: finalTotal,
      status: 'pending'
    }
  });

  return newOrder;
}
After (메서드 추출):
typescript
async function processOrder(order: Order) {
  validateOrder(order);
  const total = calculateTotal(order);
  await checkInventory(order);
  return await createOrder(order, total);
}

function validateOrder(order: Order) {
  if (!order.items || order.items.length === 0) {
    throw new Error('Order must have items');
  }
  if (!order.customerId) {
    throw new Error('Order must have customer');
  }
}

function calculateTotal(order: Order): number {
  const subtotal = order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  const tax = subtotal * 0.1;
  const shipping = subtotal > 100 ? 0 : 10;
  return subtotal + tax + shipping;
}

async function checkInventory(order: Order) {
  for (const item of order.items) {
    const product = await db.product.findUnique({ where: { id: item.productId } });
    if (product.stock < item.quantity) {
      throw new Error(`Insufficient stock for ${product.name}`);
    }
  }
}

async function createOrder(order: Order, total: number) {
  return await db.order.create({
    data: {
      customerId: order.customerId,
      items: order.items,
      total,
      status: 'pending'
    }
  });
}
重构前(冗长函数):
typescript
function processOrder(order: Order) {
  // 검증
  if (!order.items || order.items.length === 0) {
    throw new Error('Order must have items');
  }
  if (!order.customerId) {
    throw new Error('Order must have customer');
  }

  // 가격 계산
  let total = 0;
  for (const item of order.items) {
    total += item.price * item.quantity;
  }
  const tax = total * 0.1;
  const shipping = total > 100 ? 0 : 10;
  const finalTotal = total + tax + shipping;

  // 재고 확인
  for (const item of order.items) {
    const product = await db.product.findUnique({ where: { id: item.productId } });
    if (product.stock < item.quantity) {
      throw new Error(`Insufficient stock for ${product.name}`);
    }
  }

  // 주문 생성
  const newOrder = await db.order.create({
    data: {
      customerId: order.customerId,
      items: order.items,
      total: finalTotal,
      status: 'pending'
    }
  });

  return newOrder;
}
重构后(提取方法):
typescript
async function processOrder(order: Order) {
  validateOrder(order);
  const total = calculateTotal(order);
  await checkInventory(order);
  return await createOrder(order, total);
}

function validateOrder(order: Order) {
  if (!order.items || order.items.length === 0) {
    throw new Error('Order must have items');
  }
  if (!order.customerId) {
    throw new Error('Order must have customer');
  }
}

function calculateTotal(order: Order): number {
  const subtotal = order.items.reduce((sum, item) => sum + item.price * item.quantity, 0);
  const tax = subtotal * 0.1;
  const shipping = subtotal > 100 ? 0 : 10;
  return subtotal + tax + shipping;
}

async function checkInventory(order: Order) {
  for (const item of order.items) {
    const product = await db.product.findUnique({ where: { id: item.productId } });
    if (product.stock < item.quantity) {
      throw new Error(`Insufficient stock for ${product.name}`);
    }
  }
}

async function createOrder(order: Order, total: number) {
  return await db.order.create({
    data: {
      customerId: order.customerId,
      items: order.items,
      total,
      status: 'pending'
    }
  });
}

Step 2: Remove Duplication (중복 제거)

步骤2:消除重复(Remove Duplication)

Before (중복):
typescript
async function getActiveUsers() {
  return await db.user.findMany({
    where: { status: 'active', deletedAt: null },
    select: { id: true, name: true, email: true }
  });
}

async function getActivePremiumUsers() {
  return await db.user.findMany({
    where: { status: 'active', deletedAt: null, plan: 'premium' },
    select: { id: true, name: true, email: true }
  });
}
After (공통 로직 추출):
typescript
type UserFilter = {
  plan?: string;
};

async function getActiveUsers(filter: UserFilter = {}) {
  return await db.user.findMany({
    where: {
      status: 'active',
      deletedAt: null,
      ...filter
    },
    select: { id: true, name: true, email: true }
  });
}

// 사용
const allActiveUsers = await getActiveUsers();
const premiumUsers = await getActiveUsers({ plan: 'premium' });
重构前(重复代码):
typescript
async function getActiveUsers() {
  return await db.user.findMany({
    where: { status: 'active', deletedAt: null },
    select: { id: true, name: true, email: true }
  });
}

async function getActivePremiumUsers() {
  return await db.user.findMany({
    where: { status: 'active', deletedAt: null, plan: 'premium' },
    select: { id: true, name: true, email: true }
  });
}
重构后(提取公共逻辑):
typescript
type UserFilter = {
  plan?: string;
};

async function getActiveUsers(filter: UserFilter = {}) {
  return await db.user.findMany({
    where: {
      status: 'active',
      deletedAt: null,
      ...filter
    },
    select: { id: true, name: true, email: true }
  });
}

// 使用示例
const allActiveUsers = await getActiveUsers();
const premiumUsers = await getActiveUsers({ plan: 'premium' });

Step 3: Replace Conditional with Polymorphism

步骤3:用多态替代条件语句(Replace Conditional with Polymorphism)

Before (긴 if-else):
typescript
class PaymentProcessor {
  process(payment: Payment) {
    if (payment.method === 'credit_card') {
      // 신용카드 처리
      const cardToken = this.tokenizeCard(payment.card);
      const charge = this.chargeCreditCard(cardToken, payment.amount);
      return charge;
    } else if (payment.method === 'paypal') {
      // PayPal 처리
      const paypalOrder = this.createPayPalOrder(payment.amount);
      const approval = this.getPayPalApproval(paypalOrder);
      return approval;
    } else if (payment.method === 'bank_transfer') {
      // 은행 이체 처리
      const transfer = this.initiateBankTransfer(payment.account, payment.amount);
      return transfer;
    }
  }
}
After (다형성):
typescript
interface PaymentMethod {
  process(payment: Payment): Promise<PaymentResult>;
}

class CreditCardPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    const cardToken = await this.tokenizeCard(payment.card);
    return await this.chargeCreditCard(cardToken, payment.amount);
  }
}

class PayPalPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    const order = await this.createPayPalOrder(payment.amount);
    return await this.getPayPalApproval(order);
  }
}

class BankTransferPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    return await this.initiateBankTransfer(payment.account, payment.amount);
  }
}

class PaymentProcessor {
  private methods: Map<string, PaymentMethod> = new Map([
    ['credit_card', new CreditCardPayment()],
    ['paypal', new PayPalPayment()],
    ['bank_transfer', new BankTransferPayment()]
  ]);

  async process(payment: Payment): Promise<PaymentResult> {
    const method = this.methods.get(payment.method);
    if (!method) {
      throw new Error(`Unknown payment method: ${payment.method}`);
    }
    return await method.process(payment);
  }
}
重构前(冗长的if-else):
typescript
class PaymentProcessor {
  process(payment: Payment) {
    if (payment.method === 'credit_card') {
      // 신용카드 처리
      const cardToken = this.tokenizeCard(payment.card);
      const charge = this.chargeCreditCard(cardToken, payment.amount);
      return charge;
    } else if (payment.method === 'paypal') {
      // PayPal 처리
      const paypalOrder = this.createPayPalOrder(payment.amount);
      const approval = this.getPayPalApproval(paypalOrder);
      return approval;
    } else if (payment.method === 'bank_transfer') {
      // 은행 이체 처리
      const transfer = this.initiateBankTransfer(payment.account, payment.amount);
      return transfer;
    }
  }
}
重构后(多态):
typescript
interface PaymentMethod {
  process(payment: Payment): Promise<PaymentResult>;
}

class CreditCardPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    const cardToken = await this.tokenizeCard(payment.card);
    return await this.chargeCreditCard(cardToken, payment.amount);
  }
}

class PayPalPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    const order = await this.createPayPalOrder(payment.amount);
    return await this.getPayPalApproval(order);
  }
}

class BankTransferPayment implements PaymentMethod {
  async process(payment: Payment): Promise<PaymentResult> {
    return await this.initiateBankTransfer(payment.account, payment.amount);
  }
}

class PaymentProcessor {
  private methods: Map<string, PaymentMethod> = new Map([
    ['credit_card', new CreditCardPayment()],
    ['paypal', new PayPalPayment()],
    ['bank_transfer', new BankTransferPayment()]
  ]);

  async process(payment: Payment): Promise<PaymentResult> {
    const method = this.methods.get(payment.method);
    if (!method) {
      throw new Error(`Unknown payment method: ${payment.method}`);
    }
    return await method.process(payment);
  }
}

Step 4: Introduce Parameter Object

步骤4:引入参数对象(Introduce Parameter Object)

Before (많은 파라미터):
typescript
function createUser(
  name: string,
  email: string,
  password: string,
  age: number,
  country: string,
  city: string,
  postalCode: string,
  phoneNumber: string
) {
  // ...
}
After (객체로 그룹화):
typescript
interface UserProfile {
  name: string;
  email: string;
  password: string;
  age: number;
}

interface Address {
  country: string;
  city: string;
  postalCode: string;
}

interface CreateUserParams {
  profile: UserProfile;
  address: Address;
  phoneNumber: string;
}

function createUser(params: CreateUserParams) {
  const { profile, address, phoneNumber } = params;
  // ...
}

// 사용
createUser({
  profile: { name: 'John', email: 'john@example.com', password: 'xxx', age: 30 },
  address: { country: 'US', city: 'NYC', postalCode: '10001' },
  phoneNumber: '+1234567890'
});
重构前(过多参数):
typescript
function createUser(
  name: string,
  email: string,
  password: string,
  age: number,
  country: string,
  city: string,
  postalCode: string,
  phoneNumber: string
) {
  // ...
}
重构后(用对象分组):
typescript
interface UserProfile {
  name: string;
  email: string;
  password: string;
  age: number;
}

interface Address {
  country: string;
  city: string;
  postalCode: string;
}

interface CreateUserParams {
  profile: UserProfile;
  address: Address;
  phoneNumber: string;
}

function createUser(params: CreateUserParams) {
  const { profile, address, phoneNumber } = params;
  // ...
}

// 使用示例
createUser({
  profile: { name: 'John', email: 'john@example.com', password: 'xxx', age: 30 },
  address: { country: 'US', city: 'NYC', postalCode: '10001' },
  phoneNumber: '+1234567890'
});

Step 5: SOLID 원칙 적용

步骤5:应用SOLID原则

Single Responsibility (단일 책임):
typescript
// ❌ 나쁜 예: 여러 책임
class User {
  constructor(public name: string, public email: string) {}

  save() {
    // DB 저장
  }

  sendEmail(subject: string, body: string) {
    // 이메일 발송
  }

  generateReport() {
    // 리포트 생성
  }
}

// ✅ 좋은 예: 책임 분리
class User {
  constructor(public name: string, public email: string) {}
}

class UserRepository {
  save(user: User) {
    // DB 저장
  }
}

class EmailService {
  send(to: string, subject: string, body: string) {
    // 이메일 발송
  }
}

class UserReportGenerator {
  generate(user: User) {
    // 리포트 생성
  }
}
单一职责原则(Single Responsibility):
typescript
// ❌ 反面示例:承担多个职责
class User {
  constructor(public name: string, public email: string) {}

  save() {
    // 数据库保存逻辑
  }

  sendEmail(subject: string, body: string) {
    // 发送邮件逻辑
  }

  generateReport() {
    // 生成报告逻辑
  }
}

// ✅ 正面示例:职责分离
class User {
  constructor(public name: string, public email: string) {}
}

class UserRepository {
  save(user: User) {
    // 数据库保存逻辑
  }
}

class EmailService {
  send(to: string, subject: string, body: string) {
    // 发送邮件逻辑
  }
}

class UserReportGenerator {
  generate(user: User) {
    // 生成报告逻辑
  }
}

Output format

输出格式

리팩토링 체크리스트

重构检查表

markdown
- [ ] 함수는 한 가지 일만 한다 (SRP)
- [ ] 함수 이름이 하는 일을 명확히 설명한다
- [ ] 함수는 20줄 이하 (가이드라인)
- [ ] 매개변수는 3개 이하
- [ ] 중복 코드 없음 (DRY)
- [ ] if 중첩은 2단계 이하
- [ ] 매직 넘버 없음 (상수로 추출)
- [ ] 주석 없이도 이해 가능 (자기 문서화)
markdown
- [ ] 函数只做一件事(SRP)
- [ ] 函数名称清晰描述其功能
- [ ] 函数代码不超过20行(参考标准)
- [ ] 参数数量不超过3个
- [ ] 无重复代码(DRY)
- [ ] if嵌套不超过2层
- [ ] 无魔法数字(已提取为常量)
- [ ] 无需注释即可理解(自文档化)

Constraints

约束规则

필수 규칙 (MUST)

必须遵守的规则(MUST)

  1. 테스트 먼저: 리팩토링 전 테스트 작성
  2. 작은 단계: 한 번에 하나씩 변경
  3. 동작 보존: 기능 변경 없음
  1. 先写测试:重构前编写测试用例
  2. 小步迭代:每次只做一处变更
  3. 保留行为:不改变原有功能

금지 사항 (MUST NOT)

禁止事项(MUST NOT)

  1. 동시에 여러 작업: 리팩토링 + 기능 추가 동시 금지
  2. 테스트 없이 리팩토링: 회귀 위험
  1. 同时做多件事:禁止同时进行重构和添加新功能
  2. 无测试重构:避免回归风险

Best practices

最佳实践

  1. Boy Scout Rule: 코드를 발견했을 때보다 깨끗하게
  2. 리팩토링 타이밍: Red-Green-Refactor (TDD)
  3. 점진적 개선: 완벽보다 꾸준히
  4. 행동 보존: 리팩토링은 기능 변경 없음
  5. 작은 커밋: 포커스된 단위로 커밋

  1. 童子军规则(Boy Scout Rule):离开时让代码比你发现时更干净
  2. 重构时机:遵循红-绿-重构(Red-Green-Refactor,TDD流程)
  3. 渐进式改进:追求持续优化而非一蹴而就
  4. 保留行为:重构不改变原有功能
  5. 小粒度提交:按聚焦的功能单元提交代码

Behavior Validation (Code Simplifier Integration)

行为验证(代码简化器集成)

Step A: Understand Current Behavior

步骤A:理解当前行为

리팩토링 전 현재 동작 완전히 이해:
markdown
undefined
重构前需完全理解代码当前行为:
markdown
undefined

Behavior Analysis

行为分析

Inputs

输入

  • [입력 파라미터 목록]
  • [타입 및 제약사항]
  • [输入参数列表]
  • [类型及约束条件]

Outputs

输出

  • [반환값]
  • [부수 효과 (side effects)]
  • [返回值]
  • [副作用(side effects)]

Invariants

不变量

  • [항상 참이어야 하는 조건들]
  • [경계 조건 (edge cases)]
  • [必须始终成立的条件]
  • [边界情况(edge cases)]

Dependencies

依赖项

  • [외부 의존성]
  • [상태 의존성]
undefined
  • [外部依赖]
  • [状态依赖]
undefined

Step B: Validate After Refactoring

步骤B:重构后验证

bash
undefined
bash
undefined

1. 테스트 실행

1. 运行测试

npm test -- --coverage
npm test -- --coverage

2. 타입 체크

2. 类型检查

npx tsc --noEmit
npx tsc --noEmit

3. 린트 확인

3. 代码检查

npm run lint
npm run lint

4. 이전 동작과 비교 (스냅샷 테스트)

4. 与原有行为对比(快照测试)

npm test -- --updateSnapshot
undefined
npm test -- --updateSnapshot
undefined

Step C: Document Changes

步骤C:记录变更

markdown
undefined
markdown
undefined

Refactoring Summary

重构总结

Changes Made

已做变更

  1. [变更1]:[变更原因]
  2. [变更2]:[变更原因]

Behavior Preserved

保留的行为

  • 동일한 입력 → 동일한 출력
  • 부수 효과 동일
  • 에러 처리 동일
  • 相同输入 → 相同输出
  • 副作用一致
  • 错误处理逻辑一致

Risks & Follow-ups

风险与后续工作

  • [잠재적 위험]
  • [후속 작업]
  • [潜在风险]
  • [后续任务]

Test Status

测试状态

  • Unit tests: passing
  • Integration tests: passing
  • E2E tests: passing

---
  • 单元测试:通过
  • 集成测试:通过
  • 端到端测试:通过

---

Troubleshooting

问题排查

Issue: Tests fail after refactor

问题:重构后测试失败

Cause: 동작 변경이 발생함 Solution: 되돌리고 변경을 격리하여 재시도
原因:代码行为发生了变更 解决方案:回滚变更,拆分后重新尝试

Issue: Code still complex

问题:代码仍复杂

Cause: 하나의 함수에 여러 책임 혼합 Solution: 명확한 경계로 더 작은 단위 추출
原因:单个函数承担了多个职责 解决方案:按清晰的边界拆分为更小的单元

Issue: Performance regression

问题:性能下降

Cause: 비효율적인 추상화 도입 Solution: 프로파일링 후 핫 패스 최적화

原因:引入了低效的抽象 解决方案:性能分析后优化热点路径

Multi-Agent Workflow

多Agent工作流

Validation & Retrospectives

验证与回顾

  • Round 1 (Orchestrator): 행동 보존 체크리스트 검증
  • Round 2 (Analyst): 복잡도 및 중복 분석
  • Round 3 (Executor): 테스트 또는 정적 분석 검증
  • 第一轮(编排者):验证行为保留检查表
  • 第二轮(分析者):分析复杂度与重复代码
  • 第三轮(执行者):验证测试或静态分析结果

Agent Roles

Agent角色

AgentRole
Claude리팩토링 계획, 코드 변환
Gemini대규모 코드베이스 분석, 패턴 탐지
Codex테스트 실행, 빌드 검증
Agent角色
Claude制定重构计划、代码转换
Gemini大规模代码库分析、模式检测
Codex执行测试、构建验证

Workflow Example

工作流示例

bash
undefined
bash
undefined

1. Gemini: 코드베이스 분석

1. Gemini:分析代码库

ask-gemini "@src/ 복잡도 높은 함수 목록 추출"
ask-gemini "@src/ 提取复杂度高的函数列表"

2. Claude: 리팩토링 계획 및 실행

2. Claude:制定并执行重构计划

IMPLEMENTATION_PLAN.md 기반 작업

基于IMPLEMENTATION_PLAN.md开展工作

3. Codex: 검증

3. Codex:验证结果

codex-cli shell "npm test && npm run lint"
undefined
codex-cli shell "npm test && npm run lint"
undefined

References

参考资料

Metadata

元数据

버전

版本

  • 현재 버전: 1.0.0
  • 최종 업데이트: 2025-01-01
  • 호환 플랫폼: Claude, ChatGPT, Gemini
  • 当前版本:1.0.0
  • 最后更新:2025-01-01
  • 兼容平台:Claude, ChatGPT, Gemini

관련 스킬

相关技能

  • code-review
  • backend-testing
  • 代码评审
  • 后端测试

태그

标签

#refactoring
#code-quality
#DRY
#SOLID
#design-patterns
#clean-code
#refactoring
#code-quality
#DRY
#SOLID
#design-patterns
#clean-code

Examples

示例

Example 1: Basic usage

示例1:基础用法

<!-- Add example content here -->
<!-- 在此添加示例内容 -->

Example 2: Advanced usage

示例2:高级用法

<!-- Add advanced example content here -->
<!-- 在此添加高级示例内容 -->