《软件工程经济学》③
一句 User Story ,为什么开始不够用了?
前两篇建立了一个判断:方法论更替的驱动力是成本。当成本结构变了,一些"正确但太贵"的实践会重新变得经济。
这篇聊一个具体的例子。
过去十年,User Story 几乎成为需求表达的默认语言。
作为一个[角色],我想要[功能],以便于[价值]。验收标准:……
简洁,轻便,写起来快,改起来也快。在需求快速变化、需要频繁试错的环境里,它比 RUP 时代的用例文档好用得多。
这是一个合理的取舍。
但取舍意味着有东西被放弃了。
User Story 放弃了什么?
用一个例子来说。
"顾客购买商品"——这句话能说清楚正常情况下发生什么:浏览、加购、下单、支付、收货。
但如果你把这句话交给一个需要独立完成整个流程的 Agent ,它还需要知道更多。
库存不足怎么办?
支付失败怎么办?
用户没有收货地址怎么办?
优惠券在支付过程中过期了怎么办?
用户同时下了两笔订单,库存只够一笔怎么办?
这些"如果出了问题怎么办"的信息,User Story 选择性地省略了。
这不是 User Story 的设计缺陷。在那个时代,这是一个正确的决定。
敏捷面对的核心挑战是反馈速度。先把正常路径做出来,上线看效果,异常路径遇到了再补。在"试错成本低"的环境里,先说清楚正常流程,性价比最高。
但 Agent 改变了一件事。
当 Agent 需要独立执行一个带着分支和例外的任务时,它面对的不再是一个"可以边做边补"的环境。它在开始执行之前,就需要知道完整的路径——包括哪些地方可能出错,出错了应该走哪条路,哪些边界条件绝对不能踩。
Agent 需要的,恰恰是 User Story 当年选择省略的那些东西。
这就是为什么用例( Use Case )最近又开始被讨论。
不是因为它是一种更好的文档格式。
而是因为它的结构里,天然携带了 User Story 省掉的那部分信息。
一个标准用例不只是写"正常情况下做什么"。它逼你同时回答三件事——
主流程:顺利的情况下,步骤是什么?
备选流程:某一步走了另一条路呢?
异常流程:某一步失败了呢?
"库存不足怎么办"和"支付失败怎么办"不是事后补丁。在用例的结构里,它们和主流程是同等地位的组成部分。
不是"这个系统有什么功能"。而是"这个系统在所有情况下会怎么做"。
我后来越来越觉得,它们其实都在描述同一种东西:行为( Behavior )。
这里值得多说一句。
用例并不是唯一一种表达行为的方式。BDD 的 Given/When/Then 在做类似的事。状态机也在做类似的事。
它们各自在不同时代、从不同角度,试图解决同一个问题:如何把系统的行为完整地表达出来。
用例只是其中最早被大规模使用、也最早被大规模抛弃的一种。
被抛弃的原因,前两篇其实已经说过了。
不是因为它想表达的东西错了。而是因为维护这种表达的代价太高。
RUP 时代,用例写完之后,相关的 UML 图、设计文档、测试计划都需要人工同步更新。需求一变,整套制品跟着变。维护成本极高。最终代码更新了,文档没更新——系统和对它的描述逐渐分裂。
压垮用例的,从来不是互联网,不是敏捷,不是"太重了"这种模糊的批评。
是维护成本。
前篇说过一句话:很多实践是"正确但太贵"的。用例就是典型案例。它想做的事情——把行为完整地表达出来——不是错的。但在当时的技术条件下,保持这种表达的同步更新,代价高到了不可持续。
那么今天呢?
Agent 开始具备协助完成这些工作的能力,例如文档同步、变更分析、测试生成、一致性检查。
AI 开始让这些工作第一次具备自动化的可能。
这些恰恰是用例当年被压垮的原因。
这不是说 Agent 今天已经能完美地做这些事,远没有。但它第一次让"保持行为描述与系统实现的一致性"这件事,具备了自动化的可能性。
用例曾经失败的主要原因——维护成本——正在被削弱。
AI 并没有证明用例正确。它只是削弱了用例当年失败的主要原因。
但这里需要说清楚一件事。
用例是不是 AI 时代的最终答案?大概率不是。
Agent 真正需要的,不是某一种特定的格式。
它需要的是行为信息——系统在所有情况下会怎么做。
用例只是人类曾经发明过的一种行为表达方式。BDD 是另一种。状态机是另一种。也许未来还会出现新的形式。
真正值得关注的,不是哪一种格式会赢。
而是"行为"这个维度本身——当 Agent 开始独立执行任务,我们对它说清楚"做什么"已经不够了。我们还需要说清楚"在各种情况下应该怎么做"。
这个需要,以前被实现成本遮住了。
现在它正在暴露出来。
下一篇,我想聊一件更危险的事。
如果 Agent 完全按照你的描述执行,而你的描述本身就是错的,谁来发现这个错误?
最后留一个问题。
你给 Agent 的指令里,包含"如果出错怎么办"的信息吗?
如果没有,你有没有观察到它自己猜错了的时候?