引言

最近,我一直在观察团队中使用 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 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