Github Copilot 研发效能提升实战指南

文章目录

  • [GitHub Copilot 提效不靠补全:把意图、上下文和验收写清楚](#GitHub Copilot 提效不靠补全:把意图、上下文和验收写清楚)
    • [1. 拒绝许愿式编程](#1. 拒绝许愿式编程)
    • [2. 它看不见你脑子里的架构](#2. 它看不见你脑子里的架构)
    • [3. 反复要说的话,写进仓库](#3. 反复要说的话,写进仓库)
    • [4. 真值钱的一步:先补测试](#4. 真值钱的一步:先补测试)
    • [5. 别的活我怎么用](#5. 别的活我怎么用)
    • [6. 有几类事情我直接不让它碰](#6. 有几类事情我直接不让它碰)
    • [7. 你要是只改一件事](#7. 你要是只改一件事)

GitHub Copilot 提效不靠补全:把意图、上下文和验收写清楚

面向:Copilot 已经开通了,补全能用,但时好时坏,想知道怎样少踩坑的人。

我见过最常见的用法,是在 Chat 里丢一句:「写个订单创建,VIP 要打折,信用卡走风控。」几分钟后你拿到能编译的 if-else。库存预占没有事务,风控是 pass,折扣写死 0.9。演示好看,提测难看。

我现在基本不这么用。不是 Copilot 突然变聪明了,是我把活拆开了:先让它围着一段真实代码补测试,人看着跑;绿了再允许它碰实现。它还是会写错断言。我是靠 pytest 红了才知道,不是靠它自觉。

下面拿一个短函数走一遍。日期解析这种东西不性感,但前后端都在调、没测试、没人敢改------Copilot 在这种地方才值钱。订单状态机、从 Figma 出组件那些,我放到后面几句带过,单独开十章没有意义。


1. 拒绝许愿式编程

这段是我从老项目里摘出来改过名字的。前端传字符串,后端收成闭区间再查库。空值用当年首末日。没有测试。

python 复制代码
from datetime import date, datetime

def parse_date_range(start, end, year):
    # 空值用当年首末日;非法格式抛 ValueError;start > end 也抛
    if not start:
        start_d = date(year, 1, 1)
    else:
        start_d = datetime.strptime(start, "%Y-%m-%d").date()
    if not end:
        end_d = date(year, 12, 31)
    else:
        end_d = datetime.strptime(end, "%Y-%m-%d").date()
    if start_d > end_d:
        raise ValueError("start after end")
    return start_d, end_d

你要是跟它说「给这个方法补全单测,覆盖各种情况」,它会吐一串 test_parse_date_range_1。日期是魔法数字,更讨厌的是:查库用的是闭区间(BETWEEN 含当天),它经常按程序员习惯写成左闭右开。你不跑测试,肉眼不一定看得出来。账单少算一天,要到对账才炸。

我在 VS Code Chat 里会先选中函数,再把调用方文件挂上,提示词写成这样:

text 复制代码
#selection #file:app/api/orders.py
为 parse_date_range 生成 pytest。

返回闭区间,end 当天算进去。
start 或 end 为空,用 year 的首日 / 末日。
非法日期或 start > end 抛 ValueError。
不要测 strptime 怎么实现的。
用例名写场景,不要 test_1、test_2。
生成完不要改生产代码。

啰嗦一点没关系。少写那句「不要改生产代码」,它有时会顺手「优化」函数,测试倒是好写了,语义已经偏了。

入口我也分着用,懒得记成方法论,就是少踩过几次:

敲代码时的灰色补全,让它补当前文件下一行就行。DTO 字段、样板 if,我接受率很高。跨文件的设计别指望它从补全里长出来。

要解释、要测试、要对着一块选区提问,开 Chat。/tests/explain/fix 我常用。别在这儿让它「把整条下单链路写完并保存」。

Agent 能改多文件,我只在已经有测试护着的时候开。无保护的大重构、删列、改主键,我自己来。它改得又快又勤,回滚成本在你这边。

还有个很多人不知道的细节:仓库里的 .github/copilot-instructions.md 只作用于 Chat,行内补全不读它。别指望写了这份文件,敲代码时的幽灵字就会变听话。


2. 它看不见你脑子里的架构

Copilot 不理解「我们是微服务」。它看见的是当前文件、你的选区、用 # 挂上去的文件、这轮 Chat 里说过的话,以及------如果有的话------那份 copilot-instructions.md

所以我花在「把提示词写得更文学」上的时间不多,花在「把无关文件拿掉」上的时间更多。对话脏了就 /clear。它开始 import 一个仓库里不存在的包,或者突然换成隔壁模块的命名,多半是上下文圈歪了。接着跟它说「再优化一下」没有用,它会在错误上下文里继续优化。

前后端一起写的时候也是这个道理。前端要写 fetchUserDetail,别默认它记得 Java DTO 里哪个字段可空。把 OpenAPI 或那份 DTO #file 挂上,写明「字段名和空值和后端一致,不要发明字段」。没有 schema 还夸「写一端知另一端」,就是碰运气。运气好的时候你以为 Copilot 很强,运气不好就是联调现场对字段。

遗留代码看不懂,我会选中,然后:

text 复制代码
/explain
只讲控制流和会抛哪些异常。别评价该不该重构。

后半句是因为我懒得看它抒情。解释是只读的,没打算改就别把 Agent 打开。


3. 反复要说的话,写进仓库

团队里如果每回都要贴「我们用 pytest、不要吞异常」,说明这些话该进文件。我自己的版本很短。再长它会开始选择性失聪。

markdown 复制代码
# .github/copilot-instructions.md

本仓库 Python 3.11,测试用 pytest。

生成代码:公共函数带类型;错误往上抛,不要吞;不要新增 requirements 里没有的包。

生成测试:用例名写场景;断言行为,别断言私有实现;不准为了把测试变绿去改生产代码。

缩进、import 顺序、行宽这种事,交给 ruff / prettier 和 CI。Copilot 管格式,又慢又不稳,Code Review 还会吵回大括号。命名和「这个包不许用」,instructions 里写一眼,提交前人再扫一眼。业务对不对,只看测试和你自己。

/doc 我偶尔用来起注释草稿。它能把参数类型翻译成人话,翻译不了「为什么空值要用当年 1 月 1 日」------那是产品规则。代码改了边界,注释改那一行就行。不要搞「用 AI 把文档整体重生」这种活动,重生完往往和实现各说各话。


4. 真值钱的一步:先补测试

parse_date_range 短、有边界、现网在用。给这种函数补测试,是我用 Copilot 最不亏的场景。我负责把行为说清楚,它负责铺一堆用例,我负责删。

选中函数,/tests,把上面那些约束贴进去。出来的东西通常掺三股:

有用的:空值、正常闭区间、start > end、非法字符串。这些留。

多余的:专门测 strptime 格式串。你以后要是换解析方式,这批测试会无意义地红。删。

错的:闭区间被写成半开。下面这种我见过不止一次,直接扔掉。

python 复制代码
def test_end_is_exclusive():
    # 它把查库的闭区间,猜成了编程里的 [start, end)
    start_d, end_d = parse_date_range("2026-01-01", "2026-01-31", 2026)
    assert end_d == date(2026, 1, 30)  # 错:31 号当天应包含

留下来的最好能当说明书读:

python 复制代码
import pytest
from datetime import date
from billing.dates import parse_date_range

def test_empty_start_uses_first_day_of_year():
    start_d, end_d = parse_date_range(None, "2026-06-01", 2026)
    assert start_d == date(2026, 1, 1)
    assert end_d == date(2026, 6, 1)

def test_empty_end_uses_last_day_of_year():
    start_d, end_d = parse_date_range("2026-02-01", None, 2026)
    assert end_d == date(2026, 12, 31)

def test_invalid_date_raises():
    with pytest.raises(ValueError):
        parse_date_range("2026-13-01", "2026-01-31", 2026)

def test_start_after_end_raises():
    with pytest.raises(ValueError):
        parse_date_range("2026-05-02", "2026-05-01", 2026)

覆盖率以你本机 pytest --cov 为准。没跑出来的数,别写进周报。我见过有人把 Copilot 聊天框里的「已覆盖主要分支」直接贴上去,那种数字没有意义。

测试红了,VS Code 会建议 Fix Test Failure,Chat 里也有 /fixTestFailure。这里我被坑过,所以写得难听一点:

它会改生产代码,去迁就一条错误断言。

test_end_is_exclusive 要是还在,它完全可能把结束日减一天。测试绿了,查询少算一天,账是错的。所以我会写死:

text 复制代码
/fixTestFailure
只许改测试。闭区间语义不准动。
测试和注释打架,删测试,别改函数。

改完你自己再跑一遍。绿只说明断言被满足了,不说明断言是对的。这个区别,用 Copilot 之前其实也成立,只是它把「写错断言」的速度提高了一个数量级。

有测试护着,我才让它动实现。比如把 year 改成仅关键字参数、补返回类型------这种机械活它干得比我快。提示词里还是要带刹车:

text 复制代码
#file:billing/dates.py #file:tests/test_dates.py
把 parse_date_range 的 year 改为仅关键字参数,补上返回类型。
不要改日期怎么算。现有测试失败就回退,不许删用例。

订单、库存、风控那种「复杂业务」,我也不再让它一次性生成。骨架可以要。它在副作用位置填 pass,我就当这行不存在,自己接事务和远程调用。它要是生成一堆 if user_level == "VIP" 还美其名曰策略模式------那不是策略模式,是还没拆的条件。真要拆,接口和测试你先写,实现类再交给它填。


5. 别的活我怎么用

/fix 对付编译器和 linter 已经指着鼻子骂的问题,很合适。资源没关、明显 NPE,它补 try-with-resources 之类的,我接受得很快。并发安全、事务边界、权限,它没有运行现场,我只当线索,不直接合并。

慢 SQL 可以问,但要把建表、现有索引、EXPLAIN 一起贴进去。没有执行计划,它给的「给 order_date 加个复合索引」跟猜的差不多。生产上有数据倾斜的表,我被这种建议浪费过下午。

学新框架时,我会把正在看的官方文档片段,加上仓库里一份旧写法,让它按这个仓库的目录和依赖翻译,别另起一套包名。对照着看能学到东西。把它的输出当成「最新最佳实践」,你吃到的可能只是训练截止日期以前的博客。

前端也一样。有组件库,让它在库里拼。拿张截图就想出生产代码,DOM 能跑,和现有设计 token、无障碍、状态管理通常对不上。当草稿可以,当 PR 不行。

这些没有新原则。输入写得像你在给实习生交代任务,输出才值得审。输入像许愿,输出就像演示视频。


6. 有几类事情我直接不让它碰

.env、token、内网地址,不要贴进 Chat。灰色补全有时会从旁边文件续出「很像密钥」的字符串。看到就按泄露处理:轮换。不要只是把那一行删掉然后心安。

删列、改主键、不可逆的数据修复,生成脚本可以,跑之前的备份和核对是人的。它不会替你留后路。

「把这个包改成策略模式,顺便把查询都优化了」这种句子,我会拆开,或者干脆不发。它会同时改结构、改语义、改测试,最后你不知道绿的是行为还是它把测试改顺了。先锁行为,再动结构,索引是最后才谈的事。

说到底没那么玄:不变量你定,草稿它写,进 git 的那一版你负责。线上炸了,用户不会去找 Copilot。


7. 你要是只改一件事

去找一个没有测试、但每周都有人改的纯函数。/tests,删掉闭区间写反、测实现细节的那些,自己跑绿,然后再考虑让它改实现。

copilot-instructions.md 可以下周再写,四十行以内就够。团队提示词库里的「写个 XX」可以删了------需求四行都说不清,发给 Copilot 也是浪费一次上下文。

相关推荐
Ray Wang2 小时前
Agent学习
ai编程
Token掘金室2 小时前
Aider配置自定义API教程
ai
AlfredZhao3 小时前
GitHub 克隆他人私有仓库:从授权到下载
github
智能制造产品经理代码提升4 小时前
Windows Git 多 GitHub 账号切换(GCM 管理凭据,不覆盖原有账号)
github
程序员老刘4 小时前
Android Studio Quail 4发布,看日志我以为谷歌放弃Flutter了
flutter·android studio·ai编程
VIP_CQCRE4 小时前
在 Visual Studio 里接入 Ace Data Cloud:用 OpenAI 兼容接口提升 AI 编程效率
openai·api·ai编程·visual studio·ace data cloud
Young丶4 小时前
讲透 Claude Code 系列 (四):Claude Skills 完全指南:可复用的“专业能力包”从入门到精通
人工智能·ai·ai编程·ai coding
Wang's Blog5 小时前
Java框架快速入门: Spring Security+OAuth2之核心角色与授权流程
java·spring·github
dong_junshuai5 小时前
每天一个开源项目#100 OpenCodeReview:2.6万星的低噪声AI审查器
程序员·开源·github