标题说用了三年,其实是夸张的说法。GitHub Copilot预览版2021年6月才发布,我申请了预览资格,用了三个月,但用得很频繁,几乎每天写代码都在用,感触很深,感觉像用了三年一样。
Copilot是GitHub和OpenAI合作开发的AI编程助手,基于OpenAI的Codex模型(GPT-3的代码专用版本),能根据注释和上下文自动补全代码。它支持多种编程语言和框架,能写函数、写测试、写正则表达式、写SQL,甚至能写整个类。
刚拿到Copilot预览资格的时候,我很兴奋,觉得AI编程的时代来了,以后写代码只要写注释就行。用了三个月之后,我的看法变得更理性了:Copilot确实能提高编程效率,但它不是万能的,它有很多局限,使用不当反而会降低效率,甚至引入bug。
本文分享我使用Copilot三个月的经验和感悟,聊聊它的优点和局限,哪些场景下它特别好用,哪些场景下它不好用,以及使用时需要注意的问题。希望能给打算用Copilot或者正在用Copilot的朋友一些参考。
先说明一下:我主要用Copilot写JavaScript/TypeScript、Python、PHP、SQL,偶尔写一些Shell脚本和配置文件。不同语言的体验可能有差异,但核心的使用感受是类似的。
一、Copilot是什么,它是怎么工作的
在说使用感受之前,先简单介绍一下Copilot是什么,它是怎么工作的。
Copilot是什么。
Copilot是GitHub和OpenAI合作开发的AI编程助手,2021年6月发布技术预览版。它是一个编辑器插件,目前支持VS Code,以后可能会支持更多编辑器。
Copilot能做什么:
- 根据注释生成代码:你写一段注释描述你想要的功能,Copilot会自动生成对应的代码。
- 自动补全代码:你写了函数名或者前几行代码,Copilot会自动补全后面的代码。
- 生成测试代码:你写了一个函数,Copilot能自动生成对应的单元测试。
- 生成正则表达式:你描述一下想要匹配的模式,Copilot能生成对应的正则表达式。
- 生成SQL查询:你描述一下想要查询的数据,Copilot能生成对应的SQL语句。
- 翻译代码:你用一种语言写了代码,Copilot能翻译成另一种语言。
- 解释代码:你选中一段代码,Copilot能解释这段代码是做什么的。
Copilot是怎么工作的。
Copilot基于OpenAI的Codex模型,这是一个在大量代码上训练的大语言模型。它的工作原理简单来说就是:根据你当前文件的上下文(包括注释、代码、函数名、变量名等),预测接下来最可能出现的代码。
Copilot会考虑的上下文:
- 当前文件的所有内容(注释、代码、导入等)
- 当前打开的其他文件的内容
- 函数名、变量名、类名等标识符
- 注释和文档字符串
- 代码的缩进和结构
当你打字的时候,Copilot会实时分析上下文,生成代码建议,显示为灰色的文字。你按Tab键接受建议,按Esc键拒绝建议,也可以用快捷键查看更多建议。
Copilot不是简单的代码搜索和复制,它是真正理解了代码的语义,能生成全新的代码。当然,它生成的代码可能和训练数据中的某些代码相似,这也是Copilot争议比较大的地方(版权问题)。
Copilot和传统的代码补全有什么区别。
很多人会问,Copilot和VS Code自带的IntelliSense或者其他代码补全工具有什么区别?
区别很大:
- 传统补全是基于语法和规则的:IntelliSense之类的补全工具,是基于语言的语法规则和当前文件的符号表来补全的,它只能补全已经存在的变量名、函数名、关键字等,不能生成全新的代码。
- Copilot是基于AI的:Copilot是基于大语言模型的,它能理解代码的语义,根据注释和上下文生成全新的代码,包括函数体、整个类、测试代码等。
- Copilot能理解自然语言:你可以用自然语言写注释描述需求,Copilot能理解你的需求并生成对应的代码,这是传统补全工具做不到的。
- Copilot能生成更长的代码:传统补全只能补全一个标识符或者一行代码,Copilot能生成多行代码,甚至整个函数或类。
简单来说,传统补全是"帮你打字",Copilot是"帮你写代码"。
二、哪些场景下Copilot特别好用
用了三个月,我发现Copilot在某些场景下特别好用,能大大提高编程效率。
1. 写样板代码(Boilerplate)。
这是Copilot最好用的场景,没有之一。编程中有很多样板代码,比如:
- 定义一个类,包含构造函数、getter、setter
- 写一个CRUD的API接口
- 写一个数据库模型
- 写一个表单验证逻辑
- 写一个配置文件
- 写一个单元测试的基本结构
这些样板代码逻辑不复杂,但写起来很繁琐,而且容易出错。用Copilot,你只要写一个注释或者函数名,它就能自动生成完整的样板代码,大大节省时间。
比如,我写注释"// 创建一个用户类,包含id、name、email字段,以及对应的getter和setter",Copilot就能自动生成完整的User类,包括构造函数、各个字段的getter和setter,甚至还会加上类型提示和注释。
再比如,我写"// 写一个函数,验证邮箱格式是否正确",Copilot就能生成一个完整的邮箱验证函数,包括正则表达式和各种边界情况的处理。
写样板代码的时候,Copilot的准确率非常高,几乎不需要修改就能直接用。这是我用得最多、最满意的场景。
2. 写正则表达式。
正则表达式是很多程序员的噩梦,语法复杂,容易写错,而且写好了之后过一段时间自己都看不懂。Copilot在写正则表达式方面特别好用。
你只要用自然语言描述一下想要匹配的模式,Copilot就能生成对应的正则表达式,甚至还会加上注释解释每一部分的含义。
比如:
- "匹配一个11位的手机号码,以1开头" → 生成
^1\d{10}$ - "匹配一个邮箱地址" → 生成一个完整的邮箱正则
- "匹配一个URL,以http或https开头" → 生成对应的URL正则
- "匹配一个日期,格式为YYYY-MM-DD" → 生成
^\d{4}-\d{2}-\d{2}$
而且,Copilot生成的正则表达式质量很高,考虑了很多边界情况,比我自己写的更严谨。
当然,正则表达式生成之后,我还是会测试一下,确保它能正确匹配我想要的内容,不会误匹配。但总体来说,Copilot写正则的能力非常强,帮我省了很多时间。
3. 写单元测试。
写单元测试是很多程序员不喜欢但又必须做的事情。Copilot在写单元测试方面也很好用。
你写好一个函数之后,Copilot能自动识别函数的功能,生成对应的单元测试,包括正常情况、边界情况、异常情况的测试用例。
比如,我写了一个函数function add(int $a, int $b): int,Copilot就能自动生成测试用例:
- 测试两个正数相加
- 测试两个负数相加
- 测试一正一负相加
- 测试零的情况
- 测试大数的情况
而且,Copilot能识别你用的测试框架(PHPUnit、Jest、pytest等),生成对应框架的测试代码。
当然,Copilot生成的测试用例不一定覆盖了所有情况,有时候会漏掉一些边界情况,有时候会生成一些没有意义的测试用例。但作为测试的初稿,它已经非常好了,你只要在它的基础上补充和修改就行,比从零开始写测试快很多。
4. 写SQL查询。
Copilot写SQL的能力也很强。你用自然语言描述一下想要查询的数据,Copilot就能生成对应的SQL语句,包括JOIN、WHERE、GROUP BY、ORDER BY等复杂的查询。
比如:
- "查询用户表中所有年龄大于18岁的用户,按年龄降序排列" → 生成对应的SELECT语句
- "查询每个用户的订单数量和总金额" → 生成带GROUP BY和聚合函数的查询
- "查询最近30天内有订单的用户" → 生成带子查询或JOIN的查询
- "更新用户表中id为1的用户的邮箱" → 生成UPDATE语句
而且,Copilot能识别你用的数据库(MySQL、PostgreSQL、SQLite等),生成对应数据库的SQL语法。
对于复杂的SQL查询,Copilot生成的代码可能需要修改,但作为初稿已经非常好了,能帮你节省很多时间。
5. 调用不熟悉的API或库。
这是Copilot另一个特别好用的场景。当你用一个不熟悉的API或者库的时候,你不需要去查文档,只要写一个注释或者函数名,Copilot就能告诉你怎么用。
比如,我第一次用某个日期处理库的时候,不太清楚它的API,我写了注释"// 计算两个日期之间相差多少天",Copilot就自动生成了调用这个库的代码,包括导入、创建日期对象、调用方法等。
再比如,我不太记得某个HTTP客户端库的API,我写了"// 发送一个GET请求,带查询参数",Copilot就生成了对应的代码。
当然,Copilot生成的代码不一定完全正确,有时候API的版本不同,用法可能有差异。但它能给你一个很好的起点,你不用从零开始查文档,只要在它的基础上调整就行,大大提高了学习新库的效率。
6. 翻译代码。
Copilot还能翻译代码,把一种语言的代码翻译成另一种语言。比如,把Python代码翻译成JavaScript,把JavaScript代码翻译成TypeScript,把PHP代码翻译成Python等。
这个功能在你需要把旧代码迁移到新语言,或者你熟悉一种语言但需要用另一种语言实现某个功能的时候特别有用。
比如,我有一段Python的数据处理代码,需要用JavaScript重写,我把Python代码贴进去,写个注释"// 把上面的Python代码翻译成JavaScript",Copilot就能生成对应的JavaScript代码,而且翻译得很准确,逻辑和原来的Python代码一致。
当然,翻译代码的时候,不同语言的特性和最佳实践不同,Copilot生成的代码可能不是目标语言的最佳写法,需要你根据目标语言的习惯做一些调整。但作为初稿,它已经非常好了。
三、哪些场景下Copilot不好用
说了这么多好用的场景,再说说Copilot不好用的场景,这些场景下用Copilot反而会降低效率。
1. 复杂的业务逻辑。
Copilot在写简单的、常见的代码时很准确,但在写复杂的业务逻辑时,准确率会大大下降。
比如,你要写一个复杂的价格计算逻辑,涉及到会员等级、优惠券、满减、折扣、税费等多种因素,Copilot生成的代码很可能是错的,或者只考虑了部分情况,漏掉了很多边界条件。
因为复杂的业务逻辑是和你的具体业务相关的,Copilot没有你的业务上下文,它只能根据通用的模式生成代码,不可能完全理解你的业务规则。
这种场景下,用Copilot生成的代码可能需要大量修改,甚至比你自己写还慢。而且,Copilot生成的代码看起来很合理,但可能隐藏着逻辑错误,如果你不仔细检查,很容易引入bug。
所以,复杂的业务逻辑,我建议还是自己写,或者用Copilot生成一些辅助的小函数,核心逻辑自己把控。
2. 最新的技术或框架。
Copilot的训练数据有截止日期,对于最新发布的技术或框架,它可能不了解,生成的代码可能是旧版本的,甚至是错的。
比如,某个框架刚发布了新版本,API有很大变化,Copilot的训练数据里可能还是旧版本的用法,它生成的代码可能用的是已经废弃的API。
再比如,某个很新的库,用的人还不多,训练数据里没有足够的代码,Copilot生成的代码可能不准确。
这种场景下,用Copilot要特别小心,生成的代码一定要对照官方文档检查,确保用的是最新的API。如果是很新的技术,建议还是直接看官方文档,不要依赖Copilot。
3. 安全相关的代码。
安全相关的代码(比如身份验证、授权、加密、输入验证、SQL注入防护等),Copilot生成的代码可能存在安全漏洞。
因为Copilot是在大量公开代码上训练的,而公开代码里有很多是有安全漏洞的。Copilot可能会学到这些有漏洞的写法,生成不安全的代码。
比如,Copilot可能会生成直接拼接SQL的代码(有SQL注入风险),或者生成用MD5加密密码的代码(不安全),或者生成没有做输入验证的代码。
安全相关的代码,我强烈建议不要依赖Copilot,一定要自己写,并且按照安全最佳实践来写,写完之后还要做安全审查。如果用Copilot生成了安全相关的代码,一定要仔细检查,确保没有安全漏洞。
4. 需要深度思考的算法问题。
对于需要深度思考的算法问题(比如动态规划、图算法、复杂的数据结构等),Copilot的表现也不好。
简单的算法(比如排序、查找、二分查找等),Copilot能生成正确的代码。但复杂的算法,Copilot生成的代码可能逻辑不对,或者效率很低,或者根本不能运行。
因为算法问题需要深度思考和推理,Copilot虽然能生成看起来合理的代码,但它并不真正理解算法的逻辑,只是在模仿训练数据中的模式。对于不常见的算法问题,它很可能生成错误的代码。
这种场景下,我建议还是自己思考和实现算法,Copilot可以作为参考,但不能依赖。如果你用Copilot生成了算法代码,一定要写测试用例充分测试,确保逻辑正确。
5. 调试和排错。
Copilot在调试和排错方面的能力也有限。当你的代码有bug的时候,Copilot可能能帮你找到一些简单的语法错误或者明显的逻辑错误,但对于复杂的、隐蔽的bug,它很难帮你找到。
而且,Copilot可能会"好心办坏事",给你错误的修复建议,让你越调越乱。
调试和排错还是要靠自己,通过阅读代码、打日志、用调试器、写测试等方式来定位和修复bug。Copilot可以辅助,但不能替代你的思考。
四、使用Copilot的感悟和道理
用了三个月Copilot,我有很多感悟,也明白了一些道理。
1. Copilot不是要取代程序员,而是要改变程序员的工作方式。
很多人担心AI编程会取代程序员,我用了三个月之后,觉得这种担心是多余的。至少在可预见的未来,Copilot不会取代程序员,它只会改变程序员的工作方式。
以前,程序员的工作是"写代码",大部分时间花在打字上。有了Copilot之后,打字的时间大大减少了,程序员的工作变成了"描述需求、审查代码、调试优化"。
你需要做的是:
- 想清楚你要实现什么功能
- 用清晰的注释和代码结构描述你的需求
- 审查Copilot生成的代码,确保它是正确的、安全的、高效的
- 调试和优化代码,解决Copilot没有处理好的问题
这其实对程序员的要求更高了,因为你需要能判断Copilot生成的代码对不对,需要能发现隐藏的bug,需要能优化代码的性能和可读性。如果你自己都不懂,你就无法判断Copilot生成的代码是对是错,很容易被它带偏。
所以,Copilot不是要取代程序员,而是要把程序员从繁琐的打字中解放出来,让我们更专注于思考和设计。它是一个强大的工具,但工具终究是工具,需要人来驾驭。
2. 写好注释很重要,注释就是你的需求文档。
用了Copilot之后,我最大的感受之一是:写好注释太重要了。
Copilot是根据你的注释和上下文来生成代码的,你的注释写得越清晰、越详细,Copilot生成的代码就越准确。如果你的注释写得很模糊,Copilot就只能猜,生成的代码很可能不是你想要的。
比如,你写"// 处理用户输入",这个注释太模糊了,Copilot不知道你要怎么处理,生成的代码可能和你想要的完全不同。但如果你写"// 验证用户输入的邮箱格式是否正确,如果不正确返回错误信息,如果正确则返回true",Copilot就能生成准确的代码。
所以,用Copilot的时候,要把注释当成需求文档来写,清晰、详细、无歧义地描述你想要的功能。这其实是一个好习惯,即使不用Copilot,写好注释也能提高代码的可读性和可维护性。
而且,注释不仅是给Copilot看的,也是给你自己和其他开发者看的。清晰的注释能让代码更容易理解,更容易维护。
3. 永远不要盲目相信Copilot生成的代码。
这是最重要的一点:永远不要盲目相信Copilot生成的代码,一定要仔细审查。
Copilot生成的代码看起来很合理,变量名、函数名、注释都很规范,很容易让人觉得它是对的。但实际上,它可能隐藏着很多问题:
- 逻辑错误:看起来合理,但实际运行结果不对
- 边界情况:没有考虑边界情况,比如空值、零、最大值等
- 安全漏洞:比如SQL注入、XSS、不安全的加密等
- 性能问题:比如O(n²)的算法,或者内存泄漏
- 过时的API:用了已经废弃的API
- 版权问题:生成的代码可能和某些开源代码高度相似
我自己就遇到过好几次,Copilot生成的代码看起来很对,但运行起来结果不对,仔细一看才发现逻辑有问题。还有一次,Copilot生成了一个用MD5加密密码的函数,这显然是不安全的,我赶紧改成了bcrypt。
所以,Copilot生成的代码,一定要像审查别人的代码一样仔细审查,确保它是正确的、安全的、高效的。不要因为它是AI生成的就放松警惕,AI也会犯错,而且它的错误可能更隐蔽。
4. Copilot能提高效率,但也能降低效率,关键看你怎么用。
Copilot能提高编程效率,这是毫无疑问的。但如果用得不好,它反而会降低效率。
什么时候会降低效率?
- 盲目相信Copilot生成的代码,不审查,结果引入了bug,调试花了更多时间
- 用Copilot生成你不理解的代码,出了问题不知道怎么修
- 过度依赖Copilot,自己不思考,结果代码质量很差
- 用Copilot生成复杂的业务逻辑,结果生成的代码不对,改的时间比自己写还长
- 一直在调整注释让Copilot生成正确的代码,反而不如自己直接写
怎么用才能提高效率?
- 用Copilot写样板代码、正则、测试、SQL等它擅长的东西
- 复杂的业务逻辑和算法自己写,Copilot只做辅助
- 生成的代码一定要审查,确保正确、安全、高效
- 用Copilot学习新的API和库,但要对照文档验证
- 把Copilot当成一个聪明的助手,而不是一个能替你思考的人
关键是要了解Copilot的能力边界,知道它擅长什么,不擅长什么,在它擅长的地方用它,在它不擅长的地方自己来。这样才能真正提高效率。
5. 编程的核心是思考,不是打字。
用了Copilot之后,我越来越觉得,编程的核心是思考,不是打字。
以前,我们花很多时间打字,写代码的过程就是思考的过程。有了Copilot之后,打字的时间大大减少了,你需要在写代码之前就想清楚:
- 这个功能要实现什么?
- 输入是什么?输出是什么?
- 有哪些边界情况?
- 用什么数据结构和算法?
- 代码的结构怎么设计?
想清楚了这些,你再写注释,Copilot就能帮你把代码打出来。如果你没想清楚,Copilot生成的代码肯定也是混乱的。
所以,Copilot逼着我们先思考再动手,这其实是一个好习惯。编程的核心是解决问题的思路和设计,而不是打字的速度。Copilot帮我们解决了打字的问题,让我们能更专注于思考和设计。
这也意味着,只会打字、不会思考的"码农"会越来越没有竞争力。真正有价值的是能思考、能设计、能解决复杂问题的程序员。Copilot会成为每个程序员的标配工具,就像现在的IDE和代码补全一样,但它不能替代你的思考。
五、使用Copilot的建议和最佳实践
最后,总结一些使用Copilot的建议和最佳实践,希望能帮你更好地使用这个工具。
1. 写清晰、详细的注释。
注释是Copilot理解你需求的主要方式,注释写得越清晰、越详细,生成的代码就越准确。把注释当成需求文档来写,描述清楚功能、输入、输出、边界情况等。
2. 提供足够的上下文。
Copilot是根据当前文件的上下文来生成代码的,上下文越丰富,生成的代码就越准确。在写新代码之前,先把相关的导入、类型定义、函数签名等写好,Copilot就能更好地理解你的意图。
3. 分步骤生成,不要一次生成太多。
不要指望Copilot一次生成整个功能的代码,那样准确率会很低。建议分步骤生成,先生成函数签名和基本结构,再生成函数体的各个部分,每一步都审查和调整,这样准确率更高。
4. 生成的代码一定要审查和测试。
这是最重要的建议。Copilot生成的代码一定要仔细审查,检查逻辑是否正确、是否有安全漏洞、性能是否达标、是否符合代码规范。审查完之后,一定要写测试用例测试,确保代码能正确运行。
5. 复杂的逻辑自己写,Copilot只做辅助。
复杂的业务逻辑、算法、安全相关的代码,建议自己写,Copilot只用来生成一些辅助的小函数或者样板代码。不要在核心逻辑上依赖Copilot,否则出了问题你可能都不知道怎么修。
6. 用Copilot学习,但不要停止自己学习。
Copilot是一个很好的学习工具,你可以通过它学习新的API、新的库、新的写法。但不要因为有了Copilot就停止自己学习,你需要理解Copilot生成的代码,知道它为什么这么写,有什么优缺点。只有理解了,你才能判断它对不对,才能在它的基础上优化。
7. 注意版权和许可证问题。
Copilot生成的代码可能和某些开源代码高度相似,这可能会涉及版权和许可证问题。如果你的项目是商业项目,要特别注意这一点,避免因为Copilot生成的代码引入版权纠纷。建议对Copilot生成的代码做代码相似度检查,确保没有侵权。
8. 保护敏感信息,不要把机密代码给Copilot。
Copilot会把你的代码发送到服务器进行处理,所以不要把包含敏感信息(比如密码、密钥、机密业务逻辑)的代码给Copilot处理。如果你的公司有代码保密规定,要先确认是否允许使用Copilot。
六、写在最后
用了三个月GitHub Copilot,我对AI辅助编程有了全新的认识。它不是要取代程序员,而是要改变程序员的工作方式,把我们从繁琐的打字中解放出来,让我们更专注于思考和设计。
Copilot在写样板代码、正则表达式、单元测试、SQL查询、调用不熟悉的API等场景下特别好用,能大大提高编程效率。但在复杂的业务逻辑、最新的技术、安全相关的代码、需要深度思考的算法等场景下,它的表现不好,甚至会帮倒忙。
使用Copilot最重要的原则是:永远不要盲目相信它生成的代码,一定要仔细审查和测试。它是一个强大的工具,但工具终究是工具,需要人来驾驭。
编程的核心是思考,不是打字。Copilot帮我们解决了打字的问题,让我们能更专注于思考和设计。这对程序员的要求更高了,只会打字、不会思考的"码农"会越来越没有竞争力,真正有价值的是能思考、能设计、能解决复杂问题的程序员。
AI编程的时代才刚刚开始,Copilot只是一个开始。未来,AI会越来越强大,能帮我们做越来越多的事情。但无论AI怎么发展,它都只是工具,真正的创造力和思考力还是在人身上。我们要学会使用这些工具,让它们帮我们更好地工作,而不是被它们取代。
最后用一句话结束本文:"AI不会取代程序员,但会用AI的程序员会取代不会用AI的程序员。"愿我们都能学会使用AI工具,成为更高效、更有价值的程序员。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录