从重构到窒息:Claude Code 半小时搞定我两天的活儿

上周接手了个老项目,一个用户管理系统,代码四千来行,全特么塞在 user_service.py 一个文件里。那个函数耦合得,就像我妈包的韭菜盒子,咬一口发现里面还裹着昨天的饺子。

我本来打算自己人肉重构,估摸着起码要两天。后来同事跟我说 Claude Code 挺好用,我一开始还不信,心想这不就是个花里胡哨的补全插件嘛。

别废话了,直接上干货。我用真实的业务场景,把 Claude Code 怎么分析、怎么重构、还有我踩的那些坑,全都给你抖出来。你会看到一个从“屎山”到“整洁架构”的完整过程,以及我因为忘了一件事,差点把生产环境搞崩的惨痛教训。

(图片:一张“屎山代码”的截图,各种函数嵌套、全局变量、魔法数字,旁边加个红色箭头指着说“这里就是地狱”。)

第一步:先把“屎山”扔给 Claude Code,让它先骂两句

我一开始也犯过这个错,上来就让它直接改代码,结果改出来一团浆糊。后来发现,正确的做法是:先让它分析,生成一份诊断报告。

我当时直接把那个 user_service.py 文件丢进 Claude Code 的上下文里,然后输入了这么一段话:


分析这个文件的结构问题。列出所有坏味道:圈复杂度超过 10 的函数、重复代码块、未处理的异常、明显违反 SOLID 原则的地方。用表格输出,每行一个建议。
`

注意这里的关键词:“圈复杂度”、“未处理的异常”、“SOLID 原则”。千万别问它“你觉得哪里有问题”,要给它具体的评估指标,告诉它从哪个角度去分析。Claude Code 的输出大概是这样的:

| 函数名 | 圈复杂度 | 问题描述 | 建议 |
|--------|----------|----------|------|
|
get_user_by_email | 15 | 嵌套4层if-else,未处理数据库连接异常 | 抽离验证逻辑,使用 guard clause |
|
send_notification | 12

<

p> | 同时处理邮件和短信,违反单一职责 | 拆成两个函数,用策略模式 |
|
update_user_profile | 18 | 直接在函数里拼 SQL 语句 | 引入 ORM 或至少用参数化查询 |

看到了吧?它会精确到某个函数、某个指标、具体建议。这个设计一开始觉得有点反人类,但后来发现 Claude Code 的强项就是这种结构化分析,你只需要告诉它“从什么角度分析”就行。

顺手说个坑:不要给它整个项目,只给要重构的那个文件,外加它依赖的接口定义。否则它会把无关模块也改掉,我有一次发现它把 auth.py 里也加了个跟认证八竿子打不着的缓存逻辑,我当时直接懵了,赶紧回滚代码。

第二步:用“渐进式重构”指令,别想一口吃成胖子

拿到分析报告后,很多人下一步就会输入“帮我重构这个文件”——我告诉你,这是灾难性的错误。Claude Code 会一次性生成几百行代码,你根本不知道它改了什么,而且大概率会改出一堆 bug。

我的做法是:分三个阶段,每个阶段只改一个关注点

阶段一:提取常量和工作单元

我先输入:

`
把文件中所有硬编码字符串(比如数据库连接字符串、状态码、错误消息)提取到文件顶部,用大写常量定义。不改动任何逻辑。
`

这步最简单,但能大幅提高可维护性。重构前:

`python
def get_user_by_email(email):
conn = psycopg2.connect("host=localhost dbname=users user=admin password=secret")
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE email = ? AND status = 'active'")
# ...
`

重构后:

`python
DB_CONN_STRING = "host=localhost dbname=users user=admin password=secret"
USER_STATUS_ACTIVE = "active"
ERROR_USER_NOT_FOUND = "User not found"

def get_user_by_email(email):
conn = psycopg2.connect(DB_CONN_STRING)
cur = conn.cursor()
cur.execute("SELECT * FROM users WHERE email = ? AND status = %s", (USER_STATUS_ACTIVE,))
# ...
`

为什么要这么写?因为当生产环境报错“数据库连接失败”时,你只需要改一个 DB_CONN_STRING,而不是在四个函数里翻来翻去。而且 Claude Code 做这种“机械提取”,几乎零失误,特别靠谱。

阶段二:函数拆分和异常处理

提取完之后,再输入:

`
识别所有圈复杂度超过 10 的函数,将它们拆分为多个小于 5 行的小函数。每个小函数只做一件事,并添加类型注解。同时给每个函数添加 docstring,说明参数和返回值。
`

这个指令里有两个关键点:“圈复杂度超过 10”和“小于 5 行”。前者告诉它“哪些需要动”,后者告诉它“拆到什么粒度”。Claude Code 就会按这个标准去拆,不会自作主张。

比如原来那个 send_notification 函数:

`python
def send_notification(user_id, message, method):
if method == "email":
# 20 行发邮件的代码
pass
elif method == "sms":
# 15 行发短信的代码
pass
elif method == "push":
# 10 行推送的代码
pass
else:
raise ValueError(f"Unknown method: {method}")
`

拆完之后就变成了三个文件加一个策略类:

`python

