37、重构工具实战(一):IDE自动重构功能(IntelliJ IDEA / VS Code)

说实话,很多程序员对重构有误解。觉得重构就是大动干戈,得专门排个迭代来做。其实不然。真正的高手,是把重构融入日常编码中的。怎么做到?靠的就是IDE的自动重构功能。

我刚开始带团队的时候,发现一个现象:新人改代码,经常是手动改完一个变量名,再满文件搜另一个。改完还提心吊胆,生怕漏了哪里。我当时就说:你们这是用记事本写代码呢?IDE给你准备了那么多快捷键,怎么不用?

今天我们就来聊聊,IntelliJ IDEA和VS Code里那些能让你「闭着眼」重构的功能。说白了,就是让工具替你干脏活累活。

重命名:最基础也最常用

重命名是所有重构操作里,我使用频率最高的一个。没有之一。

你想想看,一个项目写久了,变量名、函数名、类名,总有不满意的时候。手动改?太容易漏了。尤其是JavaScript这种动态语言,改个变量名,可能关联了十几个文件。

在IntelliJ IDEA里,重命名的快捷键是 Shift + F6。选中一个符号,按一下,输入新名字,回车。所有引用这个符号的地方,全部自动更新。包括注释里的引用,它都能识别。

VS Code里对应的是 F2。选中符号,按F2,输入新名字,回车。效果一样。

我的习惯: 每次接手遗留代码,第一件事就是把那些a、b、c、temp之类的变量名,全部重命名为有意义的名称。改完一个,代码的可读性就提升一分。这活儿不费脑子,但效果立竿见影。

提取方法/函数:告别长函数

长函数是代码坏味道的重灾区。我见过一个函数写了800行,里面什么都有:数据库查询、业务逻辑、UI渲染、日志打印……读这种代码,简直是在考古。

怎么治?提取方法。

在IntelliJ IDEA里,选中一段代码,按 Ctrl + Alt + M(Windows/Linux)或 Cmd + Option + M(Mac),IDE会自动帮你创建一个新方法。它会自动分析这段代码用了哪些局部变量,哪些需要作为参数传入,哪些可以作为返回值。你只需要给新方法起个名字就行。

VS Code里,选中代码后右键,选择「Refactor」→「Extract Function」,或者直接用快捷键 Ctrl + Shift + R(需要安装扩展)。

// 重构前
public void processOrder(Order order) {
    // 验证订单
    if (order.getItems() == null || order.getItems().isEmpty()) {
        throw new IllegalArgumentException("订单不能为空");
    }
    if (order.getTotalPrice() <= 0) {
        throw new IllegalArgumentException("订单金额必须大于0");
    }
    
    // 计算折扣
    double discount = 0;
    if (order.getTotalPrice() > 1000) {
        discount = 0.1;
    } else if (order.getTotalPrice() > 500) {
        discount = 0.05;
    }
    
    // 保存订单
    order.setDiscount(discount);
    orderRepository.save(order);
}

// 重构后
public void processOrder(Order order) {
    validateOrder(order);
    double discount = calculateDiscount(order);
    saveOrder(order, discount);
}

private void validateOrder(Order order) {
    if (order.getItems() == null || order.getItems().isEmpty()) {
        throw new IllegalArgumentException("订单不能为空");
    }
    if (order.getTotalPrice() <= 0) {
        throw new IllegalArgumentException("订单金额必须大于0");
    }
}

private double calculateDiscount(Order order) {
    if (order.getTotalPrice() > 1000) {
        return 0.1;
    } else if (order.getTotalPrice() > 500) {
        return 0.05;
    }
    return 0;
}

private void saveOrder(Order order, double discount) {
    order.setDiscount(discount);
    orderRepository.save(order);
}
核心原则: 一个方法只做一件事。如果你发现一个方法里,需要写注释来解释「这一段是干什么的」,那就说明该提取了。

提取变量/常量:消除魔法数字

代码里直接写数字、字符串,是新手最爱犯的毛病。比如 if (status == 3),3是什么?没人知道。得去翻文档、问同事。

用IDE的提取变量功能,可以快速解决这个问题。

在IntelliJ IDEA里,选中一个表达式,按 Ctrl + Alt + V,IDE会帮你创建一个变量,并用这个变量替换所有相同的表达式。如果你选中的是一个常量值,还可以选择提取为常量(Ctrl + Alt + C)。

VS Code里,选中表达式后,右键「Refactor」→「Extract to constant」或「Extract to variable」。

