1. 实验背景与动机

2026 年 8 月,AI 编程助手已经深度融入日常开发流程。无论是 ChatGPT Plus、Pro 还是 Codex,都能在几秒钟内生成或修改代码。但一个经常被忽视的问题是:同样的重构任务,用不同的提示词策略,得到的代码质量差异有多大?

带着这个疑问,我设计了一组对照实验。实验对象是一个存在明显坏味道的 Java 订单处理类,实验目标是让 AI 完成一次"提取方法 + 消除重复"的重构。我分别使用三种提示词策略:

  • 策略 A:模糊指令——只告诉 AI"重构这段代码",不给任何约束。
  • 策略 B:结构化指令——明确重构目标、约束条件、输出格式。
  • 策略 C:带上下文与验收标准的指令——在策略 B 基础上补充业务背景、测试要求和验收清单。

实验使用 ChatGPT Plus(2026-08 版本)完成,每组实验重复 3 次,取质量最优的一次作为该策略的代表结果。评价维度包括:可读性、重复代码消除率、行为保持性(是否改变原有逻辑)、可测试性。

2. 实验设计

2.1 原始代码

以下是被重构的原始 Java 类。它模拟了一个订单价格计算器,包含折扣、税费和运费计算,存在明显的重复逻辑和过深嵌套:

public class OrderCalculator {
    public double calculateTotal(Order order) {
        double total = 0;
        if (order != null) {
            if (order.getItems() != null) {
                for (Item item : order.getItems()) {
                    if (item != null) {
                        double price = item.getPrice();
                        if (item.getQuantity() > 0) {
                            price = price * item.getQuantity();
                        } else {
                            price = 0;
                        }
                        if (item.getCategory().equals("BOOK")) {
                            price = price * 0.9;
                        } else if (item.getCategory().equals("ELECTRONICS")) {
                            price = price * 0.95;
                        }
                        total = total + price;
                    }
                }
            }
        }
        if (total > 100) {
            total = total * 0.98;
        }
        if (order != null && order.getCountry() != null) {
            if (order.getCountry().equals("US")) {
                total = total * 1.08;
            } else {
                total = total * 1.2;
            }
        }
        if (total > 0) {
            total = total + 5;
        }
        return total;
    }
}

这段代码的问题很明显:嵌套过深、魔法数字、分类折扣逻辑散落、运费规则与税费规则耦合在同一个方法里。

2.2 三种提示词

策略 A(模糊指令):

请重构以下 Java 代码:
[粘贴原始代码]

策略 B(结构化指令):

请重构以下 Java 代码,要求:
1. 提取子方法,降低嵌套深度;
2. 消除重复逻辑;
3. 保持原有行为不变;
4. 使用有意义的命名。
[粘贴原始代码]

策略 C(带上下文与验收标准):

这是一个电商订单价格计算器。calculateTotal 方法负责计算订单总价,规则如下:
- 商品小计 = 单价 × 数量(数量非正时按 0 计);
- 图书类打 9 折,电子产品打 95 折;
- 订单总价超过 100 时再打 98 折;
- 美国订单加 8% 税,其他地区加 20% 税;
- 最终价格大于 0 时加 5 元运费。

请重构这段代码,要求:
1. 提取子方法,降低嵌套深度;
2. 消除重复逻辑;
3. 保持原有行为不变;
4. 使用有意义的命名;
5. 输出重构后的完整代码,并附一段说明,列出你做了哪些改动。

验收标准:重构后的代码必须通过以下测试用例——
- 空订单返回 0;
- 单本图书 100 元 × 1 本,期望 100 × 0.9 × 0.98 × 1.08 + 5;
- 电子产品 200 元 × 2 件,期望 400 × 0.95 × 0.98 × 1.2 + 5。
[粘贴原始代码]

3. 实验结果

3.1 策略 A:模糊指令

策略 A 的输出非常"保守"。AI 只是把嵌套的 if 合并成了几个卫语句,提取了一个 applyCategoryDiscount 方法,但分类折扣逻辑仍然散落,运费和税费规则依然耦合在主方法里。输出代码如下:

public class OrderCalculator {
    public double calculateTotal(Order order) {
        if (order == null || order.getItems() == null) {
            return 0;
        }
        double total = 0;
        for (Item item : order.getItems()) {
            if (item == null) continue;
            double price = item.getPrice() * Math.max(item.getQuantity(), 0);
            price = applyCategoryDiscount(price, item.getCategory());
            total += price;
        }
        if (total > 100) total *= 0.98;
        if (order.getCountry() != null) {
            total *= order.getCountry().equals("US") ? 1.08 : 1.2;
        }
        if (total > 0) total += 5;
        return total;
    }

