代码重构
MyDeskBot 的智能代码重构功能帮助您改进代码结构、提高可维护性,同时保持功能不变。
目录
重构类型
1. 提取方法
将重复或复杂的代码块提取为独立方法:
重构前:
python
def process_users(users):
for user in users:
# 重复的验证逻辑
if not user.email or '@' not in user.email:
continue
if not user.name:
continue
# 处理用户
user.email = user.email.lower().strip()
user.name = user.name.title()重构后:
python
def is_valid_user(user):
return user.email and '@' in user.email and user.name
def process_users(users):
for user in users:
if not is_valid_user(user):
continue
user.email = user.email.lower().strip()
user.name = user.name.title()2. 内联方法
将简单的方法调用内联:
重构前:
javascript
function getDiscountedPrice(price, discount) {
return price * (1 - discount);
}
function calculateTotal(price, quantity, discount) {
return getDiscountedPrice(price, discount) * quantity;
}重构后:
javascript
function calculateTotal(price, quantity, discount) {
return price * (1 - discount) * quantity;
}3. 重命名变量/方法
使用更有意义的名称:
重构前:
java
public List<?> d(List<?> d, int c) {
if (d == null) return Collections.emptyList();
return d.stream().limit(c).collect(Collectors.toList());
}重构后:
java
public List<?> takeFirstNElements(List<?> data, int count) {
if (data == null) return Collections.emptyList();
return data.stream().limit(count).collect(Collectors.toList());
}4. 提取接口
从具体类中提取接口:
重构前:
typescript
class PostgreSQLDatabase {
connect(): void {}
query(sql: string): Promise<any> {}
close(): void {}
}
class MySQLDatabase {
connect(): void {}
query(sql: string): Promise<any> {}
close(): void {}
}重构后:
typescript
interface Database {
connect(): void;
query(sql: string): Promise<any>;
close(): void;
}
class PostgreSQLDatabase implements Database {}
class MySQLDatabase implements Database {}5. 移除重复代码
消除重复逻辑:
重构前:
javascript
function createUser(name, email) {
if (!name || name.trim() === "") {
throw new Error("Name is required");
}
if (!email || email.trim() === "") {
throw new Error("Email is required");
}
// ...
}
function updateUser(id, name, email) {
if (!name || name.trim() === "") {
throw new Error("Name is required");
}
if (!email || email.trim() === "") {
throw new Error("Email is required");
}
// ...
}重构后:
javascript
function validateName(name) {
if (!name || name.trim() === "") {
throw new Error("Name is required");
}
}
function validateEmail(email) {
if (!email || email.trim() === "") {
throw new Error("Email is required");
}
}
function createUser(name, email) {
validateName(name);
validateEmail(email);
// ...
}
function updateUser(id, name, email) {
validateName(name);
validateEmail(email);
// ...
}6. 简化条件表达式
简化复杂的条件:
重构前:
python
if status == 'active' and user.role == 'admin' and not user.deleted:
return True
else:
return False重构后:
python
def is_authorized(user):
return (
user.status == 'active'
and user.role == 'admin'
and not user.deleted
)7. 应用设计模式
MyDeskBot 可以识别机会并应用设计模式:
重构前:
java
public class ReportGenerator {
public String generatePDFReport() { }
public String generateHTMLReport() { }
public String generateExcelReport() { }
}重构后:
java
public interface ReportFormatter {
String format(ReportData data);
}
public class PDFFormatter implements ReportFormatter { }
public class HTMLFormatter implements ReportFormatter { }
public class ExcelFormatter implements ReportFormatter { }
public class ReportGenerator {
private final ReportFormatter formatter;
public ReportGenerator(ReportFormatter formatter) {
this.formatter = formatter;
}
public String generate(ReportData data) {
return formatter.format(data);
}
}使用方式
IntelliJ IDEA
- 选中要重构的代码
- 右键 → Refactor → Refactor with AI
- 描述重构目标或选择重构类型
- 预览变更
- 应用重构
VS Code
- 选中代码
- 按
Ctrl+Shift+R(Windows/Linux) /Cmd+Shift+R(macOS) - 或右键 → "Refactor with MyDeskBot"
- 查看建议的重构方案
- 接受或修改建议
Neovim
vim
" Visual 模式选中代码
:MyDeskBotRefactor
" 输入重构目标
" 提取这个函数重构准则
1. 保持功能不变
重构必须不改变代码的外部行为:
python
# 重构前
def calculate_total(price, quantity, discount=0):
return price * quantity * (1 - discount)
# 重构后 - 功能完全相同
def calculate_total(price, quantity, discount=0):
subtotal = price * quantity
discount_amount = subtotal * discount
return subtotal - discount_amount2. 小步重构
每次只做一个小改动,频繁测试:
javascript
// 第一步:提取常量
const TAX_RATE = 0.1;
// 第二步:提取方法
function calculateTax(amount) {
return amount * TAX_RATE;
}
// 第三步:使用新方法
function withTax(price) {
return price + calculateTax(price);
}3. 运行测试
每次重构后运行测试确保没有破坏任何功能。
4. 提交代码
小步重构后提交代码,便于回滚。
示例场景
场景 1: 长方法重构
原始代码:
python
def process_order(order):
# 验证订单
if not order.customer_id:
raise ValueError("Customer ID required")
if not order.items:
raise ValueError("Order must have items")
# 计算总价
total = 0
for item in order.items:
if item.price <= 0:
raise ValueError("Invalid item price")
if item.quantity <= 0:
raise ValueError("Invalid item quantity")
total += item.price * item.quantity
# 应用折扣
if order.customer_tier == 'premium':
total *= 0.9
elif order.customer_tier == 'gold':
total *= 0.85
# 检查库存
for item in order.items:
product = get_product(item.product_id)
if product.stock < item.quantity:
raise ValueError(f"Insufficient stock for {product.name}")
# 创建订单记录
db_order = OrderRecord(
customer_id=order.customer_id,
total=total,
status='pending'
)
save_order(db_order)
# 更新库存
for item in order.items:
update_stock(item.product_id, -item.quantity)
# 发送通知
send_email(order.customer_id, "Order confirmed", db_order.id)
return db_order.id重构后:
python
def process_order(order):
validate_order(order)
total = calculate_order_total(order)
check_stock_availability(order)
db_order = create_order_record(order, total)
update_product_stock(order)
send_confirmation(order, db_order.id)
return db_order.id
def validate_order(order):
if not order.customer_id:
raise ValueError("Customer ID required")
if not order.items:
raise ValueError("Order must have items")
def calculate_order_total(order):
total = 0
for item in order.items:
if item.price <= 0:
raise ValueError("Invalid item price")
if item.quantity <= 0:
raise ValueError("Invalid item quantity")
total += item.price * item.quantity
discount = get_customer_discount(order.customer_tier)
return total * (1 - discount)
def get_customer_discount(tier):
discounts = {'premium': 0.1, 'gold': 0.15}
return discounts.get(tier, 0)
def check_stock_availability(order):
for item in order.items:
product = get_product(item.product_id)
if product.stock < item.quantity:
raise ValueError(f"Insufficient stock for {product.name}")
def create_order_record(order, total):
db_order = OrderRecord(
customer_id=order.customer_id,
total=total,
status='pending'
)
save_order(db_order)
return db_order
def update_product_stock(order):
for item in order.items:
update_stock(item.product_id, -item.quantity)
def send_confirmation(order, order_id):
send_email(order.customer_id, "Order confirmed", order_id)场景 2: 复杂条件简化
原始代码:
java
public boolean canAccess(User user, Resource resource) {
if (user.isAdmin()) {
if (resource.isPublic() || resource.isSharedWith(user)) {
return true;
} else {
return false;
}
} else if (user.isPremium() && resource.isPremium()) {
if (user.hasSubscription() && !user.isExpired()) {
return true;
} else {
return false;
}
} else if (resource.isPublic()) {
return true;
} else if (resource.isSharedWith(user)) {
return true;
} else {
return false;
}
}重构后:
java
public boolean canAccess(User user, Resource resource) {
return isAccessibleByAdmin(user, resource)
|| isAccessibleByPremiumUser(user, resource)
|| isPublicOrShared(resource, user);
}
private boolean isAccessibleByAdmin(User user, Resource resource) {
return user.isAdmin() &&
(resource.isPublic() || resource.isSharedWith(user));
}
private boolean isAccessibleByPremiumUser(User user, Resource resource) {
return user.isPremium()
&& resource.isPremium()
&& user.hasActiveSubscription();
}
private boolean isPublicOrShared(Resource resource, User user) {
return resource.isPublic() || resource.isSharedWith(user);
}场景 3: 策略模式应用
原始代码:
typescript
function calculateShipping(type: string, weight: number, distance: number) {
if (type === "standard") {
return weight * 0.5 + distance * 0.1;
} else if (type === "express") {
return weight * 0.8 + distance * 0.2 + 10;
} else if (type === "overnight") {
return weight * 1.2 + distance * 0.3 + 20;
}
throw new Error("Invalid shipping type");
}重构后:
typescript
interface ShippingStrategy {
calculate(weight: number, distance: number): number;
}
class StandardShipping implements ShippingStrategy {
calculate(weight: number, distance: number): number {
return weight * 0.5 + distance * 0.1;
}
}
class ExpressShipping implements ShippingStrategy {
calculate(weight: number, distance: number): number {
return weight * 0.8 + distance * 0.2 + 10;
}
}
class OvernightShipping implements ShippingStrategy {
calculate(weight: number, distance: number): number {
return weight * 1.2 + distance * 0.3 + 20;
}
}
class ShippingCalculator {
private strategies: Map<string, ShippingStrategy> = new Map();
constructor() {
this.strategies.set("standard", new StandardShipping());
this.strategies.set("express", new ExpressShipping());
this.strategies.set("overnight", new OvernightShipping());
}
calculate(type: string, weight: number, distance: number): number {
const strategy = this.strategies.get(type);
if (!strategy) {
throw new Error("Invalid shipping type");
}
return strategy.calculate(weight, distance);
}
}最佳实践
- 有测试覆盖: 确保有足够的测试后再重构
- 小步前进: 每次只做一个小改动
- 频繁测试: 每次改动后运行测试
- 版本控制: 重构前创建分支或提交
- 团队沟通: 重构前与团队沟通意图
- 文档更新: 重构后更新相关文档