最近在用各种LLM的时候,我注意到一个很有意思的现象:每次用代码的形式来描述需求,AI给出的结果都比我用自然语言描述准确很多。
这让我开始怀疑:AI是不是天生就更”懂”代码?
带着这个疑问,我查了不少资料,发现这个观察还真不是我的错觉。数据和研究都证实了代码确实在某些方面比自然语言更适合跟AI交流。但事情没这么简单——最佳实践其实是混合使用,该用代码的时候用代码,该用自然语言的时候用自然语言。
我的直觉主要基于三个发现:代码没有歧义性、逻辑结构更清晰、而且AI直接读代码比读文档靠谱。但深入研究后发现,现实比这个简单的总结复杂得多。
代码prompt确实有优势,但不是万能的
1. 歧义问题确实存在
这个体验大家应该都有。我说”写个函数处理用户数据”,AI经常不知道我要干啥。但如果我这样写:
def process_user_data(users: List[User]) -> List[ProcessedUser]:
# TODO: 实现数据处理逻辑
pass
AI马上就明白了——输入什么、输出什么、函数签名是啥,一目了然。
据研究,自然语言prompt的幻觉率能到27%,用代码结构化的方式确实能降低不少。这个我感同身受。
2. 逻辑约束是个好东西
代码天生有逻辑约束,AI生成的时候语法必须对,逻辑路径必须说得通。就像给AI套了个”逻辑紧身衣”,胡说八道的机会少了很多。
我现在经常用伪代码来描述需求,效果比纯文字好太多:
// 我想要的逻辑:
if (user.hasPermission("admin")) {
// 显示管理界面
} else if (user.hasPermission("editor")) {
// 显示编辑界面
} else {
// 显示只读界面
}
比说”根据用户权限显示不同界面”清楚多了。
3. AI可能确实更擅长读代码
这点挺有意思的。有研究发现,给AI看错误的文档会明显影响它理解代码,但如果压根没文档,AI照样能看懂代码。
想想也合理——代码本身就是最精确的”规格说明书”,比任何文档都准确。
但纯代码也有很多坑
说实话,光用代码也不是万能的:
表达能力有限
有些需求用代码根本没法说清楚。比如”我希望这个界面看起来更现代”,你怎么用代码表达?或者”优化下这个算法性能,但别影响可读性”,这种权衡关系代码表达不出来。
缺少业务上下文
代码往往缺少背景信息。当我写:
def calculate_discount(price, user_type):
pass
AI不知道这是电商系统、SaaS订阅、还是游戏内购,不同场景的折扣逻辑天差地别。
学习门槛
让非程序员用代码prompt?基本不可能。就算是程序员,碰到不熟悉的领域(比如复杂的SQL优化、正则表达式)也不如直接说话来得快。
行业其实都在搞混合模式
我发现最成功的做法都是混合的。Google的”Chain of Code”方法就很典型:
- 先用自然语言描述问题
- 再用代码结构化解决方案
- 最后用自然语言解释结果
这种方法比单纯用代码或自然语言都要好12%。
GitHub Copilot也是这个思路,不是让你完全用代码prompt,而是:
- 注释 + 代码一起用
- 函数签名 + 文字描述结合
- 代码示例 + 文字说明配合
数据显示用Copilot的开发者效率提升55%,但要11周才能完全适应这种混合交互。看来学习新的交互方式也需要时间。
我的使用心得:什么时候用什么
通过这段时间的摸索,我总结了一些经验:
代码prompt适合的场景:
- API调用和数据结构:直接给schema,比描述半天有用
- 算法逻辑:伪代码表达条件判断、循环处理特别清楚
- 配置文件:JSON、YAML格式比长篇大论管用
- Debug问题:贴代码 + 错误信息,比描述现象靠谱
自然语言适合的场景:
- 需求探索:要什么功能、为什么需要、用户怎么用
- 创意设计:界面风格、用户体验、产品方向
- 学习理解:问原理、要解释、学最佳实践
- 权衡决策:技术选型、架构考虑、性能vs可维护性
我常用的混合模式:
// 我想做个缓存系统
// 场景:高并发读写,要保证数据一致性,支持过期
interface CacheService {
get(key: string): Promise<any>;
set(key: string, value: any, ttl?: number): Promise<void>;
delete(key: string): Promise<void>;
}
// 请实现这个接口,重点考虑:
// 1. 缓存穿透怎么办?
// 2. 内存满了怎么淘汰?
// 3. 分布式场景下怎么保证一致性?
这种方式把代码的精确性和自然语言的表达力结合起来,效果最好。
一些实用建议
基于这些发现,我整理了几个日常使用的小技巧:
1. 分层思考
- 做什么(What):用自然语言说清楚目标
- 怎么做(How):用代码表达具体实现
- 为什么(Why):用自然语言解释设计考虑
2. 别指望一次搞定
不要想着一个prompt解决所有问题。我一般是先用自然语言说个大概,AI给出方案后,再用代码细化,最后用自然语言补充上下文。
3. 具体例子很有用
AI特别喜欢看输入输出示例:
// 输入数据:
const users = [
{name: "张三", age: 25, department: "研发"},
{name: "李四", age: 30, department: "产品"}
];
// 期望结果:
const grouped = {
"研发": [{name: "张三", age: 25}],
"产品": [{name: "李四", age: 30}]
};
// 帮我实现这个groupBy函数
4. 约束条件要说清楚
技术约束用代码,业务约束用自然语言:
// 技术要求:必须是纯函数,不能改原数组
function sortUsers(users: User[]): User[]
// 业务规则:VIP用户排前面,同级别按注册时间排
// 性能要求:10万+数据,100ms内响应
更深层的思考:我们正在见证编程的演进
写到这里,我突然想到一个更有意思的话题。
你有没有注意过,编程语言这几十年来一直在朝一个方向发展:越来越接近自然语言。
从汇编的机器指令,到C的结构化语法,再到Python的”可执行伪代码”,每一代语言都在努力缩小人类思维和机器执行之间的距离。Go语言甚至直接用类似英语的语法:if err != nil
、for range
这些。
这个趋势其实从来没停过。每当我们觉得某种语言已经够”人性化”了,新技术总会推着我们向更高的抽象层次走。
现在的AI编程工具,其实就是这个演进路线的自然延续。
Prompt Engineering:一种新的”编程语言”?
最近我越来越觉得,prompt engineering已经不只是个技巧,而是一种新的编程范式了。
你看,有效的prompt其实有很明确的结构:
- 角色定义:”作为一个有10年经验的Python开发者…”
- 任务描述:具体要做什么
- 上下文信息:相关的技术栈、约束条件
- 输出格式:期望的代码风格
这不就是一种”编程语言”吗?只是它的语法更接近人话,执行环境是大语言模型而不是CPU。
GitHub现在41%的代码都是AI生成的,这说明我们已经在用这种”新语言”了,只是可能自己还没意识到。
程序员的角色在变化
那人类程序员还有什么价值?我觉得价值在重新定位。
以前我们是实现者,现在更像是设计师和协调者:
- 系统架构:复杂系统的整体设计还是需要人来做
- 业务理解:把现实世界的需求转化成技术方案
- 质量把控:AI生成的代码总得有人review吧
- 技术决策:在多个方案中做权衡选择
- 团队协作:跨部门沟通这些AI暂时还搞不定
微软的数据显示,有经验的开发者用AI工具时生产力提升更大。这说明专业知识和AI能力结合会产生乘数效应——我们不是被AI替代,而是被AI”放大”了。我的实际体感也是如此,作为一个有经验的开发,你的确需要些时间上手AI工具,但是一旦上手,你其实更累了:代码飞速输出,你的大脑需要比之前更快地思考、判断和权衡。
可能的未来:更接近自然语言的”编程”
想象一下,如果这个趋势继续下去会怎样?
也许未来我们真的会有一种”Prompt Language”——它有结构化的语法,但完全用自然语言表达;它有明确的语义,但不需要记住奇怪的符号。
现在的编程教育也在变。CS2023课程标准首次把AI作为核心内容,重点不再是语法记忆,而是:
- 怎么跟AI有效协作
- 系统设计和架构思维
- 问题分析和解决能力
- 沟通表达和批判思维
说白了,未来的程序员更像建筑师——不用自己搬砖,但得会设计蓝图。
我的一点感想
回头看这70年的编程语言演进,其实就是一个不断抽象化的过程。每次都有人担心新技术会让旧技能过时,但历史告诉我们,新的抽象层次不是替代,而是叠加。
汇编语言到现在还在用,C语言依然重要,只是它们的应用场景更专业了。
现在的AI编程工具也一样。它们不会让传统编程技能过时,反而让这些技能变得更珍贵——因为只有懂底层原理的人,才能有效地指导和审查AI的输出。
我们正站在一个转折点:编程正在从专业技能变成表达思维的方式。当自然语言可以直接转化为代码时,编程的门槛会大幅降低,但对编程思维的要求可能更高。
这不是终点,是新的开始。在这个新时代,最重要的技能不是写代码,而是设计未来。