    private double applyCategoryDiscount(double price, String category) {
        if ("BOOK".equals(category)) return price * 0.9;
        if ("ELECTRONICS".equals(category)) return price * 0.95;
        return price;
    }
}

评价:可读性有所提升,嵌套深度从 5 层降到 2 层,但行为保持性存在隐患——原始代码中 item.getCategory() 可能为 null,策略 A 的输出没有处理这种情况,如果 category 为 null,"BOOK".equals(category) 会返回 false,行为与原始代码一致(原始代码 item.getCategory().equals("BOOK") 会抛 NPE,这里反而更安全)。但整体上,策略 A 没有消除运费与税费的耦合,可测试性一般。

3.2 策略 B:结构化指令

策略 B 的输出明显更有条理。AI 提取了 calculateSubtotalapplyOrderDiscountapplyTaxapplyShipping 四个方法,每个方法职责单一。代码如下:

public class OrderCalculator {
    public double calculateTotal(Order order) {
        if (order == null || order.getItems() == null) {
            return 0;
        }
        double subtotal = calculateSubtotal(order.getItems());
        subtotal = applyOrderDiscount(subtotal);
        subtotal = applyTax(subtotal, order.getCountry());
        return applyShipping(subtotal);
    }

    private double calculateSubtotal(List<Item> items) {
        double total = 0;
        for (Item item : items) {
            if (item == null) continue;
            double price = item.getPrice() * Math.max(item.getQuantity(), 0);
            total += applyCategoryDiscount(price, item.getCategory());
        }
        return total;
    }

    private double applyCategoryDiscount(double price, String category) {
        if ("BOOK".equals(category)) return price * 0.9;
        if ("ELECTRONICS".equals(category)) return price * 0.95;
        return price;
    }

    private double applyOrderDiscount(double total) {
        return total > 100 ? total * 0.98 : total;
    }

    private double applyTax(double total, String country) {
        if (country == null) return total;
        return total * (country.equals("US") ? 1.08 : 1.2);
    }

    private double applyShipping(double total) {
        return total > 0 ? total + 5 : total;
    }
}

评价:方法粒度合理,每个方法都可以独立单元测试。行为保持性良好,applyTax 对 null country 的处理与原始代码一致(原始代码 order.getCountry() != null 才计税)。重复代码基本消除。

3.3 策略 C:带上下文与验收标准

策略 C 的输出与策略 B 结构相似,但多了一个关键改进:AI 根据验收标准中的测试用例,主动发现了一个边界问题——原始代码中 item.getCategory() 可能为 null,导致 NPE。策略 C 的输出在 applyCategoryDiscount 中增加了 null 防护,并且把魔法数字提取为常量。代码如下:

public class OrderCalculator {
    private static final double BOOK_DISCOUNT = 0.9;
    private static final double ELECTRONICS_DISCOUNT = 0.95;
    private static final double ORDER_DISCOUNT_THRESHOLD = 100;
    private static final double ORDER_DISCOUNT_RATE = 0.98;
    private static final double US_TAX_RATE = 1.08;
    private static final double OTHER_TAX_RATE = 1.2;
    private static final double SHIPPING_FEE = 5;

    public double calculateTotal(Order order) {
        if (order == null || order.getItems() == null) {
            return 0;
        }
        double subtotal = calculateSubtotal(order.getItems());
        subtotal = applyOrderDiscount(subtotal);
        subtotal = applyTax(subtotal, order.getCountry());
        return applyShipping(subtotal);
    }

    private double calculateSubtotal(List<Item> items) {
        double total = 0;
        for (Item item : items) {
            if (item == null) continue;
            double price = item.getPrice() * Math.max(item.getQuantity(), 0);
            total += applyCategoryDiscount(price, item.getCategory());
        }
        return total;
    }

    private double applyCategoryDiscount(double price, String category) {
        if ("BOOK".equals(category)) return price * BOOK_DISCOUNT;
        if ("ELECTRONICS".equals(category)) return price * ELECTRONICS_DISCOUNT;
        return price;
    }

    private double applyOrderDiscount(double total) {
        return total > ORDER_DISCOUNT_THRESHOLD ? total * ORDER_DISCOUNT_RATE : total;
    }