strategy.py

from abc import ABC, abstractmethod

class NotificationStrategy(ABC):
/> @abstractmethod
def send(self, user_id: int, message: str) -> bool:
"""发送通知,返回是否成功"""
pass

email_strategy.py

class EmailNotification(NotificationStrategy):
def send(self, user_id: int, message: str) -> bool:
# 只有发邮件的逻辑,没有 switch
pass

sms_strategy.py

class SMSNotification(NotificationStrategy):
def send(self, user_id: int, message: str) -> bool:
# 只有发短信的逻辑
pass
`

官方文档那段文档不够清晰,说什么“关注点分离”、“单一职责”,我当时也没完全看懂。但是 Claude Code 真把代码改出来的时候,你才真正明白:原来拆完之后,测试变成了单独测 EmailNotification,业务方要加个“微信通知”只需要再加一个类,不需要改老代码。真的好用。

(图片:一个对比图,左边是“屎山”代码,右边是重构后的整洁架构,中间画个大箭头写着“Claude Code 半小时”。)

第三步:处理那些 Claude Code 搞不定的脏活(以及我踩的第三个坑)

到这里,Claude Code 已经帮我完成了 80% 的重构。但还有两个事情它搞不定,而且第三个坑差点让部署挂掉。

坑一:它不会迁移测试用例

重构之后,旧的测试用例全废了。Claude Code 把 send_notification 拆成了三个类,但测试文件里还是 test_send_notification。怎么办?别指望它自动迁移,你得手动输入:

`
根据新的代码结构,为每个 NotificationStrategy 子类生成单元测试。使用 pytest 框架,覆盖正常、异常、边界三种场景。不要改动业务代码。
`

Claude Code 会生成新的测试文件,你只需要把旧的删掉。这步不能省,否则 CI 会红,到时候你就等着被同事骂吧。

坑二:它不会处理数据库迁移(坑三的核心)

第三个坑,也是我差点把生产环境搞崩的那个:我让 Claude Code 改了 update_user_profile 函数,把参数从 user_id 改成 user_uuid。它改得很完美,代码里所有引用都更新了,我当时还挺得意的。但问题是:生产环境的数据库表字段没改。部署上去之后,所有更新用户资料的请求都报 Column “user_id” does not exist,直接把用户端搞崩了。我当时心里就一句“我靠,还能这样?”

血的教训:Claude Code 只改代码,不改数据库模式。重构 SQL 语句或表结构时,一定、一定、一定要手动检查数据库迁移脚本。我现在会在重构前先输入:

`
列出所有涉及数据库模式变更的重构点:修改了哪些表的字段名、新增了哪些索引、删除了哪些列。用 SQL DDL 语句输出每个变更。
`

这样 Claude Code 会生成一个“数据库变更清单”,你拿着这个去跑迁移,就不会遗漏。别问我怎么知道的。

验证:用 Claude Code 检测重构是否成功

重构完之后,很多人直接就点部署了。我的做法是:让 Claude Code 自己给自己打分。

输入:

`
对比重构前后的代码,从以下维度评估:行数减少百分比、圈复杂度平均下降值、重复代码块数量、函数平均行数。输出一个对比表格。
`

这是我从 3.2 秒降到 0.8 秒那次的经验:重构后,代码行数从 4230 降到了 2850,圈复杂度平均值从 12 降到 4,重复代码块从 7 个变成 0。这不是“感觉上好了”,而是有数据的。

另外,Claude Code 还会自动发现一些隐性问题。有一次它告诉我:“重构后 create_user 函数中,email 参数的类型注解从 str 变成了 Optional[str]`,但调用方没有处理 None 值。” 我靠,这个 bug 我手动 review 了两遍都没发现,差点又栽了。

(图片:一个对比表格,左边是重构前的指标,右边是重构后的,用红绿颜色标注提升,标题写“数据说话”。)

最后说几个我踩坑换来的经验

  • 别信它的“一次性重构”:每次只改一个关注点,提取常量、拆分函数、重构逻辑,分三趟走。别想一步到位,你就算这么跟它说,它也会给你挖坑。
  • 数据库模式变更,千万别交给它:这玩意儿只懂代码,不懂表结构。我踩的那个坑,就是因为它改代码时改了字段名,但我忘了跑迁移脚本。现在每次重构前,我都先让它输出“数据库变更清单”,再手动跑一遍。
  • 测试用例必须手动重建:Claude Code 能生成新测试,但不会自动迁移旧的。你别指望它聪明到能识别哪些旧用例该删、哪些该改。老老实实删掉旧的,让它重新生成。
  • 验证阶段别跳过:让它自己给自己打分,行数、圈复杂度、重复代码块,有数据才安心。而且它还能发现你 review 漏掉的 bug,比如类型注解变了但调用方没处理。
  • 这玩意儿不是神器,但用好它,能让你从“屎山”里爬出来。关键在于:你得知道它的边界在哪,哪些活它能干,哪些活你得自己来。别像我一样,一开始把它当万能的,结果踩了三个坑才明白。

    滚动至顶部