refactor
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseRefactor
重构
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
适用场景
Use this skill when:
- 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
黄金准则
- Behavior is preserved - Refactoring doesn't change what the code does, only how
- Small steps - Make tiny changes, test after each
- Version control is your friend - Commit before and after each safe state
- Tests are essential - Without tests, you're not refactoring, you're editing
- One thing at a time - Don't mix refactoring with feature changes
- 保留行为 - 重构仅改变代码的实现方式,不改变代码的功能
- 小步迭代 - 每次只做微小修改,修改后立即测试
- 善用版本控制 - 在每个安全状态前后都进行提交
- 测试是核心 - 没有测试的话,你不是在重构,只是在修改代码
- 一次只做一件事 - 不要将重构与功能开发混在一起
When NOT to Refactor
不适合重构的场景
- Code that works and won't change again (if it ain't broke...)
- 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
1. 过长方法/函数
diff
undefineddiff
undefinedBAD: 200-line function that does everything
糟糕:200行的全能函数
- async function processOrder(orderId) {
- // 50 lines: fetch order
- // 30 lines: validate order
- // 40 lines: calculate pricing
- // 30 lines: update inventory
- // 20 lines: create shipment
- // 30 lines: send notifications
- }
- async function processOrder(orderId) {
- // 50行:获取订单
- // 30行:验证订单
- // 40行:计算定价
- // 30行:更新库存
- // 20行:创建物流单
- // 30行:发送通知
- }
GOOD: Broken into focused functions
良好:拆分为专注单一功能的函数
- async function processOrder(orderId) {
- const order = await fetchOrder(orderId);
- validateOrder(order);
- const pricing = calculatePricing(order);
- await updateInventory(order);
- const shipment = await createShipment(order);
- await sendNotifications(order, pricing, shipment);
- return { order, pricing, shipment };
- }
undefined- async function processOrder(orderId) {
- const order = await fetchOrder(orderId);
- validateOrder(order);
- const pricing = calculatePricing(order);
- await updateInventory(order);
- const shipment = await createShipment(order);
- await sendNotifications(order, pricing, shipment);
- return { order, pricing, shipment };
- }
undefined2. Duplicated Code
2. 重复代码
diff
undefineddiff
undefinedBAD: Same logic in multiple places
糟糕:多处存在相同逻辑
- function calculateUserDiscount(user) {
- if (user.membership === 'gold') return user.total * 0.2;
- if (user.membership === 'silver') return user.total * 0.1;
- return 0;
- }
- function calculateOrderDiscount(order) {
- if (order.user.membership === 'gold') return order.total * 0.2;
- if (order.user.membership === 'silver') return order.total * 0.1;
- return 0;
- }
- function calculateUserDiscount(user) {
- if (user.membership === 'gold') return user.total * 0.2;
- if (user.membership === 'silver') return user.total * 0.1;
- return 0;
- }
- function calculateOrderDiscount(order) {
- if (order.user.membership === 'gold') return order.total * 0.2;
- if (order.user.membership === 'silver') return order.total * 0.1;
- return 0;
- }
GOOD: Extract common logic
良好:提取公共逻辑
- function getMembershipDiscountRate(membership) {
- const rates = { gold: 0.2, silver: 0.1 };
- return rates[membership] || 0;
- }
- function calculateUserDiscount(user) {
- return user.total * getMembershipDiscountRate(user.membership);
- }
- function calculateOrderDiscount(order) {
- return order.total * getMembershipDiscountRate(order.user.membership);
- }
undefined- function getMembershipDiscountRate(membership) {
- const rates = { gold: 0.2, silver: 0.1 };
- return rates[membership] || 0;
- }
- function calculateUserDiscount(user) {
- return user.total * getMembershipDiscountRate(user.membership);
- }
- function calculateOrderDiscount(order) {
- return order.total * getMembershipDiscountRate(order.user.membership);
- }
undefined3. Large Class/Module
3. 过大的类/模块
diff
undefineddiff
undefinedBAD: God object that knows too much
糟糕:无所不知的上帝对象
- class UserManager {
- createUser() { /* ... */ }
- updateUser() { /* ... */ }
- deleteUser() { /* ... */ }
- sendEmail() { /* ... */ }
- generateReport() { /* ... */ }
- handlePayment() { /* ... */ }
- validateAddress() { /* ... */ }
- // 50 more methods...
- }
- class UserManager {
- createUser() { /* ... */ }
- updateUser() { /* ... */ }
- deleteUser() { /* ... */ }
- sendEmail() { /* ... */ }
- generateReport() { /* ... */ }
- handlePayment() { /* ... */ }
- validateAddress() { /* ... */ }
- // 还有50多个方法...
- }
GOOD: Single responsibility per class
良好:每个类单一职责
- class UserService {
- create(data) { /* ... */ }
- update(id, data) { /* ... */ }
- delete(id) { /* ... */ }
- }
- class EmailService {
- send(to, subject, body) { /* ... */ }
- }
- class ReportService {
- generate(type, params) { /* ... */ }
- }
- class PaymentService {
- process(amount, method) { /* ... */ }
- }
undefined- class UserService {
- create(data) { /* ... */ }
- update(id, data) { /* ... */ }
- delete(id) { /* ... */ }
- }
- class EmailService {
- send(to, subject, body) { /* ... */ }
- }
- class ReportService {
- generate(type, params) { /* ... */ }
- }
- class PaymentService {
- process(amount, method) { /* ... */ }
- }
undefined4. Long Parameter List
4. 过长参数列表
diff
undefineddiff
undefinedBAD: Too many parameters
糟糕:参数过多
- function createUser(email, password, name, age, address, city, country, phone) {
- /* ... */
- }
- function createUser(email, password, name, age, address, city, country, phone) {
- /* ... */
- }
GOOD: Group related parameters
良好:分组相关参数
- interface UserData {
- email: string;
- password: string;
- name: string;
- age?: number;
- address?: Address;
- phone?: string;
- }
- function createUser(data: UserData) {
- /* ... */
- }
- interface UserData {
- email: string;
- password: string;
- name: string;
- age?: number;
- address?: Address;
- phone?: string;
- }
- function createUser(data: UserData) {
- /* ... */
- }
EVEN BETTER: Use builder pattern for complex construction
更优:复杂构造使用建造者模式
- const user = UserBuilder
- .email('test@example.com')
- .password('secure123')
- .name('Test User')
- .address(address)
- .build();
undefined- const user = UserBuilder
- .email('test@example.com')
- .password('secure123')
- .name('Test User')
- .address(address)
- .build();
undefined5. Feature Envy
5. 特性依恋
diff
undefineddiff
undefinedBAD: Method that uses another object's data more than its own
糟糕:方法使用其他对象的数据远多于自身数据
- class Order {
- calculateDiscount(user) {
-
if (user.membershipLevel === 'gold') {
-
return this.total * 0.2; -
} -
if (user.accountAge > 365) { -
return this.total * 0.1; -
} -
return 0; - }
- }
- class Order {
- calculateDiscount(user) {
-
if (user.membershipLevel === 'gold') {
-
return this.total * 0.2; -
} -
if (user.accountAge > 365) { -
return this.total * 0.1; -
} -
return 0; - }
- }
GOOD: Move logic to the object that owns the data
良好:将逻辑移至拥有数据的对象
- class User {
- getDiscountRate(orderTotal) {
-
if (this.membershipLevel === 'gold') return 0.2; -
if (this.accountAge > 365) return 0.1; -
return 0; - }
- }
- class Order {
- calculateDiscount(user) {
-
return this.total * user.getDiscountRate(this.total); - }
- }
undefined- class User {
- getDiscountRate(orderTotal) {
-
if (this.membershipLevel === 'gold') return 0.2; -
if (this.accountAge > 365) return 0.1; -
return 0; - }
- }
- class Order {
- calculateDiscount(user) {
-
return this.total * user.getDiscountRate(this.total); - }
- }
undefined6. Primitive Obsession
6. 基本类型偏执
diff
undefineddiff
undefinedBAD: Using primitives for domain concepts
糟糕:使用基本类型表示领域概念
-
function sendEmail(to, subject, body) { /* ... */ }
-
sendEmail('user@example.com', 'Hello', '...');
-
function createPhone(country, number) {
-
return;
${country}-${number} -
}
-
function sendEmail(to, subject, body) { /* ... */ }
-
sendEmail('user@example.com', 'Hello', '...');
-
function createPhone(country, number) {
-
return;
${country}-${number} -
}
GOOD: Use domain types
良好:使用领域类型
- class Email {
- private constructor(public readonly value: string) {
-
if (!Email.isValid(value)) throw new Error('Invalid email'); - }
- static create(value: string) { return new Email(value); }
- static isValid(email: string) { return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email); }
- }
- class PhoneNumber {
- constructor(
-
public readonly country: string, -
public readonly number: string - ) {
-
if (!PhoneNumber.isValid(country, number)) throw new Error('Invalid phone'); - }
- toString() { return ; }
${this.country}-${this.number} - static isValid(country: string, number: string) { /* ... */ }
- }
- // Usage
- const email = Email.create('user@example.com');
- const phone = new PhoneNumber('1', '555-1234');
undefined- class Email {
- private constructor(public readonly value: string) {
-
if (!Email.isValid(value)) throw new Error('Invalid email'); - }
- static create(value: string) { return new Email(value); }
- static isValid(email: string) { return /^[^\s@]+@[^\s@]+.[^\s@]+$/.test(email); }
- }
- class PhoneNumber {
- constructor(
-
public readonly country: string, -
public readonly number: string - ) {
-
if (!PhoneNumber.isValid(country, number)) throw new Error('Invalid phone'); - }
- toString() { return ; }
${this.country}-${this.number} - static isValid(country: string, number: string) { /* ... */ }
- }
- // 使用示例
- const email = Email.create('user@example.com');
- const phone = new PhoneNumber('1', '555-1234');
undefined7. Magic Numbers/Strings
7. 魔法数字/字符串
diff
undefineddiff
undefinedBAD: Unexplained values
糟糕:无注释的神秘值
- if (user.status === 2) { /* ... */ }
- const discount = total * 0.15;
- setTimeout(callback, 86400000);
- 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,
- VIP: 0.2
- } as const;
- const ONE_DAY_MS = 24 * 60 * 60 * 1000;
- if (user.status === UserStatus.INACTIVE) { /* ... */ }
- const discount = total * DISCOUNT_RATES.PREMIUM;
- setTimeout(callback, ONE_DAY_MS);
undefined- const UserStatus = {
- ACTIVE: 1,
- INACTIVE: 2,
- SUSPENDED: 3
- } as const;
- const DISCOUNT_RATES = {
- STANDARD: 0.1,
- PREMIUM: 0.15,
- VIP: 0.2
- } as const;
- const ONE_DAY_MS = 24 * 60 * 60 * 1000;
- if (user.status === UserStatus.INACTIVE) { /* ... */ }
- const discount = total * DISCOUNT_RATES.PREMIUM;
- setTimeout(callback, ONE_DAY_MS);
undefined8. Nested Conditionals
8. 嵌套条件语句
diff
undefineddiff
undefinedBAD: Arrow code
糟糕:箭头代码
- function process(order) {
- if (order) {
-
if (order.user) { -
if (order.user.isActive) { -
if (order.total > 0) { -
return processOrder(order);
-
} else { -
return { error: 'Invalid total' }; -
} -
} else { -
return { error: 'User inactive' }; -
} -
} else { -
return { error: 'No user' }; -
} - } else {
-
return { error: 'No order' }; - }
- }
- function process(order) {
- if (order) {
-
if (order.user) { -
if (order.user.isActive) { -
if (order.total > 0) { -
return processOrder(order);
-
} else { -
return { error: 'Invalid total' }; -
} -
} else { -
return { error: 'User inactive' }; -
} -
} else { -
return { error: 'No user' }; -
} - } else {
-
return { error: 'No order' }; - }
- }
GOOD: Guard clauses / early returns
良好:卫语句/提前返回
- function process(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);
- }
- function process(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);
- }
EVEN BETTER: Using Result type
更优:使用Result类型
- function process(order): Result<ProcessedOrder, Error> {
- return Result.combine([
-
validateOrderExists(order), -
validateUserExists(order), -
validateUserActive(order.user), -
validateOrderTotal(order) - ]).flatMap(() => processOrder(order));
- }
undefined- function process(order): Result<ProcessedOrder, Error> {
- return Result.combine([
-
validateOrderExists(order), -
validateUserExists(order), -
validateUserActive(order.user), -
validateOrderTotal(order) - ]).flatMap(() => processOrder(order));
- }
undefined9. Dead Code
9. 死代码
diff
undefineddiff
undefinedBAD: Unused code lingers
糟糕:残留的未使用代码
- function oldImplementation() { /* ... */ }
- const DEPRECATED_VALUE = 5;
- import { unusedThing } from './somewhere';
- // Commented out code
- // function oldCode() { /* ... */ }
- function oldImplementation() { /* ... */ }
- const DEPRECATED_VALUE = 5;
- import { unusedThing } from './somewhere';
- // 注释掉的代码
- // function oldCode() { /* ... */ }
GOOD: Remove it
良好:删除未使用代码
- // Delete unused functions, imports, and commented code
- // If you need it again, git history has it
undefined- // 删除未使用的函数、导入和注释代码
- // 如果之后需要,Git历史记录里会有
undefined10. Inappropriate Intimacy
10. 过度亲密
diff
undefineddiff
undefinedBAD: One class reaches deep into another
糟糕:一个类深入访问另一个类的内部
- class OrderProcessor {
- process(order) {
-
order.user.profile.address.street; // Too intimate -
order.repository.connection.config; // Breaking encapsulation
- }
- }
- class OrderProcessor {
- process(order) {
-
order.user.profile.address.street; // 过于亲密 -
order.repository.connection.config; // 破坏封装
- }
- }
GOOD: Ask, don't tell
良好:请求,而非命令
- class OrderProcessor {
- process(order) {
-
order.getShippingAddress(); // Order knows how to get it -
order.save(); // Order knows how to save itself - }
- }
---- class OrderProcessor {
- process(order) {
-
order.getShippingAddress(); // Order知道如何获取地址 -
order.save(); // Order知道如何保存自己 - }
- }
---Extract Method Refactoring
提取方法重构
Before and After
重构前后对比
diff
undefineddiff
undefinedBefore: One long function
重构前:单一长函数
- function printReport(users) {
- console.log('USER REPORT');
- console.log('============');
- console.log('');
- console.log();
Total users: ${users.length} - console.log('');
- console.log('ACTIVE USERS');
- console.log('------------');
- const active = users.filter(u => u.isActive);
- active.forEach(u => {
-
console.log(`- ${u.name} (${u.email})`); - });
- console.log('');
- console.log();
Active: ${active.length} - console.log('');
- console.log('INACTIVE USERS');
- console.log('--------------');
- const inactive = users.filter(u => !u.isActive);
- inactive.forEach(u => {
-
console.log(`- ${u.name} (${u.email})`); - });
- console.log('');
- console.log();
Inactive: ${inactive.length} - }
- function printReport(users) {
- console.log('USER REPORT');
- console.log('============');
- console.log('');
- console.log();
Total users: ${users.length} - console.log('');
- console.log('ACTIVE USERS');
- console.log('------------');
- const active = users.filter(u => u.isActive);
- active.forEach(u => {
-
console.log(`- ${u.name} (${u.email})`); - });
- console.log('');
- console.log();
Active: ${active.length} - console.log('');
- console.log('INACTIVE USERS');
- console.log('--------------');
- const inactive = users.filter(u => !u.isActive);
- inactive.forEach(u => {
-
console.log(`- ${u.name} (${u.email})`); - });
- console.log('');
- console.log();
Inactive: ${inactive.length} - }
After: Extracted methods
重构后:提取方法
- function printReport(users) {
- printHeader('USER REPORT');
- console.log();
Total users: ${users.length}\n - printUserSection('ACTIVE USERS', users.filter(u => u.isActive));
- printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));
- }
- function printHeader(title) {
- const line = '='.repeat(title.length);
- console.log(title);
- console.log(line);
- console.log('');
- }
- function printUserSection(title, users) {
- console.log(title);
- console.log('-'.repeat(title.length));
- users.forEach(u => console.log());
- ${u.name} (${u.email}) - console.log('');
- console.log();
${title.split(' ')[0]}: ${users.length} - console.log('');
- }
---- function printReport(users) {
- printHeader('USER REPORT');
- console.log();
Total users: ${users.length}\n - printUserSection('ACTIVE USERS', users.filter(u => u.isActive));
- printUserSection('INACTIVE USERS', users.filter(u => !u.isActive));
- }
- function printHeader(title) {
- const line = '='.repeat(title.length);
- console.log(title);
- console.log(line);
- console.log('');
- }
- function printUserSection(title, users) {
- console.log(title);
- console.log('-'.repeat(title.length));
- users.forEach(u => console.log());
- ${u.name} (${u.email}) - console.log('');
- console.log();
${title.split(' ')[0]}: ${users.length} - console.log('');
- }
---Introducing Type Safety
引入类型安全性
From Untyped to Typed
从无类型到强类型
diff
undefineddiff
undefinedBefore: No types
重构前:无类型
- function calculateDiscount(user, total, membership, date) {
- if (membership === 'gold' && date.getDay() === 5) {
-
return total * 0.25; - }
- if (membership === 'gold') return total * 0.2;
- return total * 0.1;
- }
- function calculateDiscount(user, total, membership, date) {
- if (membership === 'gold' && date.getDay() === 5) {
-
return total * 0.25; - }
- if (membership === 'gold') return total * 0.2;
- return total * 0.1;
- }
After: Full type safety
重构后:完全类型安全
- type Membership = 'bronze' | 'silver' | 'gold';
- interface User {
- id: string;
- name: string;
- membership: Membership;
- }
- interface DiscountResult {
- original: number;
- discount: number;
- final: number;
- rate: number;
- }
- function calculateDiscount(
- user: User,
- total: number,
- date: Date = new Date()
- ): DiscountResult {
- if (total < 0) throw new Error('Total cannot be negative');
- let rate = 0.1; // Default bronze
- if (user.membership === 'gold' && date.getDay() === 5) {
-
rate = 0.25; // Friday bonus for gold - } else if (user.membership === 'gold') {
-
rate = 0.2; - } else if (user.membership === 'silver') {
-
rate = 0.15; - }
- const discount = total * rate;
- return {
-
original: total, -
discount, -
final: total - discount, -
rate - };
- }
---- type Membership = 'bronze' | 'silver' | 'gold';
- interface User {
- id: string;
- name: string;
- membership: Membership;
- }
- interface DiscountResult {
- original: number;
- discount: number;
- final: number;
- rate: number;
- }
- function calculateDiscount(
- user: User,
- total: number,
- date: Date = new Date()
- ): DiscountResult {
- if (total < 0) throw new Error('Total cannot be negative');
- let rate = 0.1; // 默认bronze等级
- if (user.membership === 'gold' && date.getDay() === 5) {
-
rate = 0.25; // 黄金会员周五额外折扣 - } else if (user.membership === 'gold') {
-
rate = 0.2; - } else if (user.membership === 'silver') {
-
rate = 0.15; - }
- const discount = total * rate;
- return {
-
original: total, -
discount, -
final: total - discount, -
rate - };
- }
---Design Patterns for Refactoring
重构常用设计模式
Strategy Pattern
策略模式
diff
undefineddiff
undefinedBefore: Conditional logic
重构前:条件逻辑
- function calculateShipping(order, method) {
- if (method === 'standard') {
-
return order.total > 50 ? 0 : 5.99; - } else if (method === 'express') {
-
return order.total > 100 ? 9.99 : 14.99;
- } else if (method === 'overnight') {
-
return 29.99; - }
- }
- function calculateShipping(order, method) {
- if (method === 'standard') {
-
return order.total > 50 ? 0 : 5.99; - } else if (method === 'express') {
-
return order.total > 100 ? 9.99 : 14.99;
- } else if (method === 'overnight') {
-
return 29.99; - }
- }
After: Strategy pattern
重构后:策略模式
- interface ShippingStrategy {
- calculate(order: Order): number;
- }
- class StandardShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return order.total > 50 ? 0 : 5.99; - }
- }
- class ExpressShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return order.total > 100 ? 9.99 : 14.99; - }
- }
- class OvernightShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return 29.99; - }
- }
- function calculateShipping(order: Order, strategy: ShippingStrategy) {
- return strategy.calculate(order);
- }
undefined- interface ShippingStrategy {
- calculate(order: Order): number;
- }
- class StandardShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return order.total > 50 ? 0 : 5.99; - }
- }
- class ExpressShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return order.total > 100 ? 9.99 : 14.99; - }
- }
- class OvernightShipping implements ShippingStrategy {
- calculate(order: Order) {
-
return 29.99; - }
- }
- function calculateShipping(order: Order, strategy: ShippingStrategy) {
- return strategy.calculate(order);
- }
undefinedChain of Responsibility
责任链模式
diff
undefineddiff
undefinedBefore: Nested validation
重构前:嵌套验证
- function validate(user) {
- const errors = [];
- if (!user.email) errors.push('Email required');
- else if (!isValidEmail(user.email)) errors.push('Invalid email');
- if (!user.name) errors.push('Name required');
- if (user.age < 18) errors.push('Must be 18+');
- if (user.country === 'blocked') errors.push('Country not supported');
- return errors;
- }
- function validate(user) {
- const errors = [];
- if (!user.email) errors.push('Email required');
- else if (!isValidEmail(user.email)) errors.push('Invalid email');
- if (!user.name) errors.push('Name required');
- if (user.age < 18) errors.push('Must be 18+');
- if (user.country === 'blocked') errors.push('Country not supported');
- return errors;
- }
After: Chain of responsibility
重构后:责任链模式
- abstract class Validator {
- abstract validate(user: User): string | null;
- setNext(validator: Validator): Validator {
-
this.next = validator; -
return validator; - }
- validate(user: User): string | null {
-
const error = this.doValidate(user); -
if (error) return error; -
return this.next?.validate(user) ?? null; - }
- }
- class EmailRequiredValidator extends Validator {
- doValidate(user: User) {
-
return !user.email ? 'Email required' : null; - }
- }
- class EmailFormatValidator extends Validator {
- doValidate(user: User) {
-
return user.email && !isValidEmail(user.email) ? 'Invalid email' : null; - }
- }
- // Build the chain
- const validator = new EmailRequiredValidator()
- .setNext(new EmailFormatValidator())
- .setNext(new NameRequiredValidator())
- .setNext(new AgeValidator())
- .setNext(new CountryValidator());
---- abstract class Validator {
- abstract validate(user: User): string | null;
- setNext(validator: Validator): Validator {
-
this.next = validator; -
return validator; - }
- validate(user: User): string | null {
-
const error = this.doValidate(user); -
if (error) return error; -
return this.next?.validate(user) ?? null; - }
- }
- class EmailRequiredValidator extends Validator {
- doValidate(user: User) {
-
return !user.email ? 'Email required' : null; - }
- }
- class EmailFormatValidator extends Validator {
- doValidate(user: User) {
-
return user.email && !isValidEmail(user.email) ? 'Invalid email' : null; - }
- }
- // 构建责任链
- const validator = new EmailRequiredValidator()
- .setNext(new EmailFormatValidator())
- .setNext(new NameRequiredValidator())
- .setNext(new AgeValidator())
- .setNext(new CountryValidator());
---Refactoring Steps
重构步骤
Safe Refactoring Process
安全重构流程
1. PREPARE
- Ensure tests exist (write them if missing)
- Commit current state
- Create feature branch
2. IDENTIFY
- Find the code smell to address
- Understand what the code does
- Plan the refactoring
3. REFACTOR (small steps)
- Make one small change
- Run tests
- Commit if tests pass
- Repeat
4. VERIFY
- All tests pass
- Manual testing if needed
- Performance unchanged or improved
5. CLEAN UP
- Update comments
- Update documentation
- Final commit1. 准备阶段
- 确保存在测试用例(如果没有则编写)
- 提交当前代码状态
- 创建功能分支
2. 识别阶段
- 找出需要处理的代码异味
- 理解代码的功能
- 规划重构方案
3. 重构(小步迭代)
- 做出一个微小修改
- 运行测试
- 测试通过则提交
- 重复上述步骤
4. 验证阶段
- 所有测试通过
- 如有需要进行手动测试
- 性能无下降或有所提升
5. 清理阶段
- 更新注释
- 更新文档
- 最终提交Refactoring Checklist
重构检查清单
Code Quality
代码质量
- Functions are small (< 50 lines)
- Functions do one thing
- No duplicated code
- Descriptive names (variables, functions, classes)
- No magic numbers/strings
- Dead code removed
- 函数体积小(少于50行)
- 函数单一职责
- 无重复代码
- 命名具有描述性(变量、函数、类)
- 无魔法数字/字符串
- 已删除死代码
Structure
结构
- Related code is together
- Clear module boundaries
- Dependencies flow in one direction
- No circular dependencies
- 相关代码集中在一起
- 模块边界清晰
- 依赖单向流动
- 无循环依赖
Type Safety
类型安全性
- Types defined for all public APIs
- No types without justification
any - Nullable types explicitly marked
- 所有公共API都定义了类型
- 无无理由的类型
any - 可空类型已明确标记
Testing
测试
- Refactored code is tested
- Tests cover edge cases
- All tests pass
- 重构后的代码已覆盖测试
- 测试覆盖边缘情况
- 所有测试通过
Common Refactoring Operations
常见重构操作
| Operation | Description |
|---|---|
| Extract Method | Turn code fragment into method |
| Extract Class | Move behavior to new class |
| Extract Interface | Create interface from implementation |
| Inline Method | Move method body back to caller |
| Inline Class | Move class behavior to caller |
| Pull Up Method | Move method to superclass |
| Push Down Method | Move method to subclass |
| Rename Method/Variable | Improve clarity |
| Introduce Parameter Object | Group related parameters |
| Replace Conditional with Polymorphism | Use polymorphism instead of switch/if |
| Replace Magic Number with Constant | Named constants |
| Decompose Conditional | Break complex conditions |
| Consolidate Conditional | Combine duplicate conditions |
| Replace Nested Conditional with Guard Clauses | Early returns |
| Introduce Null Object | Eliminate null checks |
| Replace Type Code with Class/Enum | Strong typing |
| Replace Inheritance with Delegation | Composition over inheritance |
| 操作名称 | 描述 |
|---|---|
| Extract Method | 将代码片段提取为方法 |
| Extract Class | 将行为移至新类 |
| Extract Interface | 从实现中提取接口 |
| Inline Method | 将方法体移回调用处 |
| Inline Class | 将类的行为移回调用处 |
| Pull Up Method | 将方法移至父类 |
| Push Down Method | 将方法移至子类 |
| Rename Method/Variable | 重命名以提升清晰度 |
| Introduce Parameter Object | 分组相关参数 |
| Replace Conditional with Polymorphism | 用多态替代switch/if条件判断 |
| Replace Magic Number with Constant | 使用命名常量替代魔法数字 |
| Decompose Conditional | 拆分复杂条件 |
| Consolidate Conditional | 合并重复条件 |
| Replace Nested Conditional with Guard Clauses | 用卫语句替代嵌套条件 |
| Introduce Null Object | 消除空值检查 |
| Replace Type Code with Class/Enum | 使用强类型替代类型码 |
| Replace Inheritance with Delegation | 用组合替代继承 |