Cursor 是一个现象级的产品,它解决了很多 AI 辅助编程的痛点,让 AI 辅助编程真的能用起来(虽然很多企业用户还有很多合规的问题需要解决)。
不过在使用 Cursor 的过程中,有一个非常大的感受是,开始编码前的上游的系统设计输出物对 AI 辅助编程影响非常大。
比如,如果使用 Draw.io 来绘制架构图,那么 AI 是无法理解的,但如果输出为 PlantUML 以代码化的方式描述架构、时序图等系统设计产物时,对 AI 就非常友好,也能提高工作效率。
想要尽可能提高工作效率,我们必须思考人类如何同 AI 分工。
人类和 AI 分工
AI 很强,但目前又离不开人类独立完成工作。
一个不恰当的比喻是,AI 就像挖掘机,在合适的条件下它的工作能力远远超过手握锄头的人类,但很多地方挖掘机去不了。
所以在 AI 是否取代人类的话题中,二元对立的讨论对我们基本没有帮助。
在合适的地方发挥 AI 的价值,在合适领域挖掘人的潜力,只有这样工程师才能继续为公司出售自己的劳动力。
学习开挖掘机而不是用锄头证明自己比挖掘机挖的又快又好。
在某一次研讨会中,我们讨论了哪些工作适合 AI 完成,而哪些工作适合人类。
我们总结了几点适合 AI 的任务:
- 上下文小的任务。
- 越接近形式化的任务表述,越适合 AI,形式化意味着上下文更小。
- 重复的任务。
- 有精确输出的任务。
看似是四个问题,本质其实还是一个特点:人类更擅长大上下文的任务(虽然 AI 正在赶上),所以人需要拆解复杂上下文,并代理给 AI处理。
这是不是非常像软件行业经典的“高低搭配”“大头兵带小兵”的套路,由 TL、架构师负责处理复杂上下文的任务获得明确清晰的系统设计,并交由开发人员完成。
某种程度上来说,不具备系统设计能力的开发人员被 AI 取代是早晚的事。
如何让 AI 更友好?
两个原则:
- 尽可能用形式化和文本化的方式表述系统设计产物。
- 有可靠的工作模式可以抄(Pattern 或者 SOP)。
这两个原则其实也是日常 TL 操心的内容。
在项目开始之前 TL 有能力搭建一套不错的打样工程起来,该有的元素都要有。
对后端来说,比如一套基本的 CURD 套路,常见的一些组件、单元测试、代码扫描等等。
对前端来说,清晰的数据流转过程,页面规范,常用组件等。
在真正开始写业务代码的时候,用这套打样工程 + 设计好的技术方案就能交给 AI 了。
在 AI 之前,我们大量通过一些代码生成器,根据技术方案和脚手架生成基本的代码。代码生成的缺点在于,不方便更新和演进。现在有 AI 后这个过程变得非常简单。
这也是为什么普通的软件开发工作慢慢变成了装修的活儿了,价格也变成装修的价格了,以后软件开发会变得越来越平民化。
反而深刻理解需求,做出合理的方案比写代码更有价值。
技术方案怎么文本化?
这个问题在我之前的文章中提到过。
每个迭代前用到的技术方案,可以看做一堆模型的集合,这些模型用于描述不同视角下软件的关键信息。
比如:
- 使用 PlantUML 的类图来描述领域模型,表达业务概念
- 使用 DDL 来描述数据实体(可以和领域模型一一对应)
- 使用 Swagger 的 Open API 描述 API
- 使用 PlantUML 时序图、状态图来描述时序和状态
- 使用 Markdown 来描述非结构化的规则和约束
上述的材料全部是文本化的,结合一套不错的打样工程,买了 Cursor 账号,优化掉几个初级程序员是完全可行的。
对比这两个 Prompt。一个用完全自然自然语言描述需求,而一个使用设计规格(Specification)来描述设计。
版本1:
实现一个用户管理模块,完成对用户的管理 API 编写,完成所有 API 的实现和 API 测试。用户模型有 id, username, password, email 等字段,密码需要使用 Hash 编码。
版本2:
参考当前代码仓库中的示例代码,基于 DDL:[放上 DDL ] 和 [API 定义],编写用户管理模块,完成所有 API 的实现和 API 测试,密码需要使用 Hash 编码。。
参考 DDL:
CREATE TABLE `users` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`username` VARCHAR(50) NOT NULL UNIQUE,
`password_hash` VARCHAR(255) NOT NULL,
`email` VARCHAR(100) NOT NULL UNIQUE,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
使用我之前准备的代码脚手架: https://github.com/domain-driven-design/ddd-microservices
如果使用第二个 Prompt Cursor 可以理解代码上下文,基于 Specification 的输入完成的结果会比前面一个好很多。
如何让 AI 更可靠?用 TDD
作为重度的 AI 使用者,无数次被 AI 坑。
AI 的幻觉现象,在实际应用中常常表现为模型过度拟合训练数据,导致在新数据上表现不佳的现象。
我们有时候骂 AI 给的结果不可靠,其实还真不是这样。在我之前的技术管理内容中提到过,人其实也不可靠。
在软件工程中 TDD 本来是一个非常小众的实践,但现在 AI 编程普及后, TDD 可以非常好的解决 AI 的幻觉问题,验证 AI 的生成结果的可靠性。
程序员的工作会变成定义规则、接口,检查单元测试和 API 测试的合理性,然后由 AI 来实现。
AI 和人的输入作为交叉验证的方法,基本上能消除幻觉带来的负面作用。
总结
有人说软件开发的过程是知识学习的过程,其实是对非形式化的业务进行形式化表达,然后让计算机干活。好在现在 AI 居然也能听懂一些非形式化的需求了。
如果 AI 能完全理解非形式化的内容,那么程序员还需要吗?
那么只能说现在先学好用挖掘机,找到更多用挖掘机的场景,至于有一天无人驾驶的挖掘机出现了,那我们再找其它价值吧。
如果真的 AI 有了自己的动机,并繁衍自身,黑客帝国预言的 AI 统治人类也许真的会到来。