正文:

引言

在过去的几个月里,我一直在个人和专业项目中尝试使用 AI 驱动的编码工具。无论是对我还是我的软件工程师团队来说,这种体验都非常积极。

我们以更少的时间取得了更好的结果,并且在许多情况下,我们的输出质量得到了显著提高。

有趣的是,这种体验与我从一些同行软件开发人员那里收到的反馈形成对比,他们报告说 AI 工具对他们不起作用。

我现在确信,AI 辅助的软件开发有潜力将我们的技能在生产力方面提升到一个新的水平。这就是为什么我认为我们的社区应该尽早拥抱它——但像所有工具和实践一样,需要正确的视角和有条不紊的方法。

我分享这些经验和我发现的最佳实践的动机是帮助推动更广泛的软件开发社区中 AI 的采用——即使实际上,它只是移动了几微米。

AI 编码的现状

超越“感觉编码”

我的 Twitter 信息流表明,AI 驱动的编码工具已经在特定的领域引起了极大的关注:非专业的开发人员,他们正在非常开心地构建软件产品。对他们来说,这些工具主要充当赋能者,使他们能够处理没有这种帮助他们可能永远不会考虑的项目。

更多权力交给他们——很高兴见证他们奋斗和突破的旅程。

但是,这仅代表潜在用户的一部分,当然不是唯一可以从这些工具中获得巨大价值的群体。

资深开发者的优势

我目前的结论,尽管在这个快速发展的领域中只是初步的,是经验丰富的开发人员不仅可以从此项技术中受益,而且实际上处于利用其力量的最佳位置。

这里最吸引人的部分是:在软件工程和项目管理中积累的经验和知识——在 AI 时代可能显得过时——恰恰是实现这些工具最有效使用的关键。

AI 助手:资深编码员,初级同事

虽然我还没有找到基于 LLM 的编程代理在 AI 辅助编码设置中的完美比喻,但我目前将它们视为“在编程知识方面绝对是资深人士,但在 您的特定环境中 的架构监督方面绝对是初级人士”。

这意味着需要一些战略性的努力才能使它们为您节省大量的工作

还有谁比资深软件工程师更擅长以正确的方式投入这项工作呢?

正如我们将看到的,虽然我们正在处理尖端技术,但正是经过时间考验的传统实践和工具使我们能够最有效地运用这种新功能。

关键专业领域

我确定了在使用 AI 辅助编码时需要三个关键的专业领域:

在深入研究这些概念之前,让我分享一些我在项目中如何使用 AI 的真实示例。

我将给出两类项目的示例:全新项目和棕地项目。

对于这两类项目,我将重点关注 AI 处理整个实现或几乎整个实现的情况。

虽然我有时会将 AI 用作“更好的自动完成”或仅作为聊天伙伴进行一般讨论,但本文重点介绍我所说的“真正的交易”——AI 工具以代理模式运行并处理所有繁重的工作。

开发环境

我目前用于这些项目的首选工具是 Cursor,由 Anthropic 的 Claude Sonnet 3.7 模型提供支持。为了获得最佳的开发者体验,我更喜欢不手动将生成的代码复制粘贴到我的代码库中,并且需要 AI 助手直接在我的本地命令行上执行命令。Cursor 提供了此功能,我希望类似的产品会产生类似的结果。

示例 1:平台问题监控

这种设置,结合我将讨论的专业领域,使我能够创建并完全实现一个全新的应用程序:Platform Problem Monitoring。您可以在 https://github.com/dx-tooling/platform-problem-monitoring-core 找到源代码。

该应用程序每小时连接到我们的 ELK 堆栈的 Elasticsearch 服务器,读取最新的错误消息,并向我们发送一封格式良好的电子邮件,总结我们 Web 平台上当前的问题状态:

Platform Problem Monitoring Email Report

有关更多详细信息,请查看 “New project: Platform Problem Monitoring” 文章。

这个例子特别有趣的是,整个源代码都是由 Cursor/Claude 编写的,没有任何我手动编码。

这一点尤其值得注意,因为我实际上并不懂 Python。是的,凭借 25 年以上的软件开发经验,如果需要的话,我可能会编写几行可用的 Python 代码——但我并不真正 这门语言。我缺乏肌肉记忆,也缺乏对其约定和最佳实践的深入了解。

但是,我对软件架构、工程最佳实践、系统操作以及如何打造出色的软件项目有着广泛的理解,这使得开发过程非常顺利。

示例 2:流程管理 UI 集成

虽然我无法分享此棕地示例的源代码,但它展示了一个不同但同样有价值的用例:

我有一个遗留的 PHP/Symfony 应用程序,具有“仅后端”的流程协调功能——想想服务类、枚举、Doctrine 实体和通过 cron 运行的 CLI 命令。虽然功能齐全,但它缺少用户界面。

虽然不是绝对必要,但拥有此流程协调功能的基于 Web 的视图将非常有价值——允许用户监视当前操作、调查失败并管理流程执行。

