引言

最近,我一直在观察团队中使用 AI 编程助手的模式与效果。发现了一个有趣的现象:

当我们在一个拥有 10 年历史的存量代码库中引入 AI 时,它表现得像个刚毕业的实习生——经常犯错、需要大量监督、甚至会把整个模块搞崩溃。

但当我们从零开始一个新项目时,同样的 AI 却能展现出架构师的潜质——代码结构清晰、模式运用得当、效率惊人。

这不仅仅是我的个人感受。经过深入思考,我得出了一个结论:

AI 不适合处理增量代码,但它天生就是为全新代码开发而生的。

这个结论背后有着深刻的认知逻辑。今天,我想通过这篇文章,聊聊这个观点。

第一部分:存量代码的“不可理解性”

1.1 问题本质:认知基础的不牢靠

存量代码最大的问题是什么?不仅是代码写得差,而是它承载了太多“隐式上下文”,导致新需求扩展困难。

这些隐式上下文包括:

  • 历史遗留的业务逻辑(“为什么这里要加 1?因为 5 年前有个客户提了个特殊需求”)

  • 多人协作产生的风格冲突(A 喜欢工厂模式,B 喜欢简单函数)

  • 不断妥协的技术债(“本来应该重构,但上线时间不够,先这样吧”)

  • 隐含的依赖关系(“这个函数看起来没用,但删了之后登录就挂了”)

AI 学习的是人类公开发布的代码、文档、最佳实践。它学到的是“理想世界”的编码方式。但存量代码往往是“现实世界”的产物——充满了妥协、历史包袱和非理性的决策。

AI 的认知建立在理想之上,而你的代码建立在现实之上。这两者之间存在一道鸿沟。

1.2 代码案例:AI 在存量代码中的失败

让我们看一个具体的例子。假设我们有一个遗留的订单处理模块:

# 存量代码(有 8 年历史)
class OrderProcessor:
    def __init__(self):
        self.db = LegacyDatabaseConnection()  # 已废弃的数据库驱动
        self.cache = {}  # 手动实现的简陋缓存
        
    def process_order(self, order_data):
        # 为什么要用字符串拼接?因为 2016 年那个版本不支持 JSON
        query = "SELECT * FROM orders WHERE order_id = '" + order_data['id'] + "'"
        
        # 为什么要写这个 if?因为某个大客户的数据格式特殊
        if order_data.get('client_id') == 'SPECIAL_CLIENT_001':
            order_data['amount'] = order_data['amount'] * 1.08  # 加 8% 手续费
        
        result = self.db.execute(query)
        
        # 这个缓存逻辑有 bug,但所有人都不敢动
        if result[0]['status'] in self.cache:
            return self.cache[result[0]['status']]
        
        # 300 行类似的业务逻辑...

现在,假设我们让 AI 帮忙重构这个 process_order 方法:

# AI 给出的“优化”代码
class OrderProcessor:
    def __init__(self, db: Database, cache: CacheService):
        self.db = db  # AI 认为应该用依赖注入
        self.cache = cache
        
    async def process_order(self, order_data: dict) -> dict:  # AI 加了 async
        # AI 使用了参数化查询(这是最佳实践)
        query = "SELECT * FROM orders WHERE order_id = $1"
        
        # AI 移除了特殊客户的特殊逻辑(因为它认为这应该是配置化的)
        # 但这样会导致那个大客户的订单金额计算错误!
        
        result = await self.db.execute(query, order_data['id'])
        
        # AI 改用了现代缓存抽象
        return await self.cache.get_or_set(
            result[0]['status'], 
            lambda: self._process_logic(result[0])
        )

这段 AI 生成的代码技术上更优秀,但它破坏了业务逻辑:

  1. 移除了特殊客户的 8% 手续费(业务错误)

  2. 改用了异步(与调用方不兼容)

  3. 改变了缓存行为(可能引发性能问题)

问题不在于 AI 的能力,而在于 AI 无法理解这 8% 手续费背后的历史故事。

1.3 “重写”的经济学