// 重构前
if (order.getStatus() == 3) {
    // 已发货
}

// 重构后
private static final int ORDER_STATUS_SHIPPED = 3;

if (order.getStatus() == ORDER_STATUS_SHIPPED) {
    // 已发货
}
我曾经踩过的坑: 提取变量时,IDE默认会用表达式的类型作为变量类型。但有时候,用接口类型而不是实现类型,会让代码更灵活。比如提取一个 ArrayList 时,我建议手动改成 List。IDE不会替你思考设计层面的东西,它只负责机械操作。

内联:反向操作也很有用

有提取,就有内联。内联是提取的反向操作。什么时候用?

比如你发现某个变量只被使用了一次,那这个变量就是多余的。直接内联掉,代码更简洁。或者某个方法体只有一行,而且只被调用了一次,也可以内联掉。

在IntelliJ IDEA里,选中变量或方法调用,按 Ctrl + Alt + N。VS Code里,选中后右键「Refactor」→「Inline variable」或「Inline function」。

// 内联前
String userName = user.getName();
System.out.println("Hello, " + userName);

// 内联后
System.out.println("Hello, " + user.getName());

移动和复制:调整代码结构

项目大了,类的位置经常需要调整。比如把某个工具类从 utils 包移到 common 包。手动移动?那所有引用这个类的地方都得改import。

用IDE的移动功能:在IntelliJ IDEA里,选中类名,按 F6,选择目标包,IDE会自动更新所有引用。VS Code里,右键「Refactor」→「Move to file」。

复制功能(F5)则适合用来创建相似类。比如你有一个 UserService,现在要创建一个 AdminService,大部分逻辑类似。复制一份,再改差异,比从头写快得多。

签名变更:改方法参数不再头疼

改方法签名,是重构里风险比较高的操作。尤其是当这个方法被很多地方调用时,改一个参数名、增删一个参数,都可能引发编译错误。

IDE的「Change Signature」功能就是为此设计的。在IntelliJ IDEA里,选中方法名,按 Ctrl + F6。你可以自由增删参数、调整顺序、改参数名。IDE会自动更新所有调用点,并且会提示你哪些地方需要手动处理(比如新参数没有默认值)。

VS Code里,这个功能需要安装扩展(比如「P42」或「JavaScript Refactor」),原生支持较弱。

我的建议: 改签名时,尽量给新参数设置默认值。这样调用方不需要立即修改,可以逐步迁移。这是大型项目里比较稳妥的做法。

知识体系总览

下面这张图,是我对IDE自动重构功能的一个梳理。你可以把它当作一个速查表。

IDE自动重构 重命名 (Rename) Shift+F6 (IDEA) F2 (VS Code) 提取 (Extract) 方法: Ctrl+Alt+M 变量: Ctrl+Alt+V 常量: Ctrl+Alt+C 内联 (Inline) Ctrl+Alt+N (IDEA) 移动/复制 移动: F6 (IDEA) 复制: F5 (IDEA) 签名变更 Ctrl+F6 (IDEA) 安全删除 Alt+Delete (IDEA) 检查所有引用 快捷键以 IntelliJ IDEA 默认配置为准,VS Code 需安装相应扩展

安全删除:别怕删代码

很多程序员不敢删代码,怕删了不该删的东西。其实IDE提供了「安全删除」功能。

在IntelliJ IDEA里,选中一个符号(类、方法、变量),按 Alt + Delete。IDE会先检查这个符号是否被任何地方引用。如果有引用,它会列出所有引用点,让你确认。只有确认没有引用后,才会真正删除。

这个功能我经常用来清理死代码。项目迭代久了,总会积累一些废弃的方法、类。用安全删除扫一遍,能清理掉不少垃圾。

注意: 安全删除只能检查编译期的引用。对于反射调用、Spring的Bean名称注入、XML配置里的引用,IDE是检查不到的。删之前,最好全局搜一下字符串引用。

总结一下

IDE的自动重构功能,说白了就是让你把精力集中在「改什么」上,而不是「怎么改」上。重命名、提取方法、提取变量、内联、移动、签名变更、安全删除——这七个功能,覆盖了日常重构90%的场景。

我个人建议,花一个下午的时间,把这些快捷键练熟。练到手指形成肌肉记忆。以后写代码,遇到坏味道,顺手就重构了。不用犹豫,不用纠结。工具就在那里,用就是了。

下一章,我们会聊聊更高级的重构工具——那些能跨文件、跨模块进行大规模重构的利器。敬请期待。


公众号:蓝海资料掘金营,微信deep3321