出于战略原因,我希望此 UI 位于我们较新的应用程序中——该应用程序具有设计更好的代码库、更新的框架版本、改进的测试功能以及具有全面生活风格指南的卓越前端架构。

该任务涉及:

再一次,AI 代理实现了此整个功能,而无需我手动编写任何代码。

两个项目的主要见解

这些示例突出了 AI 辅助的两个不同优势:

  1. 在全新项目中,我可以创建一个应用程序,尽管我不熟悉技术堆栈
  2. 在棕地项目中,我更快地取得了成果——尤其有价值,因为 UI 开发不是我的强项

正是在这个时候,“改变游戏规则”之类的词开始感觉很合适,我开始认识到这项技术对个人和团队生产力的重要性。

成功 AI 协作的关键

让我们研究一下我采用的技术,以确保高效的 AI 编码会话能够持续交付成功的结果。

投入回报原则

如前所述,要通过 AI 节省大量时间,需要进行一些前期投入。这与管理有才华的初级开发人员类似——您不能只是告诉他们“构建 X”并期望获得最佳结果。您需要投入时间来帮助他们取得成功。

结构良好的需求

任何成功的 AI 编码会话的基础都是全面的需求文档。对于 Platform Problem Monitoring 项目,我在开始之前创建了此文档:REQUIREMENTS.md

它有 371 行,内容丰富,但更重要的是,它遵循清晰的层次结构:

低层部分将应用程序的操作分解为 12 个不同的步骤,每个步骤都具有明确定义的输入、输出和副作用。

正如这种结构有效地指导人类开发人员一样,它也为 AI 助手提供了一个框架,使其能够交付可靠的结果。

您可能认为创建此类文档工作量过大。您是对的——确实如此。但这是获得成功结果的必要投资。

我最喜欢的软件开发格言之一是:“六周的实施可以轻松节省您两个小时的计划”

讽刺意味突出了一个重要的事实:实施阶段是弥补计划不足的最昂贵的地方。

我总是鼓励我的团队从白板开始与他们的产品经理一起工作,而不是从键盘开始。此原则同样适用于 AI 协作。

“回放”技术

与 AI 配合使用的一种特别有效的做法是我所说的“回放”:我以“提问”模式开始每个会话,要求 AI:

  1. 用自己的话总结需求
  2. 创建行动计划
  3. 提出澄清问题

仅在此验证之后,我才切换到“代理”模式并开始实施。

基于工具的防护栏

虽然需求定义了目的地,但基于工具的防护栏可确保我们采用最直接的路线到达那里。

考虑一下我们在开发中如何重视实时反馈系统。没有什么比在发布后几周通过客户服务投诉发现缺少 null 检查更糟糕的了。

静态分析工具可以在开发过程中捕获问题,这是非常宝贵的——对于 AI 代理来说,它们也同样宝贵。

这就是为什么我优先在启动 AI 会话之前设置全面的质量工具。我们的 Python 项目的 Makefile 演示了这种方法:

AI 了解这些工具并有效地使用它们。当更改破坏类型检查时,它会自动调整其实现以保持合规性。

我还确保 AI 可以验证其工作的函数方面。对于 API 实现,我提供 curl 命令,以便它可以直接测试其端点。观看 AI 使用和改进自己的代码真是太棒了。

基于文件的关键帧

虽然 AI 代理擅长创造性地解决问题,但有时我们需要限制这种创造力,尤其是在代码组织方面。这就是基于文件的关键帧发挥作用的地方。

该技术借鉴了动画工作室的工作流程,其中主要动画师创建关键帧——动画序列中的关键时刻——而初级动画师填充中间帧。这种方法可以在优化资源使用的同时保持质量。 Platform Problem Monitoring Email Report 通过关键帧,主要动画师可以确保某种风格和特定动画步骤的发生,而无需自己创建完整的动画。

实际应用

与 AI 合作时,我在开始编辑之前在代码库中创建“空壳”文件。例如,在我们的棕地项目中,AI 需要实现各种组件:

等等。

我不是让 AI 决定文件位置和名称,或者在提示中指定这些细节,而是创建最小的存根文件:

<?php
declare(strict_types=1);
namespace App\HighVolumeProcessManagement\Presentation\Service;
readonly class HighVolumeProcessManagementPresentationService
{
}

对于控制器,我可以包含少量基本细节,例如路由名称:

<?php
declare(strict_types=1);
namespace App\HighVolumeProcessManagement\Presentation\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
class HighVolumeProcessManagementController extends AbstractController
{
  #[Route(
    '/volumen-prozesse/übersicht',
    name: 'high_volume_process_management.presentation.controller.show_dashboard',
    methods: ['GET']
  )]
  public function showDashboardAction(): Response
  {
  }
}

这些存根可能看起来很小,但它们非常有效。它们为 AI 提供了有关以下内容的重要信息:

这种方法突出了在 AI 时代仍然至关重要的另一种永恒实践:命名事物。

毕竟,Cursor 等工具核心的 AI 模型是大型语言模型——它们处理文本,而具有意义和意图的文本对于获得出色的编码体验至关重要。

