code-refactoring
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseCode 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)
- 테스트 먼저: 리팩토링 전 테스트 작성
- 작은 단계: 한 번에 하나씩 변경
- 동작 보존: 기능 변경 없음
- 先写测试:重构前编写测试用例
- 小步迭代:每次只做一处变更
- 保留行为:不改变原有功能
금지 사항 (MUST NOT)
禁止事项(MUST NOT)
- 동시에 여러 작업: 리팩토링 + 기능 추가 동시 금지
- 테스트 없이 리팩토링: 회귀 위험
- 同时做多件事:禁止同时进行重构和添加新功能
- 无测试重构:避免回归风险
Best practices
最佳实践
- Boy Scout Rule: 코드를 발견했을 때보다 깨끗하게
- 리팩토링 타이밍: Red-Green-Refactor (TDD)
- 점진적 개선: 완벽보다 꾸준히
- 행동 보존: 리팩토링은 기능 변경 없음
- 작은 커밋: 포커스된 단위로 커밋
- 童子军规则(Boy Scout Rule):离开时让代码比你发现时更干净
- 重构时机:遵循红-绿-重构(Red-Green-Refactor,TDD流程)
- 渐进式改进:追求持续优化而非一蹴而就
- 保留行为:重构不改变原有功能
- 小粒度提交:按聚焦的功能单元提交代码
Behavior Validation (Code Simplifier Integration)
行为验证(代码简化器集成)
Step A: Understand Current Behavior
步骤A:理解当前行为
리팩토링 전 현재 동작 완전히 이해:
markdown
undefined重构前需完全理解代码当前行为:
markdown
undefinedBehavior Analysis
行为分析
Inputs
输入
- [입력 파라미터 목록]
- [타입 및 제약사항]
- [输入参数列表]
- [类型及约束条件]
Outputs
输出
- [반환값]
- [부수 효과 (side effects)]
- [返回值]
- [副作用(side effects)]
Invariants
不变量
- [항상 참이어야 하는 조건들]
- [경계 조건 (edge cases)]
- [必须始终成立的条件]
- [边界情况(edge cases)]
Dependencies
依赖项
- [외부 의존성]
- [상태 의존성]
undefined- [外部依赖]
- [状态依赖]
undefinedStep B: Validate After Refactoring
步骤B:重构后验证
bash
undefinedbash
undefined1. 테스트 실행
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
undefinednpm test -- --updateSnapshot
undefinedStep C: Document Changes
步骤C:记录变更
markdown
undefinedmarkdown
undefinedRefactoring Summary
重构总结
Changes Made
已做变更
- [变更1]:[变更原因]
- [变更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角色
| Agent | Role |
|---|---|
| Claude | 리팩토링 계획, 코드 변환 |
| Gemini | 대규모 코드베이스 분석, 패턴 탐지 |
| Codex | 테스트 실행, 빌드 검증 |
| Agent | 角色 |
|---|---|
| Claude | 制定重构计划、代码转换 |
| Gemini | 大规模代码库分析、模式检测 |
| Codex | 执行测试、构建验证 |
Workflow Example
工作流示例
bash
undefinedbash
undefined1. 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"
undefinedcodex-cli shell "npm test && npm run lint"
undefinedReferences
参考资料
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-codeExamples
示例
Example 1: Basic usage
示例1:基础用法
<!-- Add example content here -->
<!-- 在此添加示例内容 -->
Example 2: Advanced usage
示例2:高级用法
<!-- Add advanced example content here -->
<!-- 在此添加高级示例内容 -->