3 位 Java 冠军如何借助 GitHub Copilot 提升生产力
原题How 3 Java Champions are using GitHub Copilot for increased productivity
读前速览
3 位 Java 冠军分享了将 GitHub Copilot 用作思维碰撞伙伴和执行智能体的具体做法,重点强调设置验证关卡、定制技能、使用确定性工具,以及在委派实现工作的同时保留架构责任。
定制技能将个人和项目规范编码下来,使 AI 输出与现有代码库保持一致
Vlad Mihalcea 根据自己的 65 篇文章创建技能,让生成的文档符合他的表达风格;Patrick Baumgartner 则维护了 maintainer-audit 等技能,自动执行代码仓库标准(CI、Dependabot、CodeQL),以及用于落实验证关卡的 unlazy。技能将来之不易的经验转化为可复用、持续演进的工程知识。
验证关卡用客观证据取代「模型说做完了」
Patrick 会针对具体任务设定验证关卡:迁移幻灯片时检查视觉差异、比较 PDF 并验证动画;重构时则要求测试通过、更新文档且 TODO 数量为 0。智能体必须按照这些关卡证明任务已完成,让「完成」可验证,而不是只靠口头宣称。
确定性工具为概率性生成提供保障,从而确保大规模工作中的质量
Patrick 会循环运行质量保障工具,包括 Checkstyle、PMD 和 Spring Modulith 架构检查,流程为:修改 → 执行检查 → 查看结果 → 修复 → 重复。这能让智能体的输出符合项目标准,无须人工持续进行细枝末节的审查。
智能体工作流让开发者从敲代码转向引导、审查和架构决策
处理大型任务时,Patrick 会使用终端编码智能体;例如,他曾在旅途中用 4 小时构建了一个 Maven 插件,并完成 CI 和性能测试。需要快速进行视觉迭代时,他则使用 VS Code。他会先与智能体沟通,厘清其假设,再审查计划是否明确呈现假设、设置验证关卡、符合架构要求,并避免不必要的工作。
AI 擅长诊断横跨语言运行时、操作系统和硬件的复杂问题
Frank Delporte 将一个 Pi4J 问题交给编码智能体处理:Raspberry Pi 上第 5 个 GPIO 按钮没有反应,并提供了两个文件路径。30 分钟内,智能体就找到了根因:虚拟线程在原生 `poll()` 调用中阻塞,导致载体线程被占用;在 4 核机器上,4 个监视线程会耗尽所有载体线程,使第 5 个线程无法运行。修复方法是让阻塞调用脱离虚拟线程执行。
完整摘要
GitHub 采访了 3 位 Java 冠军——Vlad Mihalcea、Patrick Baumgartner 和 Frank Delporte,了解他们如何将 GitHub Copilot 融入生产和开源工作流。Vlad 使用定制技能模仿自己的写作风格和代码规范,并根据任务复杂度切换模型,同时将可维护性置于单纯的生成能力之上。Patrick 采用智能体工作流:先通过与智能体访谈来澄清需求,为任务设定专属验证关卡(截图、差异对比、测试),将经验整理为可复用技能(例如 maintainer-audit),并用确定性检查工具(Checkstyle、PMD、Spring Modulith)约束概率性输出。他将 AI 视为思维碰撞伙伴,而不是初级开发者,并强调「委派执行,而非责任」。Frank 则讲述了 Copilot 编码智能体如何在 30 分钟内诊断出一个隐蔽的 Pi4J 错误:在一台 4 核 Raspberry Pi 上,虚拟线程在执行原生 `poll()` 调用时占用了载体线程。这个问题原本涉及硬件、令人困惑,最终却有了清晰的根因和修复方案。3 人都强调,应提供丰富的上下文、分步执行任务,并由人类判断架构权衡。
目录 · 3 节
AI 编码工具可以快速生成代码,但速度本身并不能解决最棘手的软件工程问题。开发者仍需提供上下文、验证结果、保障可维护性,并对最终交付的内容负责。AI coding tools can generate code quickly, but speed alone does not solve the hardest software engineering problems. Developers still need to provide context, validate results, protect maintainability, and remain accountable for what ships.
为了了解经验丰富的开发者如何把握这种平衡,我们采访了三位 Java 冠军,他们使用 Java 的经验都超过十年。他们分享了在生产环境和开源项目中使用 GitHub Copilot 的具体案例,以及他们如何将 AI 生成的内容转化为可靠软件的实践方法。To learn how experienced developers strike that balance, we spoke with three Java Champions, all with over a decade of experience in using Java. They shared concrete examples of using GitHub Copilot in production and open source, along with the practices they use to turn AI-generated output into reliable software.
以下是他们与我们分享的建议。Here are the tips they shared with us.
- Hypersistence 创始人、《高性能 Java 持久化》一书的作者 Vlad MihalceaVlad Mihalcea, founder of Hypersistence and author of the book High-Performance Java Persistence
- Patrick Baumgartner, software crafter at 42talents with 20+ years of Java experience
- Frank Delporte,Azul 高级技术撰稿人,Foojay.io 维护者,拥有 15 年以上 Java 经验Frank Delporte, senior technical writer at Azul and maintainer of Foojay.io with 15+ years of Java experience
弗拉德·米哈莱恰Vlad Mihalcea
GitHub profile: @vladmihalcea
GitHub Copilot 最近是如何帮助你的?How has GitHub Copilot helped you recently?
我一直在用它分析、设计并实现 Hypersistence Utils 和 Hypersistence Optimizer 中的各种功能。I’ve been using it to analyze, design, and implement various features in both Hypersistence Utils and Hypersistence Optimizer.
例如,我一直想开发一个 Web 应用,用来提供 Optimizer 事件历史记录,这样我们就能看到性能优化工作如何体现在应用性能上。在 AI 出现之前,我一直推迟这项任务,因为开发它可能需要好几周。但使用 Copilot 就像多了一位新团队成员,因此我用它创建了一个应用,该应用将在 Hypersistence Optimizer 的下一个版本中发布。这项任务只花了两天就完成了,而不是几周。For example, I’ve been wanting for a long time to develop a web application that provides Optimizer event history so we can see how performance improvement efforts are materializing in application performance. Before AI, I kept postponing this task because it would have taken me weeks to develop. But using Copilot is like having a new team member, so I used it to create an app that will ship in the next version of Hypersistence Optimizer. Instead of weeks, this task took just two days to implement.
你通常是怎么使用的?你是把 GitHub Copilot 当作 IDE 插件使用,还是使用 GitHub Copilot 应用?What’s your typical usage? Are you using GitHub Copilot as an IDE plugin or the GitHub Copilot app?
我在 IntelliJ IDEA 中使用 GitHub Copilot,因为在审查源代码或调试时使用起来很方便。I use GitHub Copilot in IntelliJ IDEA because it’s convenient to run while reviewing source code or during a debug session.
它作为代码助手非常实用,能帮助我加快调查和构建原型的速度,以便验证那些需要验证的功能。It’s very useful as a code assistant, and it helps me speed up both investigations and building prototypes for features that need validation.
我仍会审查 AI 生成的计划和代码,因为它们的目标是提高我的工作效率,而不是完全取代我。尽管 AI 在很多情况下都能给出正确答案,但有时它的回复仍不尽如人意,需要我介入。I still review the plans and the code that is generated by AI since their goal is to improve my productivity, not replace me entirely. While AI provides the right answer in many situations, there are still times when the response is not satisfactory and requires my intervention.
你能分享一些技巧和最佳实践吗?例如,你使用了哪些技能?Can you share some tips and best practices? For example, which skills are you using?
我创建了自己的技能,让 Copilot 生成的任何文本看起来都像是我亲手写的。I created my own skills so that whatever text Copilot generates looks like something I wrote by hand.
这项技能从我已发表的 65 篇文章中提炼出我的写作风格,因此生成的草稿读起来像我的博客,而不像语言模型写的内容。在为这个项目编写文档时,这非常有用,因为它能让 LLM 从我 12 年的博客写作中学习,并提供遵循相同原则(如表达力、可测试性和简洁性)的示例。This skill captures my voice from 65 of my published articles, so a draft comes back sounding like my blog instead of like a language model. This is really useful when generating documentation for this project, since it lets the LLM learn from 12 years of blogging and provide examples that follow the same principles, such as expressiveness, testability, and simplicity.
在我的软件工程师职业生涯中,我逐渐认识到,我们花在维护代码上的时间远多于编写代码。因此,鉴于维护和稳定性对现有产品至关重要,我培养了相关技能,帮助 AI 按照最小意外原则模仿现有的代码实践。Throughout my career as a software engineer, I’ve learned that we spend far more time on code maintenance than on creating it. Therefore, because maintenance and stability are critical for existing products, I developed skills that help AI mimic existing code practices in accordance with the principle of least astonishment.
一个建议是根据操作类型更换模型类型。对于需要深入思考的任务,我会使用支持 100 万上下文窗口的 Opus,并选择“超高”或“最高”推理强度。不过,对于生成报告、发布说明或核对文档等较简单的任务,我会使用消耗 token 更少的轻量模型。One tip is to change the model type based on the type of operation. For thorough thinking, I use Opus with the 1 million context window and Extra High or Max reasoning. However, for simpler tasks, such as generating reports, release notes, or verifying documentation, I use lighter models that consume fewer tokens.
帕特里克·鲍姆加特纳Patrick Baumgartner
GitHub profile: @patbaumgartner
你的工作涉及辅导团队。你会采用什么方法?Your work involves coaching teams. What is your approach?
我的很多工作都是在日常业务仍必须持续运转的情况下开展的。你不可能为了“转型”而让一切停摆六个月。我们通常会先携手解决眼前的问题,了解团队目前的状况,明确我们想要实现的目标,以及如何判断自己正在取得进步,然后一步一步朝着目标迈进。A lot of my work happens while the normal business still has to keep running. You cannot stop everything for six months to “transform.” We usually start by solving immediate problems together, understand where the team currently stands, define where we want to go and how we will know that we are improving, and then move there step by step.
视具体情况而定,这可能意味着软件匠艺实践,例如 TDD、重构、持续交付和 XP;使用 Spring Boot、Spring Modulith 进行架构设计和模块化;Spring Security;针对容器优化 Java 和 Spring Boot 应用;或者越来越多地涉及智能体工程。Depending on the situation, that can mean Software Craft practices such as TDD, refactoring, continuous delivery and XP; architecture and modularisation with Spring Boot, Spring Modulith; Spring Security; optimising Java and Spring Boot applications for containers; or increasingly, agentic engineering.
对我来说,重要的是我和团队一起工作。我们共同做决定。我不希望团队变得依赖我。理想情况下,过一段时间后,他们就不再需要我了,除非偶尔需要我作为切磋讨论的伙伴。The important part for me is that I work with the team. We make decisions together. I don’t want a team to become dependent on me. Ideally, after some time they no longer need me except perhaps as a sparring partner.
也许这就解释了为什么我觉得新一代 AI 工具如此有趣:我喜欢与人合作、学习、尝试新事物和解决问题。AI 为我们提供了另一种非常强大的工具,帮助我们实现这些目标。And maybe that explains why I find this new generation of AI tools so interesting: I like working with people, learning, experimenting, and solving problems. AI gives us another very powerful tool for doing exactly that.
你能分享一个最近 GitHub Copilot 帮到你的精彩故事吗?Can you share a good story about how GitHub Copilot has helped you recently?
实际上,有三个截然不同的例子改变了我对使用 GitHub Copilot 的看法。There are actually three very different examples that changed how I think about working with GitHub Copilot.
我们从第一个开始吧。Let’s start with the first one.
其中一个项目是将 15 份演示文稿中约 900 张教学幻灯片从 Reveal.js 迁移到 Marp。这些可不是简单的幻灯片。许多幻灯片包含代码、动画,甚至还有交互式示例,我可以在授课时实时修改 JavaScript。更重要的是,这些演示文稿已经经过学生的实战检验,讲解流程行之有效。哪怕丢失一小部分内容,都可能破坏我在课堂上要讲述的脉络。One was a migration of around 900 teaching slides across 15 presentations from Reveal.js to Marp. These were not simple slides. Many contain code, animations, and even interactive examples where I can change JavaScript live while teaching. More importantly, the presentations had already been battle-tested with students. The flow worked. Losing one small piece could break the story I use in the classroom.
手动完成那次迁移可能要花我一周甚至更久——说实话,我也可能干脆就不做了,因为这项工作实在太繁琐。Doing that migration manually would probably have taken me a week or more—and realistically, I might simply have avoided doing it because it was such tedious work.
使用 Copilot 时,我采用了不同的方法。我们先分析现有材料,确定目标,制定迁移计划,明确约束条件,提供示例,并界定哪些内容必须保持不变。随后,我们从整体结构上的重大改动着手,再逐步深入细节。With Copilot, I approached it differently. We first analysed the existing material, defined the target, created a migration plan, established constraints, provided examples, and defined what had to remain intact. Then we worked from the big structural changes down into the details.
真正重要的部分是验证。The really important part was verification.
我们生成了 Reveal.js 和 Marp 版本的截图,并通过目视和算法进行比较。我们还搭建了一个小型应用,让我可以将两套幻灯片并排播放,以手动检查动画效果。我们甚至比较了生成的 PDF。We generated screenshots of the Reveal.js and Marp versions and compared them visually and algorithmically. We built a small application where I could run both slide decks next to each other to verify animations manually. We even compared the generated PDFs.
这意味着代理并非只是说:“迁移完成。”我们有证据。That meant the agent did not just say, “Migration complete.” We had evidence.
整个迁移过程大约花了我八到十个小时。内容、教学意图以及每一项有实质意义的改动,仍然都由我负责。Copilot 可以自动修正错别字,但如果要改动内容、版本、日期或含义,我们就会先讨论。The entire migration took me roughly eight to ten hours. I still owned the content, the teaching intent, and every meaningful change. Copilot could fix a typo automatically, but if content, versions, dates or meaning changed, that was something we discussed.
对我而言,这次经历进一步印证了一个重要原则:可以委派执行工作,但不能转移责任。结果由我负责。For me, that experience reinforced an important principle: delegate execution, not responsibility. I own the result.
你能分享第二个示例吗?Can you share the second example?
另一个例子来自使用 Tamboui 构建终端 UI 应用。它最初在 WSL 下的 Linux 中运行得非常完美,我完全忘了有人可能会直接在 Windows CMD 或 PowerShell 中运行它。A second example came from building a terminal UI application with Tamboui. It initially worked perfectly in Linux under WSL, and I had completely forgotten that somebody might run it directly in Windows CMD or PowerShell.
然后,确实有一位真实用户这么做了。And then a real user did.
他们发现,在某些表单中,Enter 键会被直接忽略。这也是我深信的一条原则:尽早发布软件,因为你能从人们的实际使用方式中学到东西。They discovered that the Enter key was simply ignored in some forms. That is another principle I strongly believe in: ship software early, because you learn from how people actually use it.
我们使用 Copilot 将这些反馈转化为可复现的 UI 测试。在 Linux 上,Copilot 使用 tmux 操作应用程序。通过与它协作,我了解了 psmux,并能在 PowerShell 中执行类似的流程。我们复现了问题,创建了本地修复,追查发现根本问题出在 Tamboui 中,随后我提交了上游修复,并且该修复已被合并。We used Copilot to turn that feedback into reproducible UI tests. On Linux, Copilot was navigating the application with tmux. Through working with it, I learned about psmux and could execute similar flows in PowerShell. We reproduced the problem, created a local fix, traced the real problem into Tamboui, and I submitted the upstream fix, which was merged.
在这项工作中,测试描述本身变得过于庞大,超出了可用上下文的容量。因此,我请 Copilot 帮我重新设计测试的表示方式。它没有采用包含标识符、名称和重复描述的冗长表格,而是提出了一种更加简洁的箭头表示法:步骤 → 步骤 → 输入,只在关键信息必不可少时才补充说明。During this work, the test descriptions themselves became too large for the available context. So I asked Copilot to help me redesign the way the tests were represented. Instead of verbose tables containing identifiers, names and repeated descriptions, it proposed a much more compact arrow notation: step → step → input, with additional information only where it was critical.
这让我感到意外。我们并不只是用 AI 来执行信息,而是在共同探索如何表示信息,以便执行。它不必最大限度地便于人类理解,但必须在对代理高效的同时保留语义。That surprised me. We were not just using AI to execute information; we were working together on how information should be represented for execution. It did not have to be maximally human-friendly. It had to preserve the semantics while being efficient for the agent.
第三个例子怎么样?How about the third example?
第三个示例又完全不同。The third example is completely different again.
我身边有个人需要练习数学,于是我想:我们为什么不做一个小型学习应用呢?Someone close to me needed to practise mathematics, and I thought: why don’t we build a small learning app?
它涵盖了一至四年级的加法、减法、乘法、除法和有余数的除法。但我不想再做一个简单的测验应用。我与 Copilot 一起研究了间隔重复、即时反馈、自适应难度、激励机制、合作学习,以及不采用暗黑设计的游戏化等学习方法。It covers addition, subtraction, multiplication, division and division with remainder for grades one through four. But I did not want to build another simple quiz application. Together with Copilot, I researched learning approaches such as spaced repetition, immediate feedback, adaptive difficulty, motivation, cooperative learning and gamification without dark patterns.
有趣的是,在那项研究过程中,Copilot 对我最初的一个假设提出了质疑。我一开始希望这个应用能适用于世界各地的孩子。研究让我们转而关注实际的学校课程。我意识到,知识点的引入顺序、运算方式和数字范围都存在足够大的差异,因此一开始就将它做成“通用”的应用并无必要。Interestingly, during that research Copilot challenged one of my original assumptions. I initially wanted the application to be generic for children everywhere. The research led us toward looking at the actual school curriculum instead. I realised that the order in which topics are introduced, the operations and number ranges differ enough that making it “universal” immediately was unnecessary.
因此,我们首先聚焦瑞士,并据此调整了发展路径。由于瑞士是多语言国家,该应用支持德语、法语、意大利语和英语。So we focused on Switzerland first and aligned the progression accordingly. Because Switzerland is multilingual, the application is available in German, French, Italian and English.
它还支持双人合作和竞争模式;当有人答错时,应用会讲解一种解法,并通过间隔重复再次呈现类似的问题。It also has cooperative and competitive two-player modes, and when someone gets an answer wrong, the application explains one way to solve it and brings similar questions back through spaced repetition.
我特意选择了不需要后端的架构。我没有理由在服务器上收集儿童的个人数据,因此数据会保留在设备上,应用程序也可以直接托管在 GitHub Pages 上。I deliberately chose an architecture without a backend. There is no reason for me to collect children’s personal data on a server, so the data stays on the device and the application can simply be hosted on GitHub Pages.
最初只是一个小小的实验,如今朋友们已经开始使用并分享它。它意外地成了一个小产品。What started as a small experiment is now being used and shared among friends. It accidentally became a little product.
那次经历让我看到了 Copilot 的另一面:不要只用它来实现你的解决方案。开始构建之前,可以把它当作思想碰撞的伙伴,拓展并挑战解决方案的空间。That experience showed me another side of Copilot: don’t only use it to implement your solution. Use it as a sparring partner to expand and challenge the solution space before you start building.
你通常如何使用 Copilot?How do you typically use Copilot?
实际上,我已经不再使用经典的 Copilot 自动补全体验了。I actually don’t use the classic Copilot autocomplete experience anymore.
我的工作几乎已经完全转向了智能体工作流。My work has moved almost completely toward agentic workflows.
当我需要快速获得视觉反馈时,我会使用 VS Code——比如想仔细查看文档、代码、演示文稿或中间结果,并在过程中调整流程。I use VS Code when I need a tight visual feedback loop—when I want to look closely at documents, code, presentations or intermediate results and adapt the process as I go.
对于更大型、以执行为导向的任务,我经常在终端中使用编码代理。在那里,我更习惯于把一项工作交给它,让它执行,然后检查完整结果。我选择哪种界面,主要取决于我需要怎样的反馈循环。For larger execution-oriented tasks, I often work with the coding agent from the terminal. There I am more comfortable delegating a piece of work, letting it execute, and then inspecting the complete result. The interface I choose depends mostly on the feedback loop I need.
在前往 JavaLand 的途中,我还通过 GitHub 使用编码代理工作流,经历了一段令人着迷的体验。我当时刚开始探索一个想法:开发一个 Maven 插件,用来优化 Spring Boot 自动配置的加载方式。大约四个小时的旅途中,我一直用手机引导代理:给它分配任务、审查它的工作成果、思考下一步该做什么,然后发送下一条指令。I also had a fascinating experience using the coding-agent workflow through GitHub while travelling to JavaLand. I had started exploring an idea for a Maven plugin that optimises which Spring Boot auto-configurations are loaded. During roughly a four-hour journey, I was steering the agent from my phone: giving it a task, reviewing what it had done, thinking about the next step, and sending the next instruction.
等我到达时,我已经有了一个可用的 Maven 插件、一条 CI 流水线、针对示例应用的性能测试,以及能够证明优化是否确实有效的报告。By the time I arrived, I had a working Maven plugin, a CI pipeline, performance tests against a sample application, and reports that could demonstrate whether the optimisation actually worked.
那是我第一次以这种方式工作,我惊讶地发现它竟然真的行得通。我并不是想在手机上写 Java,而是在智能体执行任务的同时进行审查、做出决策并把控方向。That was the first time I had worked that way, and I was amazed that it actually worked. I wasn’t trying to write Java on my phone. I was reviewing, deciding and steering while the agent executed.
当 MCP 服务器能为我提供有用的功能或上下文时,我也会使用它们。例如,我曾使用 Context7 查阅文档、与我的 Logseq 知识库集成,也试验过 Adobe Premiere Pro 的 MCP 集成。I also use MCP servers when they give me useful capabilities or context. For example, I have used Context7 for documentation, integrations with my Logseq knowledge base, and I have experimented with an MCP integration for Adobe Premiere Pro.
但我不会仅仅因为能用 MCP 就去用它。如果有好用的 CLI,我通常更喜欢用 CLI,因为对我来说它更直接、也更快捷。But I don’t use MCP just because I can. If a good CLI exists, I often prefer the CLI because it feels more direct and faster to me.
在我的认知中,这个智能体也不是一个“初级开发者”。我更愿意把它看作一个切磋搭档。不过,和任何加入项目的人一样,它首先需要了解项目的来龙去脉。The agent is also not a “junior developer” in my mental model. I think of it much more as a sparring partner. But just like anyone joining a project, it first needs to be brought up to speed.
语境为王。Context is king.
你能分享一些技巧和最佳实践吗?Can you share some tips and best practices?
我最想建议的一点是:别再只靠一次性提示了。The biggest thing I would recommend is: stop one-shot prompting.
对于任何非简单的任务,我都希望在开始执行之前先弄清楚问题。很多时候,我会明确要求代理先向我提问。这样做是为了挖掘仍未明说的假设和期望。For anything non-trivial, I want to understand the problem before execution starts. Quite often I explicitly ask the agent to interview me first. The purpose of that interview is to uncover assumptions and expectations that are still implicit.
一个优秀的智能体可以极快地执行错误的想法,但这并不意味着绕远路的代价更低。A good agent can execute the wrong idea incredibly quickly. That does not make the detour cheaper.
我在开发 Spring Boot 自动配置优化器时亲身经历了这一点。最初,我想同时支持 Spring Boot 3.5 和 4.x。由于两者在架构上存在差异,我们分别实现了两种方案。后来我意识到,自己已经不再需要支持 3.5,而移除这部分代码却很费劲。I experienced this myself while working on my Spring Boot auto-configuration optimiser. Initially I wanted to support both Spring Boot 3.5 and 4.x. There were architectural differences, so we implemented both approaches. Later I realised I no longer needed the 3.5 path and removing it was painful.
教训很简单:绕远路代价高昂。加速之前,先把需求弄清楚。The lesson was simple: detours are expensive. Get the requirements right before you accelerate.
一旦意图明确,我就需要一份计划。审阅计划时,有四点对我尤其重要:假设是否清晰可见,是否定义了验证关卡,方案是否符合架构,以及是否避免了不必要的工作?Once the intent is clear, I want a plan. When I review that plan, four things matter especially to me: are assumptions visible, are verification gates defined, does the approach fit the architecture, and does it avoid unnecessary work?
第二项原则是定义特定于任务的验证门槛。The second principle is to define task-specific verification gates.
“完成”不应意味着模型说自己已经完成。“Done” should not mean that the model says it is done.
对于一次重构,验收条件可能包括测试通过、证明所有预期文件都已处理、更新文档,并确保没有遗留 TODO。对于幻灯片迁移,验收条件则包括截图、视觉差异对比、动画、PDF 输出和内容完整性。For a refactoring, the gates might include passing tests, proving that all intended files were handled, updating documentation and leaving no TODOs behind. For the slide migration, the gates included screenshots, visual diffs, animations, PDF output and content completeness.
门槛取决于任务,但原则始终不变:智能体应能够提供证据,证明工作符合完成标准。The gates depend on the task. The principle does not: the agent should be able to provide evidence that the work satisfies the definition of done.
我最近发现了一个名为 unlazy 的技能,它遵循类似的理念:设置明确的关卡,逐一认真完成,并证明这些关卡都已完成,而不是走捷径。I recently came across a skill called unlazy that follows a similar idea: create explicit gates, work through them deliberately, and prove that they have been completed rather than taking shortcuts.
第三个原则是将你的经验教训转化为可复用的技能。The third principle is to turn your lessons into reusable skills.
我已经开始编写和维护自己的 Agent Skills。每当我从一次执行中有所收获——比如智能体误解了某项约定、遗漏了一项有用的检查,或者我找到了更好的任务处理方式——我就会更新相应的技能。I have started writing and maintaining my own Agent Skills. When I learn something from an execution—perhaps the agent misunderstood a convention, a useful check was missing, or I found a better way to approach a task—I update the skill.
下次我执行那项任务时,经验教训已经在那里了。The next time I perform that task, the lesson is already there.
一个例子是我称为 maintainer-audit 的技能,它的灵感来自开放的智能体技能社区中的工作。我会在自己的各个代码仓库中使用它。它会检查并在适当情况下修复我认为一个有人维护的项目应具备的事项:仓库文档、CI 流水线、Dependabot 配置、CodeQL、一致的清理措施以及其他项目标准。One example is a skill I call maintainer-audit, inspired by work in the open agent skills community. I use it across my own repositories. It checks and, where appropriate, fixes the things I expect a maintained project to have: repository documentation, CI pipelines, Dependabot configuration, CodeQL, consistent cleanup and other project standards.
目标不是再生成一份供我阅读的审计报告,而是自动让代码库恢复到我期望的基线状态。这样一来,我的项目会更加一致,也更易于维护。The goal is not to generate another audit report for me to read. It brings the repository back toward the baseline I want automatically. That makes my projects more consistent and easier to maintain.
我认为,这些技能是鲜活的工程知识,而非静态提示词。I think of these skills as living engineering knowledge rather than static prompts.
第四项原则是在概率模型周围配备确定性工程工具。The fourth principle is to put deterministic engineering tools around the probabilistic model.
我有自己的质量测试框架,可以封装 Checkstyle、PMD 和 Spring Modulith 架构检查等工具,并生成一份智能体可以使用的汇总报告。我可以通过钩子运行它,让智能体反复迭代:I have my own quality harness that wraps tools such as Checkstyle, PMD and Spring Modulith architecture checks and produces a consolidated report that the agent can consume. I can run that from hooks and let the agent iterate:
修改 → 执行检查 → 查看检查结果 → 修复 → 再次执行。change → execute checks → read findings → fix → execute again.
它会持续进行,直到没有剩余的发现为止。It continues until there are no findings left.
这并不意味着我不再审视软件。我仍然会运行应用程序、与它交互,并判断它的行为和外观是否符合预期。有时我会刻意逐个功能地实现,因为这样反馈循环会紧密得多。That does not mean I stop looking at the software. I still run the application, interact with it and decide whether it behaves and looks the way I expect. Sometimes I deliberately implement feature by feature because the feedback loop is much tighter.
我发现,因为“AI 能做到”就一次性要求它完成所有事情,通常不是个好主意。庞大而笼统的规格说明会催生庞大而笼统的实现,而事后清理这些实现,可能比一开始就正确地分步构建更难。I learned that asking for everything at once because “the AI can do it” is usually a bad idea. Large, generic specifications create large, generic implementations—and cleaning them up afterwards can be harder than building smaller increments correctly.
更广泛地说,我认为我们开发者需要更多地讨论如何使用这些工具。分享奏效的尝试,也分享没能奏效的尝试。彼此借鉴思路,并结合自己的实际情况加以调整,而不是寻找一种放之四海而皆准的 AI 开发流程。More broadly, I think we developers need to talk much more about how we use these tools. Share the experiments that worked. Share the ones that didn’t. Borrow ideas from each other and adapt them to your own context instead of looking for one universal AI development process.
这也是我喜欢把 AI 视为切磋伙伴的原因。周五晚上,当我想尝试点新东西,却找不到人一起搭档时,我突然就有了一个人——或者说某种东西——可以和我探讨想法、一起审视方案,或者充当一个非常聪明的“橡皮鸭”。That is also why I like the idea of AI as a sparring partner. On a Friday night, when I want to experiment with something and no human pair is available, I suddenly have somebody—or something—I can challenge an idea with, review an approach with, or use as a very sophisticated rubber duck.
但我仍会把这些想法带回现实中的人群中。人类反馈、对产品的理解以及现实环境仍然至关重要。But I still take those ideas back to real people. Human feedback, product understanding and real-world context remain essential.
你认为人工智能正在如何改变我们的职业?How do you think AI is changing our profession?
我认为,软件工程专业的学生不应把成为只会产出代码的机器作为主要目标。他们需要成为出色的问题解决者。他们需要了解用户和利益相关者,发现需求背后的真正问题,质疑各种假设,理解产品和市场,权衡架构方案,进行批判性思考,以有条理的方式开展工作,并将有用的解决方案应用到不同的情境中。I don’t think software engineering students should primarily aspire to become code-producing machines. They need to become strong problem solvers. They need to understand users and stakeholders, discover the real problem behind a requirement, challenge assumptions, understand products and markets, make architectural trade-offs, think critically, work in a structured way and transfer useful solutions from one context into another.
这个模型极其擅长生成各种可能性并付诸行动。但作为人类,我通常更了解实际情况,包括那些从未有人记录下来的事情。The model is extraordinarily good at generating possibilities and executing things. But as a human, I usually know much more of the actual context—including the things nobody ever documented.
所以我想继续主导解决方案的设计,同时让智能体承担更多执行工作。So I want to remain in charge of shaping the solution and let the agent take over more of the execution.
从这个意义上说,我认为 AI 正在让软件工程重新回归工程本质。In that sense, I think AI is putting the engineering back into software engineering.
而我喜欢这一点。And I like that.
弗兰克·德尔波特Frank Delporte
GitHub profile: @FDelporte
你是如何进入科技行业的?How did you get started in tech?
我从11岁拥有一台 Commodore 64 起,就一直对电脑着迷。离开学校后,我曾绕道做过一阵视频制作和电视相关工作,但后来又回到了编程,因为那些视频需要刻录到 DVD 上,而且那时也正是最早一批网站出现的时候……是的,我就是那么老 ;-).I’ve been fascinated by computers since I got a Commodore 64 when I was 11. Took some side steps into video production and television work after school but turned back into coding as that video needed to be put on DVD and the very first websites… Yes, I’m that old ;-).
GitHub Copilot 最近是如何帮助你的?How has GitHub Copilot helped you recently?
它是评估拉取请求和调查错误报告的绝佳助手。It’s a perfect companion to evaluate pull requests and investigate bug reports.
一个引人注目的案例是 Pi4J 库,它让你能够构建 Java 应用程序,与 Raspberry Pi 上的电子元件进行交互。2026 年 2 月,我们发布了 V4,其中包含一个使用 Foreign Function & Memory API 的新插件。发布前我们进行了全面测试,但发布后不久,仍有人报告说,使用 5 个输入按钮时,实际效果并不符合预期。按下前四个已配置按钮中的任意一个,都会像预期那样触发代码执行;但按下第五个按钮时则毫无反应。One remarkable story is about the Pi4J library that lets you build Java applications to interact with electronic components on the Raspberry Pi. In February 2026, we released V4 which has a new plugin using the Foreign Function & Memory API. We tested it thoroughly before releasing, but still, shortly after the release someone reported that using 5 input buttons doesn’t work as expected. Pushing one of the first four configured buttons triggers a code execution as expected, while nothing happens with the fifth button.
这就是那种你最不想收到的报告。表面上看一切正常:没有异常,没有日志警告,第五个按钮却毫无反应。更糟的是,换回较旧的 gpiod 插件后,同一套硬件和同一个应用程序都运行正常。也就是说,问题出在我们新的 FFM 代码中。它构建在 Linux 内核的 GPIO 字符设备之上,并通过原生调用与其通信。这可不是代码库中那种能让你轻松找到答案的地方。This is the kind of report you don’t want to get. Nothing was visibly broken. No exception, no warning in the logs, the fifth button was simply silent. And it got worse: with the older gpiod plugin, the exact same hardware and the exact same application, worked fine. So the problem was in our new FFM code, which sits on top of the Linux kernel’s GPIO character device and talks to it through native calls. That is not the part of the codebase where you expect to find a quick answer.
于是我把这个问题分配给 Copilot 编码代理,并给了它两个文件路径作为起点:provider 类和 FFMDigitalInput。大约半小时后,一个拉取请求就提交了,附带的解释着实出乎我的意料。So I assigned the issue to the Copilot coding agent and gave it two file paths as a starting point, the provider class and FFMDigitalInput. About half an hour later there was a pull request, with an explanation I really did not expect.
每个输入都会运行一个事件监听器,在原生 `poll()` 调用中阻塞,等待内核报告其 GPIO 引脚上的变化。这些监听器运行在虚拟线程中。而在原生调用中阻塞的虚拟线程无法从其载体线程上卸载。它会在整个调用期间一直占据该载体线程。Raspberry Pi 4 有四个核心,因此虚拟线程调度器有四个载体线程。注册四个输入后,四个载体线程就都永远停在 `poll()` 中。第五个监听器虽然创建了,却永远不会被调度。这正是当时报告的那个 bug。问题不是“事件时灵时不灵”,而是“第五个完全不起作用”。Each input runs an event watcher that blocks in a native poll() call, waiting for the kernel to report a change on its GPIO line. Those watchers ran in virtual threads. And a virtual thread that blocks inside a native call cannot be unmounted from its carrier thread. It stays pinned there for the whole duration of the call. A Raspberry Pi 4 has four cores, so the virtual thread scheduler has four carrier threads. Register four inputs, and all four carriers are parked in poll() forever. The fifth watcher is created, but is never scheduled. That is exactly the bug that was reported. Not “events are flaky”, but “the fifth one does nothing.”
我最喜欢的不是代码差异,而是之后评审中的那段对话。我留言请 Copilot 更详细地解释这一点:What I liked most was not the diff, it was the conversation that followed in the review. I left a comment asking Copilot to explain this in more detail:
我以为虚拟线程的目标恰恰就是摆脱平台线程数量的限制?那么,在树莓派这样的四核处理器上,四个虚拟线程阻塞了四个线程,这怎么会成为问题呢?I thought the goal of virtual threads was exactly to step away from the platform thread limit? So how is this a problem that four virtual threads block the four threads on a four-core processor like the Raspberry Pi?
查看拉取请求以了解完整对话。Copilot 成功将使用配备四个 CPU 核心的 Raspberry Pi 与报告的问题联系起来,并提出了一个简单的修复方案,以及调查过程中发现的一些额外改进。Check the pull request for the full conversation. Copilot was able to link the use of the Raspberry Pi which has four CPU cores with the reported problem. It was able to propose a simple fix for the problem, plus some extra improvements it found during its investigation.
你能分享一些技巧和最佳实践吗?Can you share some tips and best practices?
- 告诉它该去哪里找:针对 Pi4J issue #622,我添加了两个文件路径。这只需要花一点点功夫,却能省去在大型代码库中大量搜索的时间。即使你完全不知道 bug 出在哪里,通常也会对它所在的代码区域有些头绪。把这些线索告诉工具,它就不必检查整个代码库。Tell it where to look: For the Pi4J issue #622, I added two file paths. That is a tiny bit of effort that removes a huge amount of searching in a large codebase. You usually have a hunch about the neighbourhood even when you have no idea about the bug. Give it to the tool so it doesn’t need to investigate the complete code.
- 要求提供证据和测试:“添加一个单元测试来验证这项更改”是我最近经常提出的要求。嗯,曾经经常提出,因为这现在已经成了我的指令文件中的一条规则。这样也能避免误诊的情况,因为如果诊断有误,这个测试在旧代码上就不会失败。Ask for proof and tests: “Add a unit test to validate the change” is something I ask a lot these days. Well, asked, because it has now become a rule in my instructions file. It also prevents cases where the diagnosis was wrong, because the test won’t fail on the old code.
- 询问原因:如果你不理解某项修复,就直说并提出问题。解释本身也是交付成果,应该补充到项目文档或工单、拉取请求中。这样能让日后阅读这些信息的每个人都从中受益。例如,这也引发了 Pi4J 团队对原生调用中虚拟线程固定问题的进一步探讨。Ask why: If you don’t understand a fix, say so and ask. The explanation is a deliverable too and should be added into your project documentation or inside the ticket or pull request. It teaches everyone who reads the info later. For example, this also triggered more questions within the Pi4J team about virtual thread pinning on native calls.
- 掌控全局:Pi4J 中所有这些拉取请求在合并前都经过了维护者的审查和批准。这是本项目中最有效的协作模式:由智能代理负责调查,人类则对最终发布的内容负责。不过,在我的其他项目中,我也总会审查工具生成的代码。我始终希望代码易于阅读和维护。工具经常会创建重复的方法,或者重新实现其他地方已经提供、原本应该整合起来的功能。这是你的责任。如今,借助 AI 辅助编程,你可以做得非常快,但这也意味着你可能很快就会把代码弄得一团糟。别这么做,要让代码保持整洁、易于管理。将来如果同事或未来的你需要排查 bug 或改进代码,他们会感谢你的。Stay in control: All of these pull requests in Pi4J were reviewed and approved by maintainers before they went in. That’s the model that works best in this project: the agent does the investigation, the humans stay responsible for what ships. But also for my other projects I always do a review of the code that was generated by the tool. I always want to keep code readable and maintainable. Too often, a tool creates duplicate methods or recreates something which is already available in another place and should be combined. That’s your responsibility. You can go very fast these days with AI-assisted coding, which also means you can very fast create a mess. Don’t do that, keep your code manageable, your colleagues and future-self will thank you if they have to investigate bugs or make improvements later.