有人会问:那我们可以花时间让 AI 理解这些存量代码吗?

答案是:可以,但成本可能比重写还高。

让 AI 理解存量代码,你需要:

  1. 为 AI 提供完整的业务上下文(可能需要梳理数百个需求文档)

  2. 逐个解释历史遗留决策的原因

  3. 建立一套“规则库”来约束 AI 的行为

  4. 每次迭代都要更新这个知识库

这个过程本身就是一项巨大的工程。等到你终于把 AI “教会” 了,你其实已经完成了一次隐式的重构——既然如此,为什么不直接让 AI 从头重写呢?

这就是核心矛盾:AI 理解存量代码的成本,接近甚至超过了重写这些代码的成本。

第二部分:全新代码的“无主之地”

2.1 为什么 AI 适合从 0 到 1?

当代码库还是空白时,情况完全不同:

  1. 没有历史包袱:AI 的所有决策都是基于“当前最优”

  2. 认知基础一致:AI 的理想模型就是代码的现实

  3. 人机协作清晰:人类负责“做什么”(需求),AI 负责“怎么做”(实现)

在全新项目中,AI 不需要理解任何历史决策,它只需要:

  • 理解当前的需求

  • 运用最佳实践

  • 在反馈中迭代

这完美契合了 AI 的工作模式。

2.2 代码案例:AI 开发全新特性

假设我们要开发一个“用户积分系统”的全新特性。以下是理想的 AI 协作流程:

第一步:AI 生成初始方案

# AI 自动生成的设计文档(固化到 skill)
"""
# 用户积分系统设计文档

## 核心实体
- User: 用户信息
- PointsAccount: 积分账户
- PointsTransaction: 积分流水

## 业务规则
- 用户注册奖励 100 积分
- 每日签到奖励 10 积分(连续签到递增)
- 每消费 1 元获得 1 积分
- 积分有效期为 365 天

## API 设计
- POST /api/points/earn - 增加积分
- POST /api/points/redeem - 兑换积分
- GET /api/points/balance - 查询余额
"""

# AI 自动生成的代码
from datetime import datetime, timedelta
from typing import Optional
from sqlalchemy import Column, Integer, DateTime, ForeignKey
from sqlalchemy.orm import relationship

class PointsAccount(Base):
    __tablename__ = 'points_accounts'
    
    id = Column(Integer, primary_key=True)
    user_id = Column(Integer, unique=True, nullable=False)
    balance = Column(Integer, default=0)
    created_at = Column(DateTime, default=datetime.utcnow)
    updated_at = Column(DateTime, onupdate=datetime.utcnow)
    
    transactions = relationship('PointsTransaction', back_populates='account')
    
    def earn(self, amount: int, reason: str) -> 'PointsTransaction':
        """增加积分"""
        self.balance += amount
        transaction = PointsTransaction(
            account_id=self.id,
            amount=amount,
            type='earn',
            reason=reason,
            expires_at=datetime.utcnow() + timedelta(days=365)
        )
        return transaction
    
    def redeem(self, amount: int, reason: str) -> Optional['PointsTransaction']:
        """兑换积分"""
        if self.balance < amount:
            return None
        
        self.balance -= amount
        transaction = PointsTransaction(
            account_id=self.id,
            amount=-amount,
            type='redeem',
            reason=reason
        )
        return transaction

第二步:人类验证并反馈

人类开发者测试后发现:“连续签到的递增逻辑需要累加,而不是每次都重置。”

第三步:AI 自主修改

# AI 根据反馈修改代码
class PointsAccount(Base):
    # ... 原有代码 ...
    
    def check_in(self) -> 'PointsTransaction':
        """签到奖励(支持连续签到递增)"""
        # AI 自动查询最近签到记录
        last_checkin = self.transactions.filter(
            PointsTransaction.type == 'checkin',
            PointsTransaction.created_at >= datetime.utcnow() - timedelta(days=1)
        ).first()
        
        if last_checkin:
            # 连续签到,奖励递增(AI 自动实现递增逻辑)
            consecutive_days = self._get_consecutive_days()
            reward = min(10 + consecutive_days, 50)  # 上限 50
        else:
            reward = 10
        
        return self.earn(reward, '每日签到')

