DeepSeek 实战之九:重构的艺术------基于 AST 与 AI 的遗留系统"手术刀"式治理方案
前言
在软件工程中,最令人头秃的不是写新代码,而是维护**"遗留系统" (Legacy System)。
那些长达 2000 行的 utils.py,那些嵌套了 10 层 if-else 的"上帝函数",就像一颗颗定时炸弹。
传统的重构极其依赖个人经验,且风险巨大。但 DeepSeek 的出现改变了游戏规则。
本篇将超越简单的"代码优化",我们将结合 静态代码分析 (Static Analysis) 和 DeepSeek-R1 的推理能力,打造一套自动化的重构流水线。
我们将解决三个硬核问题:
-
精准定位: 如何用脚本自动找出项目中"最烂"的代码?
-
安全重构: 如何利用 Golden Master 策略,确保 AI 重构后的代码逻辑不变?
-
架构解耦: 如何把面向过程的"面条代码"自动重构为设计模式(如策略模式)?
一、 核心战术:AST 分析 + DeepSeek 靶向治疗
盲目把整个文件丢给 AI 是不专业的。我们需要先用 AST (Abstract Syntax Tree) 对代码进行"体检",找到病灶(高圈复杂度的函数),再让 DeepSeek 进行"微创手术"。
1. 编写"烂代码探测器"
我们将使用 Python 的 ast 模块和 radon 库来计算圈复杂度。
技术背景: 圈复杂度 (Cyclomatic Complexity) 衡量代码线性独立路径的数量。通常 > 10 表示复杂,> 20 表示极难维护。
import ast
import inspect
from radon.visitors import ComplexityVisitor
def scan_for_complex_functions(file_path, threshold=10):
"""
扫描指定文件,返回圈复杂度超过阈值的函数源码
"""
with open(file_path, 'r', encoding='utf-8') as f:
code = f.read()
# 1. 使用 Radon 计算复杂度
visitor = ComplexityVisitor.from_code(code)
complex_funcs = []
for func in visitor.functions:
if func.complexity > threshold:
print(f"⚠️ 发现高复杂度函数: {func.name} (复杂度: {func.complexity})")
# 2. 使用 AST 提取该函数的原始源码
# (这里为了简化演示,实际需结合 ast.get_source_segment 或类似逻辑)
# 简单实现:我们假设能获取起止行号
complex_funcs.append({
"name": func.name,
"complexity": func.complexity,
"lineno": func.lineno,
"endlineno": func.endlineno
})
return code, complex_funcs
2. DeepSeek 手术刀:策略模式重构
当我们定位到那个复杂度高达 25 的 calculate_pricing() 函数时,我们不仅仅是让 DeepSeek 简化它,而是要求它使用设计模式重构。
System Prompt 设计:
REFACTOR_PROMPT = """
你是一个精通设计模式的 Python 架构师。
请分析以下高复杂度的函数。它充斥着大量的 if-else 判断。
【任务】
1. 识别代码中的变化点(如不同的折扣策略、不同的支付渠道)。
2. 使用 **策略模式 (Strategy Pattern)** 或 **工厂模式** 对其进行解耦。
3. 将大函数拆解为多个小类或函数。
4. 保持对外接口签名不变(Defensive Refactoring)。
【输入代码】
{source_code}
"""
二、 核心保障:Golden Master 测试策略 (Snapshot Testing)
AI 重构最大的恐惧是:"改坏了逻辑"。
对于没有单元测试的遗留代码,我们必须先建立**"黄金快照" (Golden Master)**。
原理: 在重构前,用 1000 组随机数据跑一遍旧函数,记录下所有的输入和输出。重构后,用同样的输入跑新函数,确保输出完全一致。
自动化脚本实现
import json
import random
import importlib.util
# 1. 生成黄金数据 (Record)
def generate_golden_master(module_path, func_name, inputs, output_file="golden_data.json"):
# 动态加载模块
spec = importlib.util.spec_from_file_location("legacy_module", module_path)
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)
func = getattr(module, func_name)
records = []
for args in inputs:
try:
result = func(*args)
records.append({"input": args, "output": result})
except Exception as e:
records.append({"input": args, "error": str(e)})
with open(output_file, 'w') as f:
json.dump(records, f)
print(f"✅ 已为 {func_name} 生成 {len(records)} 条基准测试数据。")
# 2. 验证重构代码 (Replay)
def verify_refactoring(new_func, golden_file="golden_data.json"):
with open(golden_file, 'r') as f:
records = json.load(f)
for case in records:
args = case["input"]
expected = case.get("output")
actual = new_func(*args)
if actual != expected:
raise ValueError(f"❌ 重构失败!输入: {args}, 期望: {expected}, 实际: {actual}")
print("✨ 全量回归测试通过!重构是安全的。")
工作流:
-
定位到
calculate_pricing。 -
脚本自动生成随机参数,运行旧代码,保存
golden_data.json。 -
调用 DeepSeek 生成新代码。
-
脚本动态加载新代码,运行验证。
-
如果通过,自动覆盖原文件并 Git Commit。
三、 深度实战:Go 语言的依赖注入重构
在 Go 语言遗留系统中,最常见的问题是强耦合 (比如在 Controller 里直接 New 了一个 Database 实例)。这导致代码无法测试。
我们要利用 DeepSeek 自动提取接口,实现依赖注入 (DI)。
场景:
// 遗留代码
type OrderService struct {}
func (s *OrderService) Create() {
db := mysql.NewConnection() // 强耦合!无法 Mock!
db.Execute("INSERT...")
}
DeepSeek-R1 深度指令:
"分析这段 Go 代码。请应用依赖倒置原则 (DIP)。
提取
Database接口。修改
OrderService结构体,通过构造函数注入该接口。生成
mock_database.go用于单元测试(使用 gomock 规范)。"
生成的代码:
// 重构后
type Database interface {
Execute(query string) error
}
type OrderService struct {
db Database // 依赖接口
}
func NewOrderService(db Database) *OrderService {
return &OrderService{db: db}
}
这不仅仅是代码修改,这是架构层面的解耦。
四、 进阶:自动生成"防御性注释"与文档
重构完的代码虽然漂亮,但对于新人来说可能太抽象。
我们可以利用 DeepSeek 的 "Explanation Mode"。
在重构流水线的最后一步,让 AI 扫描新代码,并插入 Why-Comments:
不要只注释"是什么",要注释"为什么这么改"。
示例输出:
class PricingStrategy(ABC):
"""
[DeepSeek Refactor Note]:
提取为抽象基类,是为了隔离具体的促销逻辑。
之前所有的促销逻辑都硬编码在主流程中,导致每次新增活动都要修改核心代码。
"""
@abstractmethod
def calculate(self, price):
pass
五、 总结
我们构建的这套系统:
-
AST 扫描 -> 像 X 光一样发现病灶。
-
Golden Master -> 像安全网一样兜底逻辑。
-
DeepSeek 重构 -> 像资深专家一样进行手术。