> For the complete documentation index, see [llms.txt](https://ethan-lin.gitbook.io/refactoring/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ethan-lin.gitbook.io/refactoring/dan-wei-zhuan-huan/5-refactorings-extract-constants.md).

# 任务3：提取字符串常量

上一节课的重命名应该比较简单，目的是让你慢慢找到一些重构的节奏和感觉。但是简单之中仍然有细节：每做完一次重构，修改了几行代码，你有没有做到及时运行测试，确保测试通过？频繁运行测试、小步前进，这跟 TDD 的精神是一样的：一是为了获得更快的反馈，二是减少出错时的排查范围。

接下来，在开展进一步重构前，我们需要**决定下一步重构的目标**。这件事可以靠直觉或者经验，也可以做做简单的分析。在继续之前，我想请你花 3 分钟时间阅读一下代码，把对这两个问题的想法写下来：**代码里有哪些坏味道/你觉得不好的地方？下一步从哪里开始重构？**

如果你对“坏味道”这个词不是很熟悉，那你可以翻开[《重构：改善既有代码的设计》](https://book.douban.com/subject/30468597/)一书的第三章通读一遍，里面列举了 24 种常见的坏味道，是用来判断“哪段代码需要重构”的一些建议。

![](/files/-Lr9XDTb44nl7goQjSEr)

比如说我看到的就有这么几个事情：

* 表示“单位”的字符串在多处（实现与测试里）出现。这是一种“重复代码（Duplicated Code）”
* 用于表示英尺的`"f"`字符串不够表意。这是一种“神秘命名（Mysterious Name）”
* `Length()`对象的创建过程也有一些“重复代码”（Duplicated Code）

你可以看到代码里用来描述长度单位的字符串到处都在使用，`as()`方法里在用，构造函数里在用，`getUnit()`函数里也在用，这种重复实际上增加了维护的难度。假如你要将其中一个字符串改成另外一个，你得记住修改所有的地方（那个表示英尺的`"f"`，我们看它不顺眼很久了不是吗）。Martin Fowler 在《重构 2》里讲到：“如果你在一个以上的地点看到相同的代码结构，那么可以肯定，设法将它们合而为一，程序会变得更好。”

这节课的任务，让我们先从简单的味道开始：将表示“单位”的字符串提炼到一处地方。

## 你的任务

Java：

```
git checkout task-3
./gradlew test
```

JavaScript：

```
git checkout task-3
npm test
```

1. 提炼`parseTo()`/`as()`方法中重复出现的表示“单位长度”的字符串
2. 使测试代码中硬编码的字符串也引用提炼出来的字符串常量
3. 修改表示英尺的`"f"`变量名
4. `git checkout task-4`看一下参考步骤
5. 再多练几次

## 参考资料

* 《重构 2》6.3 提炼变量（Extract Variable）


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ethan-lin.gitbook.io/refactoring/dan-wei-zhuan-huan/5-refactorings-extract-constants.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
