让AI替代50%的工作 ——解决程序员最痛苦的难题:命名
chinese AI
本文以及本专栏正在参加豆包 Marscode 专栏征文活动,如何喜欢欢迎投票支持,这将对我们意义非凡
投票链接
以下实战案例均使用豆包 MarsCode AI 工具,欢迎大家尝试!
在结束了原理篇的理论性讨论后,这一章我们正式进入技巧篇,也是本小册中内容最丰富的一部分。之所以这样安排,是因为我认为 prompt 的相关理论固然重要,但即使大家理解了理论,可能也不容易在实战中熟练应用。
因此,在这个新篇章中,我们将以原理篇的内容为基石,讨论在实战场景下如何使用 AI 提升工作效率。我们会通过大量案例和对技巧的详细讲解,帮助大家更深入地理解 AI 辅助编程,从而提高应用技巧的熟练度。
在国内网络环境下,使用国产工具的速度和合规性更有保障,所以后续的 AI 工具我们会以国产的 MarsCode 为例。它目前完全免费使用,支持云 IDE、VSCode 插件、JetBrains 插件,其中云 IDE 支持在线部署。在实战篇中,我们会利用免费部署的功能,方便地把我们制作的 AI Chat 展示给朋友看。
安装方式见:https://www.marscode.cn/
本小册中的所有 prompt 技巧对所有 AI 都是通用的,所以读者也可以使用任意自己喜欢的 AI 工具。
变量命名
变量命名看似基础,但实际上,写过较多代码的程序员都知道,这是最折磨人的地方。有多少重构 PR 只是为了修改一个让自己看着别扭的变量名。
Programs are meant to be read by humans and only incidentally for computers to execute.
可以翻译为:“代码是写给人读的,只是偶尔用来运行”,所以可读性是代码非常重要的部分,而很多时候给代码取一个合适的名字是非常难的。
在这种场景下,我们需要做的是:
-
描述函数的作用和变量的目的:描述你想要实现的函数的功能,变量要记录什么、目的是什么,这些信息可以让 AI 理解你的需求。
-
充分利用 AI 的计算能力:AI 的劳动是极度廉价的,所以要灵活利用“给我十个,再给我十个,再给我十个”这样的 prompt,不要节约 AI 的算力,而是利用它廉价的思考,来激发自己的创造。
-
要求解释命名理由:灵活应用“并解释你这样命名的理由”,来帮助你理解 AI 如此命名的目的,从而选出最符合自己想法的命名。
-
提供足够的上下文:如果你是在已有的代码中进行重构,那么充足的代码上下文要比你的描述更有价值。例如:“我要对这段代码进行重构,将 a 变量和 b 变量合并成一个新的变量,给我十个合适的新变量命名方式”。
-
善于选择合适的命名:人类想出十个有意义的命名是非常难的,但很擅长从十个答案中选出合适的一个。
例如,我们在工程中,有一个电商平台的订单系统,现在需要写一个新函数来计算用户购买商品时的总价格。这个总价格需要考虑商品的单价、购买数量以及折扣。
function calculate(userCart: { price: number; quantity: number }[], discount: number): number {
let total = 0;
for (const item of userCart) {
total += item.price * item.quantity;
}
total = total - discount;
return total;
}
那我们就可以这么写 prompt:
帮我给这个函数命名,这个函数是计算用户购买商品的总价:
function calculate(userCart: { price: number, quantity: number }[], discount: number): number {
let total = 0;
for (const item of userCart) {
total += item.price * item.quantity;
}
total = total - discount;
return total;
}
给我十个命名,并解释你命名的理由
你可以看到,这个 prompt 中的语言非常随意,并不像网络上精选 prompt 那样格式化和整洁。因为我们这本小册讲的是如何在实战中应用 AI,虽然经过打磨后的高质量 prompt 能够提高 AI 的回复质量,但在实战中我们并没有时间和必要去打磨 prompt,只要提供有效的信息和清晰的指令,能够让 AI 返回有价值的信息即可。
然后我们就可以从 MarsCode AI 得到结果:
然后,我们可以进一步进行 prompt:
对你提出的十个命名进行评价,给出你认为最优秀的选择,并解释理由
AI 回复:
在您提供的十个命名中,我认为最优秀的选择是 calculateTotalPriceWithDiscount。这个命名清晰地描述了函数的功能,即计算用户购物车中商品的总价,并考虑折扣。它遵循了函数命名的最佳实践,具有以下优点:
1. **描述性强**:通过名称就能清楚地知道函数的用途。
2. **简洁明了**:命名简洁,易于理解和记忆。
3. **动词+名词结构**:使用了动词“calculate”和名词“TotalPriceWithDiscount”,这种结构在函数命名中很常见,易于理解。
4. **避免缩写**:命名中没有使用缩写,使得名称更加直观。
5. **上下文相关**:名称与函数所在的上下文(如购物车、折扣等)相关,有助于提高代码的可读性和可维护性。
相比之下,其他命名虽然也能表达函数的功能,但可能不够简洁或直观。例如,getDiscountedTotal 和 applyDiscountToCartTotal 虽然也描述了函数的功能,但不如 calculateTotalPriceWithDiscount 那么直接和简洁。而 calculateDiscountedAmount 和 getFinalPriceAfterDiscount 则更侧重于函数的输出,而不是整个计算过程。
因此,我认为 calculateTotalPriceWithDiscount 是最优秀的命名选择。
虽然可能有些读者更喜欢较短的命名(你可以把你的喜好添加到 prompt 中),但一般在工程协作中,有代码提示的存在,长命名并不会影响效率,反而能让程序员从命名就知道函数或变量的意义和效果。
例如,有些人可能会把这个函数命名为 calculateTotalPrice
或者 calculatePrice
,那未来使用和修改这个函数的程序员(可能就是你自己),就会疑惑这个函数是否考虑了折扣的存在?那就可能需要查看函数的签名或者实现,降低效率。
这其实涉及到 AI 的另一个应用。工程最佳实践有非常多细节,小到代码和文件的命名习惯,大到架构的设计规范,很多初看觉得麻烦,但都是无数前人踩过的坑。对于初级程序员,这些细节需要在大量的工程实践中慢慢积累,也没有完整的教程和列表来入门,这正是 AI 擅长的点。
例如你可以问 AI:“为什么你给的命名都是这么长?我是一个刚入门的程序员,一般函数命名的最佳实践有哪些原则?”
AI 回复:
这么详细的讲解对新人是非常友好的,可以快速学到很多工程中默认的知识和规则。这些技巧我们也会在后续章节中逐步涉及。
优化整体命名
虽然听起来命名是非常基础的事情,但这是代码质量很重要的部分,也是体现程序员编程经验的重要方面。
对于新人来说,过去的编码经验大多是自己写代码,合作场景较少,所以很多代码都是命名越简单越好,只要自己读懂就行。在这种情况下,需要的不仅仅是命名建议,更是命名的相关知识和引导,帮助自己理解什么是好的命名并建立起良好的命名习惯。
例如,我们现在有一个按照自己习惯实现的函数:
function calcProj(tDone: number, tTotal: number): string {
let perc = (tDone / tTotal) * 100;
if (perc === 100) {
return "Project complete";
} else {
return "Project progress: " + perc.toFixed(2) + "%";
}
}
然后我们 prompt AI:
这个函数是用来计算项目完成度的,帮我优化其中的命名,使其符合工程通用的命名最佳实践,并解释为什么这些命名更合适
当然,这个例子中的原始变量名过于随意。这个技巧更适合的应用场景是,在自己认真实现完函数后,让 AI 检查其中可能的优化命名方向。
即使你把 AI 优化后的函数发给 AI,让它提出优化建议,它依旧可以提供有理有据的建议。就像原理篇我们讨论的,AI 并不具备真正的智能,只是基于概率的涌现智能。
所以,我们不能完全依赖 AI。在这个场景下,我们是在 AI 的辅助下,逐步学习命名的最佳实践,进而能够分辨出 AI 输出信息的价值,取其精华。
小结
命名难题非常常见,也是困扰许多程序员的问题。
AI 因为训练数据庞大,见过足够多高质量的代码,相对人类更容易得出高质量的命名,并辅以合理的解释。
这一章通过命名这个基础问题,诠释了原理篇提到的一些理论,例如上下文、利用 AI 廉价的思考等,可以帮助大家对原理篇的理论有更深入的理解。
也欢迎大家在评论区分享自己发现的 AI 使用小技巧。