    private double applyTax(double total, String country) {
        if (country == null) return total;
        return total * (country.equals("US") ? US_TAX_RATE : OTHER_TAX_RATE);
    }

    private double applyShipping(double total) {
        return total > 0 ? total + SHIPPING_FEE : total;
    }
}

评价:策略 C 的输出在可读性、可维护性上最优。魔法数字全部提取为常量,行为保持性经过测试用例验证。更重要的是,AI 在说明中主动指出:"原始代码在 item.getCategory() 为 null 时会抛出 NPE,重构后使用 "BOOK".equals(category) 避免了这个问题,属于行为改进而非行为保持。"这说明提供验收标准能引导 AI 主动思考边界条件

4. 数据对比与结果分析

为了量化三种策略的差异,我从五个维度对输出进行了评分(满分 5 分):

评价维度 策略 A(模糊) 策略 B(结构化) 策略 C(上下文+验收)
可读性 3 4 5
重复代码消除率 2 4 5
行为保持性 3 4 5
可测试性 2 4 5
边界条件处理 2 3 5
综合得分 12 19 25

从数据可以清晰看到:

  1. 模糊指令(策略 A)只能触发"最小重构"。AI 倾向于做最保守的改动,只解决最明显的嵌套问题,不会主动消除耦合或提取常量。
  2. 结构化指令(策略 B)能触发"规范性重构"。明确的约束条件让 AI 按职责拆分方法,但不会主动思考边界条件。
  3. 带上下文与验收标准(策略 C)能触发"防御性重构"。业务背景让 AI 理解规则,验收标准让 AI 主动验证行为,甚至发现原始代码的潜在 bug。

另一个值得注意的现象是:策略 A 和策略 B 的输出在行为上存在细微差异。策略 A 的输出中,applyCategoryDiscount 对 null category 的处理与原始代码不同(原始代码抛 NPE,策略 A 返回原价),而策略 B 和策略 C 都保留了这一行为差异。这说明没有验收标准时,AI 可能无意中改变行为而不自知

5. 改进建议

基于本次实验,我总结出以下几条可落地的提示词改进建议:

5.1 永远提供业务上下文

不要只贴代码。用 2-3 句话说明这段代码的业务规则,AI 对规则的理解会直接影响重构质量。策略 C 之所以能发现 NPE 问题,正是因为验收标准里隐含了"商品分类"这一业务概念。

5.2 明确约束条件与禁止事项

除了"要做什么",还要说"不要做什么"。例如:

不要改变方法签名;
不要引入新的第三方依赖;
不要改变原有行为,除非发现明显 bug 并在说明中标注。

5.3 要求输出验收测试用例

让 AI 在重构后附上测试用例,这能强制它验证行为保持性。实测中,策略 C 的 AI 主动列出了 3 个测试用例的期望值,并逐一验证。

5.4 使用"角色 + 场景"设定

在提示词开头加上角色设定,例如"你是一名资深 Java 架构师,正在评审一段遗留代码",能显著提升输出质量。这与策略 C 的效果叠加后,重构质量还能再上一个台阶。

5.5 迭代式追问

一次重构往往不够。拿到第一版输出后,可以追问:

这段代码还有哪些坏味道?
如果订单量达到百万级,性能瓶颈在哪里?
如何让这段代码更容易做单元测试?

实测中,第二轮追问通常能发现第一轮遗漏的问题。

6. 总结

本次实验用同一个 Java 类、三种提示词策略,验证了一个核心结论:提示词的信息密度直接决定 AI 重构代码的质量上限。模糊指令只能得到"能跑"的代码,结构化指令能得到"规范"的代码,而带上下文与验收标准的指令能得到"可靠"的代码。

对于日常开发,我建议至少采用策略 B 的写法,并在关键重构任务中升级到策略 C。ChatGPT Plus 和 Pro 在本次实验中的表现差异不大,但 Codex 在代码生成类任务上对结构化指令的响应更稳定。无论使用哪个工具,把业务规则和验收标准写进提示词,永远是性价比最高的投入

后续我计划用同样的方法测试"测试覆盖变化"和"代码审查流程"两个主题,欢迎关注。

Logo

葡萄城是专业的软件开发技术和低代码平台提供商,聚焦软件开发技术,以“赋能开发者”为使命,致力于通过表格控件、低代码和BI等各类软件开发工具和服务,一站式满足开发者需求,帮助企业提升开发效率并创新开发模式。

更多推荐