关键原则:人类不修改代码,只反馈需求。

这样做的好处是:

  • AI 保持对代码的“所有权”

  • 需求与实现之间的映射关系始终由 AI 维护

  • 人类只需要关注“做什么”,不需要关注“怎么做”

第三部分:从“人懂”到“机懂”的范式转变

3.1 传统开发模式 vs AI 原生开发模式

维度传统模式AI 原生模式
代码所有权人拥有代码AI 拥有代码,人拥有需求
维护方式人直接修改代码人反馈,AI 修改代码
文档更新事后补充,容易过期AI 自动维护,实时更新
Clean Code必须严格遵守AI 内部优化,人无需干预
重构成本高,需要人工分析低,AI 全局理解后自动重构

3.2 Clean Code 在 AI 时代的重新定义

Robert C. Martin 提出的 Clean Code 原则,本质上是让代码对人类友好。但在 AI 原生开发模式中,代码的主要“读者”变成了 AI 本身。

这意味着:

  • 变量命名:AI 不需要你命名成“自解释”的,它理解上下文

  • 函数长度:AI 可以轻松管理 200 行的函数,不会迷失

  • 设计模式:AI 在生成时就天然运用了合适的模式

这不是说 Clean Code 不重要,而是说它的优先级变了。 在新模式下,我们更关注:

  1. 需求表达的清晰度(人类给 AI 的反馈是否明确)

  2. 设计文档的完整性(AI 能否理解全局架构)

  3. 测试覆盖的全面性(验证 AI 的行为是否正确)

3.3 未来预言

基于以上分析,我对 AI 在软件开发中的应用做出以下预言:

AI 在存量代码中的价值会有一个明确的上限。除非重写这些代码,否则 AI 不可能真正融入存量代码的日常维护中。

对于全新项目,AI 将从第一天起就扮演“主导开发者”的角色,人类退居“产品经理+测试”的监督角色。

未来的软件开发将分化为两个世界:

  • “遗产世界”:由人类维护,AI 只充当结对编程助手(检查语法、建议优化、识别代码异味)

  • “新大陆世界”:由 AI 主导开发,人类负责需求定义和验收


第四部分:实践建议

4.1 对于存量代码

如果你必须在存量代码中使用 AI,建议将 AI 的角色限制为:

  1. 结对编程伙伴:让 AI 检查代码质量,而不是修改业务逻辑

  2. 语法和类型检查:识别潜在的类型错误和空指针

  3. 冗余检测:找出重复代码和不必要的复杂度

  4. 设计模式建议:判断是否适合引入某种设计模式

示例提示词:

不要修改业务逻辑。请分析以下代码的:
1. 潜在的 bug 和边界条件问题
2. 可以提取为公共函数的重复逻辑
3. 是否适合使用策略模式简化条件分支

4.2 对于全新代码

  1. 从一开始就让 AI 主导:从项目初始化就让 AI 生成代码

  2. 人只反馈,不修改:即使发现小问题,也让 AI 去改

  3. 固化设计文档:要求 AI 把架构决策记录在 skill 或文档中

  4. 接受“不优雅”:只要功能正确,不要纠结代码风格(AI 有自己的审美)

  5. 让 AI 修 bug:即使是生产环境的 bug,也让 AI 分析并修复

结语

AI 不是万能药,也不是洪水猛兽。它有自己的认知边界和适用场景。

存量代码承载的是历史,而 AI 不擅长理解历史。全新代码面向的是未来,而 AI 恰好是创造未来的最佳工具。

接受这个现实,调整你的开发策略,AI 才能成为真正的生产力倍增器。

不要试图让 AI 理解你的屎山——那不是它的使命。它的使命,是帮你建造下一座不需要屎山的新世界。


本文仅代表个人观点,欢迎讨论和反驳。毕竟,技术的未来从来不是预言出来的,而是实践出来的。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