将所有内容组合在一起:一个真实的例子

为了演示这些原则如何在实践中协同工作,让我分享一个最近的项目,我在其中应用了所有三个关键技术:结构良好的需求、基于工具的防护栏和基于文件的关键帧。

挑战

该任务与我们之前的棕地示例类似:实施 UI 仪表板以显示来自我们平台的订阅合同信息。以下是使此项目有趣的原因:

初始提示

下面是我用来启动此项目的实际提示。当您阅读它时,请注意它如何包含我们的三个关键原则,结构良好的需求基于工具的防护栏基于文件的关键帧

我需要你实现一个基于 Web 的只读用户界面,它将以类似表格的概述形式呈现一些现有的 db 持久化数据。

所讨论的数据称为“合同”,它与我们在平台中保存的某些订阅合同信息有关。

该功能需要在包含多个代码库的 monorepo 中实现。对于所讨论的功能,有四个代码库起作用:

  • “backend-app”中的 Symfony 5 应用程序
  • “janus-christophorus”中的 Symfony 7 应用程序
  • “janus-shared-bundle”文件夹中“janus-christophorus”使用的 Symfony 捆绑包
  • “janus-webui-bundle”文件夹中“janus-christophorus”使用的另一个 Symfony 捆绑包

代码库的角色如下:

  • backend-app 当前保存所讨论的数据,但不提供 UI 来呈现数据
  • janus-christophorus 旨在提供将呈现数据的 UI
  • janus-shared-bundle 除其他事项外,还托管 backend-app 提供的 API 端点的 API 客户端实现;janus-christophorus 使用这些客户端从 backend-app 中提取数据
  • janus-webui-bundle 包含 tailwind 设置、css 和 Twig 模板,用于应用于 janus-christophorus UI 的生活风格指南。

你现在的任务是:

  • 在 backend-app 中实现所需的 API 端点,这些端点将提供要在 janus-christophorus 的 Web UI 上显示的数据;此 API 还将支持集成 API 的“演示模式”功能,该功能需要在 backend-app 实现的测试工具层中提供演示数据服务,以便在 API 客户端请求时提供虚假数据
  • 实现一个匹配的 API 客户端,该客户端可用于从这些新的 API 端点读取数据
  • 在 janus-christophorus 中实现一个表示层服务类,该服务类将使用新的 API 客户端
  • 实现一个表示层控制器和 Twig 模板,该模板使用表示层服务来显示通过 API 集成收集的信息

为了准备此实现,我已在不同的代码库中创建了一些“空壳”文件。

考虑提供的合同、用户和 jobofferer 配置文件实体,以确定需要从 MariaDB 数据库中提取哪些数据(或通过演示服务伪造),以便在 UI 的 API 上提供有用的信息。

此外,我还提供了其他文件,如风格指南中的文件、UI 导航服务等等。另请考虑我提供的其他现有功能中的文件作为指导和灵感。

此功能的目的是提供一个 UI,该 UI 允许快速收集系统中可用合同的概述。

重要提示:你可以并且应该使用多个工具来检查自己的工作。

每个代码库都允许你运行质量工具,其中包含 PHPStan 检查和其他检查。你可以像这样运行它们:

cd ~/Projects/website/backend-app && /usr/bin/env bash .dxcli/dxcli.sh quality

cd ~/Projects/website/janus-shared-bundle && /usr/bin/env bash .dxcli/dxcli.sh quality

cd ~/Projects/website/janus-christophorus && /usr/bin/env bash .dxcli/dxcli.sh quality

你可以像这样请求你将实现的 API 端点:

curl -H “Accept: application/json” -H “Content-Type: application/json” “http://127.0.0.1/_/janus-integration-api/membership/contracts/"

你可以像这样请求你将实现的 Web UI:

curl http://127.0.0.1/_jc/mitgliedschaftsverwaltung/verträge/

请创建一个实施计划,并提出你需要回答的任何问题才能完成你的任务。

@Contract.php @User.php @Profile.php @JoboffererProfile.php @MembershipContractsApiController.php @DemoDataService.php @AbstractJanusIntegrationApiController.php @MainNavigationPresentationService.php @ContractsDashboardController.php @contracts_list.html.twig @ContractsDashboardPresentationService.php @services.yaml @AbstractBackendAppApiClient.php @BackendAppMembershipContractsApiClient.php @ContractApiDto.php @BackendAppMembershipContractsApiClientInterface.php @ContractsApiDto.php @NothingApiDto.php @janus-webui.css @living_styleguide.html.twig

结论

此处分享的示例和技术表明,经过适当指导后,AI 编码助手可以显着提高开发生产力。成功的关键在于将传统的软件工程最佳实践应用于这项新技术。

通过提供结构良好的需求、实施适当的防护栏和使用基于文件的关键帧,我们可以利用 AI 的力量,同时保持代码质量和架构完整性。这些经过时间考验的实践,并且最重要的是,通过这些实践获得的来之不易的人类经验,在 AI 辅助开发时代比以往任何时候都更有价值,并且远未过时。