---
title: "代码修改与优化"
description: "改代码之前先摸清影响面，把「不能动什么」写进需求；重构、提速、补类型都拆成小步，每步用测试证明原有行为没被破坏。"
updated: 2026-11-13
canonical: https://docai.cc/learn/code-modification-optimization/
markdown_mirror: https://docai.cc/learn/code-modification-optimization.md
---
## 改之前，先问影响面

新增代码只影响自己，修改代码却牵动所有调用方。所以第一步不是下命令，而是摸底：

> 先别动手。这个邮箱校验函数被哪些地方引用、改动后哪些入口会受影响、现有测试能覆盖到什么程度，把这三件事列清楚再说话。

拿到调用清单，你再决定哪些行为必须保留。看不见的依赖，往往是线上事故的来源。清单列完再动手，能避免改到一半才发现方向错了。

## 把限制写进需求

改动的质量，取决于你有没有说清「不能动什么」。三条约束最常用：旧参数必须保留、接口签名不能变、不新增依赖。

> 给现有的搜索接口加一个排序参数，默认按相关度排序。
> 旧调用不传这个参数时，返回结果与现在完全一致。
> 不改返回结构，不新增第三方依赖。

这样写，它会在兼容的前提下扩展，而不是顺手把接口重设计一遍。加字段、加方法、加可选参数，都适用同一套说法。约束不是不信任，而是把返工挡在提交之前。

## 重构：一次只做一件事

重构最容易失控的地方，是「顺手」：拆函数时顺手改名，改名时顺手改逻辑。改完测试挂了，你都不知道是哪一步惹的。

| 目标 | 这一轮只做 | 留到下一轮 |
|---|---|---|
| 拆长函数 | 把代码搬进小函数，逻辑原样 | 改名、改判断顺序 |
| 消除重复 | 抽出公共处理 | 统一各处细节行为 |
| 改善命名 | 换名字，保留行为 | 调整结构 |
| 压平嵌套 | 把不满足的情况逐个提前挡回 | 合并条件、换算法 |

最后一项值得单独说：三层嵌套的判断，重构成「先挡掉不满足的情况，最后只剩成功路径」，读起来会顺很多。但这一步只调整结构，不改变任何分支的结果。判断条件本身是否合理，是另一件事，别在同一轮里改。

还有一个常被忽略的约束：改动的范围要和需求对得上。让它修一个空指针，结果它顺手重排了整个文件，diff 里几十行无关变化，审查的人根本看不出哪一行是关键。需求里写明「只改这一个函数」，diff 才会干净。

每一轮结束都跑一次相关测试。测试通过，再进入下一轮。

## 性能：先测量，再动手

没有测量数据的「优化」，多数只是换个写法。先定位瓶颈，再选手段：

- 循环里反复查库，改成一次批量查询；
- 热点数据加缓存，同时想清楚键名、过期时间和更新时怎么失效；
- 列表渲染开销大，只在输入变化时重新计算；
- 首屏图片太多，进入视口再加载。

每次只处理一个瓶颈，改完复测同一组指标。快了多少要有数字，不能凭感觉。

## 质量和安全：让验证可重复

补错误处理时，把行为写成清单：失败重试几次、间隔怎么增长、最终抛什么错、请求能不能中途取消。重试与退避的取舍见[退避与重试](/concepts/retry-backoff/)。

把模糊类型换成具体类型、按项目配置统一格式、清理调试输出，这些都属于低风险改动，但同样要跑测试。大改造则拆成小步：先抽出一块，验证，再抽下一块，任何一步都能单独回滚。

改完做两件事：跑与该模块相关的测试，看输出而不是听话术；再看一遍改动范围，确认没有夹带无关修改。把这两件事变成习惯，修改才敢交给它做。

## 扩展与迁移：两类改动的固定动作

**给现有函数加参数。** 新参数一律可选，默认值等于旧行为。比如日期格式化原来只输出年月日，现在要支持三种格式：

```js
formatDate(value)                 // 旧行为，保持 YYYY-MM-DD
formatDate(value, 'datetime')     // 带时分秒
formatDate(value, 'relative')     // 显示相对时间
```

指令里把三种取值和默认值写全，再补一句「不传第二参时，输出与现在逐字符一致」。接口加筛选参数同理：`role`、`status`、`createdAfter` 各自可选、可以组合，不传时结果集不变。

**迁移到新格式。** 依赖升级、第三方响应改结构、JavaScript 换 TypeScript，都走三项固定动作：先找全调用点，再机械替换，最后跑类型检查和测试。比如响应从 `{ data: { user } }` 变成 `{ result: { userData } }`，先让它列出所有读旧字段的位置，确认清单完整再动手；缺一个，线上就多一个空值。

改完怎么判断有没有把握，见[评估改动](/learn/evaluate-changes/)。三类症状对应三种处理：

| 现象 | 为什么 | 怎么办 |
| --- | --- | --- |
| 单测全绿，线上仍报错 | 测试没覆盖真实调用方 | 先列调用点，补一条走真实入口的测试 |
| 优化后反而更慢 | 没有改前基线，凭感觉选手段 | 先记录耗时和次数，改完复测同一组指标 |
| 差异里混着大量格式变化 | 指令范围太宽，顺手格式化了整个文件 | 限定「只改这个函数」，提交前逐行看差异 |

改得动，还要讲得清。下一节看怎么把改动变成团队能接手的提交与审查：[基础代码协作](/learn/basic-code-collaboration/)。
