IntelliJ IDEA 重构 uMarkdown 实战:Rename / Extract Method 手法详解

原创2026-09-21 18:58:37207 阅读
文章标签:文档教程

IntelliJ IDEA 重构 uMarkdown 实战:Rename / Extract Method 手法详解

写在前面:这本 GitHub 重构指南在讲什么

《GitHub 漫游指南》中专门有一章讲「改善 GitHub 项目代码质量:重构」,用一个真实的开源小项目 uMarkdown(一个把 Markdown 转换成 HTML 的库)做重构示范,并手把手演示 IntelliJ IDEA 的 5 种经典重构手法:Rename、Extract Method、Inline Method、Pull Members Up、Replace Temp with Query。本章完整收录在 06-refactor-project.md。

IntelliJ IDEA 重构 uMarkdown:GitHub 开源项目代码重构指南

为什么重构:写代码容易,读代码难

书里的一句话很扎心:

写代码容易,读代码难。

假设我们写代码只要半天,别人读起来却要一天。那为什么不花一天的时间把代码写得更好,让别人半天就能读懂?

两条铁律先记住:

  • 没有测试保护,不要动已上线的代码——盲目重构只会引入更多 Bug;
  • 重构要小步快跑:编写测试 → 功能代码 → 修改测试 → 重构,每个循环都跑一遍测试。

获取重构练习代码:uMarkdown 长什么样

uMarkdown 的代码是非常典型的「过程式代码」:一连串 while 循环里堆着正则匹配和字符串替换,比如处理 code 块的部分:

while ((stra = micromarkdown.regexobject.code.exec(str)) !== null) {
  str = str.replace(stra[0], '<code>\n' + micromarkdown.htmlEncode(stra[1]) ...);
}

问题一目了然:

  • 变量名 stra、str 含义不明;
  • 每一段 while 循环结构几乎一模一样,大量重复;
  • 所有逻辑挤在一个函数里,职责不清。

它的 Markdown 解析过程类似「Pipe and Filters」架构模式:正则表达式是各个 Filter,字符串 str 是管口的输入输出。重构目标,就是把这些 Filter 一个个抽出来。完整代码与说明见 06-refactor-project.md。

IntelliJ IDEA 重构手法一:Rename 重命名(Shift + F6)

作用:安全重命名。把光标放在变量名上,按下 Shift + F6,输入新名字,IDEA 会自动更新所有引用位置。

书中示例:变量 c、d 根本看不出表达什么,重命名为 result_add、result_sub 后,代码立刻可读:

int result_add = new Cal().add(1, 2);
int result_sub = new Cal2().sub(2, 1);

新手最常犯的错误是手动全局替换,漏改一处就埋下 bug;Rename 重构由编译器级分析保证引用一致,永远选它。

IntelliJ IDEA 重构手法二:Extract Method 提取方法(Alt + Cmd + M)

作用:把选中的代码片段提取成独立方法,让主流程更清晰。

书中对 uMarkdown 的重构正是从这里开始:把 code 块那段 while 循环体,提取成 codeFilter 方法:

codeFilter: function (str, stra) {
  return str.replace(stra[0], '<code>\n' + micromarkdown.htmlEncode(stra[1]) ...);
}

原来的 while 循环就变成:

while ((stra = regexobject.code.exec(str)) !== null) {
  str = this.codeFilter(str, stra);
}

对 mail、headline 做同样处理后,再用 forEach + apply 把重复循环统一掉——9 种 Markdown 类型的处理,从一坨重复代码变成三行。提取方法后记得跑一遍全部测试,看到 ✓ 全绿再提交。

IntelliJ IDEA 重构手法三:Inline Method 内联方法(Alt + Cmd + N)

作用:与提取方法相反,把过短、没有存在价值的方法「压回」调用处。

书中演示:如果刚提取的 mprint 方法只有一行 System.out.println,反而让阅读多一次跳转,那就选它执行 Inline,勾选「Inline all invocations and remove the method」,代码还原为直接调用。

提取与内联是一对来回:方法名能表达意图就保留,不能就内联回去。

IntelliJ IDEA 重构手法四:Pull Members Up 上提成员

作用:把子类里「本该属于父类」的成员上提到基类。

书中例子:Cal2 extends Cal,但 sub 方法写在子类 Cal2 里,而 add 在父类 Cal 里。右键选择 Pull Members Up,sub 被提到 Cal,两个方法归位,继承结构才符合直觉。

IntelliJ IDEA 重构手法五:Replace Temp with Query 以查询取代临时变量

作用:过多的临时变量会撑长函数。选中临时变量,执行该重构,它会被替换成一个查询方法,函数体只留逻辑主干。

Replace Temp with Query 重构菜单:IntelliJ IDEA 重构手法详解

重构前,basePrice 临时变量夹在判断中间:

public void count() {
  double basePrice = _quantity * _itemPrice;
  if (basePrice > 1000) {
    return basePrice * 0.95;
  } else {
    return basePrice * 0.98;
  }
}

重构后,函数主干只剩业务判断:

public void count() {
  if (basePrice() > 1000) {
    return basePrice() * 0.95;
  } else {
    return basePrice() * 0.98;
  }
}

小技巧:它等价于先对表达式「Extract Method」再「Inline Method」两步走,记住这点,任何编辑器里都能手工复刻。

重构循环:测试先行,diff 收尾

把五种手法串起来,就是书中推荐的完整开发流程:

  1. 编写测试(功能复杂时先行,功能简单时可行);
  2. 写功能代码;
  3. 修改、补充测试;
  4. 重构,并随时运行测试。

每完成一个循环,用 diff 检查一遍改动范围——只看到预期的几行变化,才敢提交。

重构代码 Git diff 检查改动:GitHub 开源项目代码质量

小结:一套 GitHub 代码重构技巧清单

手法 快捷键(Mac) 一句话场景
Rename Shift + F6 变量名含义不明
Extract Method Alt + Cmd + M 函数过长、逻辑可独立命名
Inline Method Alt + Cmd + N 方法太短,反而碍阅读
Pull Members Up 右键 Refactor 成员放错了子类
Replace Temp with Query Cmd + Alt + Shift + T 临时变量撑长函数

重构不是「重写」,而是一系列安全、可回滚的小变形。想完整练习,可以到 Artisan Stack 的 js-refactor 练习仓库里动手,把 uMarkdown 的每个 Filter 都抽出来,跑绿全部测试后再提交 pull request。更多章节可阅读 GitHub 漫游指南。

登录后查看全文
github