在 Cursor、Copilot 和 AI Agent 席卷工作流的今天,代码的属性发生了本质变化。过去,代码是给人读的指令集;现在,代码是 AI 推理的语料库

人类阅读代码可以靠“悟性”和项目背景知识,但 AI 主要依靠其内部的注意力机制(Attention Mechanism)和概率预测。这意味着,如果你的代码逻辑是隐晦、跳跃或高度动态的,AI 就会因为找不到足够的“锚点”而产生幻觉。AI 友好编程的核心,就是通过确定性的结构,降低 AI 预测的熵值。

1. 显式类型:AI 推理的“导航灯塔”

很多开发者认为 Python 或 JS 的类型标注只是为了报错检查。但在 AI 视角下,类型是搜索空间的过滤器

案例对比

  • 反面教材(隐式类型):
    def update_user(user_data):
        # AI 看到这里时,不知道 user_data 的结构
        # 它必须向上检索 5 个文件找到调用处,或者干脆猜测
        db.save(user_data['id'], user_data['meta']) 
    
  • AI 友好实践(显式类型):
    class UserProfile(TypedDict):
        id: str
        meta: dict
        last_login: datetime
    
    def update_user(user_data: UserProfile):
        # 类型标签瞬间锁定了 AI 的推理边界
        # 即使 db.save 的实现在另一个文件,AI 也能确信 user_data 拥有哪些 Key
    

逻辑剖析

LLM 的工作方式是逐 Token 预测。当存在 UserProfile 定义时,模型内部的注意力权重会瞬间向该类型关联的属性倾斜。这不仅减少了生成的错误,更重要的是,它显著提升了 Zero-shot(零样本生成) 的准确率。类型声明就像是在迷雾中为 AI 点亮了导航灯塔。


2. 局部性原则:针对 RAG 检索的物理优化

目前的 AI 编程助手(如 Cursor)底层高度依赖 RAG(检索增强生成)。它会根据你当前的操作,计算代码片段的向量相似度,然后把“它认为相关”的代码塞进 Context Window。

为什么过度解耦可能是 AI 的毒药?

在传统工程中,我们推崇“一个函数只做一件事”,导致逻辑被拆分到 services/, utils/, models/ 等无数微小文件中。

但对 RAG 来说,如果逻辑跨度太大,它检索出的代码块可能是碎裂的:

  • 片段 A:函数定义。
  • 片段 B:远在另一个目录的辅助工具函数。
  • 片段 C:写在全局配置文件里的类型定义。

如果这三个片段在物理距离上太远,RAG 很难一次性把它们都准确地抓取。当 AI 拿到的信息只有“残片”时,它就会开始根据概率分布“脑补”逻辑。

工程建议:语义完备单元

适度的“聚合”优于极度的“解耦”。在 AI 时代,我们应该遵循“语义完备单元”原则:将强相关的类型定义、核心逻辑和辅助函数保持在同一个文件或相邻的物理空间。这确保了 AI 在“低头看一眼”时,能看到逻辑的全貌。


3. 声明式编程:缩短 AI 的推理路径

AI 擅长总结模式,不擅长模拟复杂的内存状态转换。

代码演示

  • 反面教材(命令式):
    let activeUsers = [];
    for (let i = 0; i < users.length; i++) {
        if (users[i].status === 'active' && users[i].lastLogin > 30) {
            activeUsers.push(users[i].name.toUpperCase());
        }
    }
    
  • AI 友好实践(声明式):
    const activeUsers = users
        .filter(u => u.isActive)
        .filter(u => u.hasRecentLogin)
        .map(u => u.getUpperCaseName());
    

深度解析

在命令式代码中,AI 必须像 CPU 一样在脑子里维护变量 i 的变化、数组长度和中间状态。一旦逻辑嵌套过深,AI 的注意力就会分散。

而声明式代码(如 Stream API 或 SQL)直接表达了**“意图”**。AI 能够瞬间匹配到它在训练数据中见过数亿次的“过滤-映射”模式。越接近自然语言逻辑的代码,AI 续写的成功率就越高。


4. 断言式错误处理:给 AI Agent 留下一条“求救绳”

当你使用 AI Agent(如 Auto-GPT 或 Cursor Agent)自动修复 Bug 时,错误日志就是它的 Prompt

论证

如果你只抛出一个 Error: 500,AI 只能盲目重试。但如果你使用断言式编程(Assertive Programming)

assert config.db_url.startswith("postgres://"), f"Expected PostgreSQL URL, got {config.db_url}"

当 AI 运行代码并看到这个错误时,它不需要人类介入,就能根据错误信息(“噢,我把 URL 格式写错了”)自动修正代码。好的代码应该具备“自解释的崩溃能力”,这直接决定了 AI 自动化运维的成功率。


💡 总结:从“砖瓦匠”到“规格制定者”

AI 友好编程要求我们完成一次心态转换:你不是在亲手拧紧每一个螺丝,而是在编写一份**“无需额外解释就能被准确理解的代码规格书”**。

当我们抱怨“AI 生成的代码全是 Bug”时,也许可以反思一下:我们是否给这个拥有全球知识库的助手,提供了一份逻辑碎片化、充满了隐式依赖、且毫无导航线索的破烂草稿?


Making code reasonable, not just runnable.