分治法实战:如何把 300 行的“屎山”函数拆解掉
面对一个逻辑极其复杂、嵌套了无数 if-else 的巨型函数,最糟糕的做法就是试图在原代码上打补丁。我之前写过一个报表生成器,要把三个 API 的数据拉回来,跑一遍业务规则再出 PDF。刚开始为了快,直接写了个 300 行的单函数,结果每次改个税率都要在几百行代码里翻找,稍微动一下就导致其他逻辑崩溃,简直像在闭眼拆炸弹。
这种拆分方式在用 Claude Code 或 Cursor 辅助编程时极其高效,因为你可以给 AI 一个非常明确的单一职责指令,而不是让它在几百行代码中猜测上下文。
这种写法把 I/O、数据转换和业务逻辑全部搅在一起,极难测试。
我将逻辑解耦为三个纯净的函数,这样每个部分都可以独立写单元测试。
下一篇
用 AI 写代码会被社区“嫌弃”?分享个真实经历 →
解决这种问题的核心不在于语法,而在于寻找“接缝(Seams)”。只要能把一个大问题拆成几个互不干扰的小模块,代码的可维护性会瞬间提升。
针对这种复杂逻辑,我习惯把流程强制划分为三个独立层级:
- 数据获取层:只负责调用 API 并将原始数据标准化。
- 业务规则引擎:纯函数处理,输入数据 → 输出结果,不涉及任何 I/O。
- 输出渲染层:只负责把处理好的结果填进 PDF 模板。
这种拆分方式在用 Claude Code 或 Cursor 辅助编程时极其高效,因为你可以给 AI 一个非常明确的单一职责指令,而不是让它在几百行代码中猜测上下文。
改造实操
改造前:典型的“大泥球”模式
这种写法把 I/O、数据转换和业务逻辑全部搅在一起,极难测试。
def generate_report(start_date, end_date):
# 1. 拉取数据(职责混杂)
raw_a = fetch_api_a(start_date, end_date)
raw_b = fetch_api_b(start_date, end_date)
raw_c = fetch_api_c(start_date, end_date)
# 2. 标准化(逻辑散乱)
data = []
for item in raw_a + raw_b + raw_c:
if item['type'] == 'sale':
data.append({
'amount': item['value'] * 1.08, # 税率硬编码
'date': item['timestamp'][:10],
'category': map_category(item['code'])
})
# 后面还跟着几十个 elif...
# 3. 执行业务规则(与循环耦合)
total = 0
for d in data:
if d['date'] >= '2024-01-01':
d['amount'] *= 1.05 # 促销逻辑
if d['category'] == 'electronics':
d['amount'] *= 0.9 # 折扣逻辑
total += d['amount']
# 4. 渲染 PDF(与数据准备混在一起)
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
pdf.cell(0, 10, f"Report Total: {total:.2f}", ln=1)
# ... 更多渲染代码
pdf.output("report.pdf")改造后:分治工作流
我将逻辑解耦为三个纯净的函数,这样每个部分都可以独立写单元测试。
# -------------------------------------------------
# 1. 数据获取层:仅负责 I/O 和初步清洗
# -------------------------------------------------
def fetch_all_data(start_date, end_date):
raw_data = fetch_api_a(start_date, end_date) + \
fetch_api_b(start_date, end_date) + \
fetch_api_c(start_date, end_date)
return [normalize_item(item) for item in raw_data]
# -------------------------------------------------
# 2. 业务规则层:纯函数,无副作用
# -------------------------------------------------
def apply_business_rules(data):
processed_data = []
for item in data:
amount = item['amount']
if item['date'] >= '2024-01-01':
amount *= 1.05
if item['category'] == 'electronics':
amount *= 0.9
processed_data.append({**item, 'amount': amount})
return processed_data
# -------------------------------------------------
# 3. 渲染层:只关注表现层
# -------------------------------------------------
def render_pdf_report(data, output_path):
pdf = FPDF()
# ... 渲染逻辑
pdf.output(output_path)通过这种方式,如果以后 API 字段变了,我只需要改 fetch_all_data;如果促销政策变了,我只需要改 apply_business_rules。这种从零构建清晰工作流的习惯,比死磕任何一个具体的 AI 提示词都要有用。