为什么规范驱动开发也不是银弹

为什么规范驱动开发也不是银弹 规范驱动开发Specification-Driven DevelopmentSDD是当前AI编程浪潮中涌现出的较好的理念之一。它不再从模糊的提示词直接跳到生成代码而是强制开发者和编码代理首先产出结构化的规范明确需求、定义验收标准、并制定实施计划。这很有价值。但我们需要小心不要把更好的提示词纪律与完全自主的软件开发混为一谈。在执行阶段即使是最成熟的SDD工作流最终也会变成一个模型上下文。规范、计划、约束、护栏和任务分解最终都会传递给LLM进行解读。SDD提高了那个上下文的质量。它并没有消除模型的局限性。这类似于为什么思维链式分解通常有帮助。一个详细、结构化的中间表示通常比模糊的表示产生更好的结果。但它并不能神奇地赋予模型架构判断力、领域理解能力、库选择纪律或长期工程可靠性。每个企业都在追求的终极目标是完全自主的软件开发。目前的模型还远未达到那个水平即使有了更好的前期规划和SDD这样的框架。需要明确的是我并非否定SDD。恰恰相反。我计划在未来的项目中继续使用Spec Kit或类似的框架。它们减少了样板提示词为随性编程vibe coding施加了结构使AI辅助开发更加规范。但我的实验清楚地揭示了其边界。让一个抽象物规范变得详细本身就是一个逻辑矛盾。我尝试使用GitHub Spec Kit v0.8.9和Claude Code使用Claude Opus 4.7将SDD应用于一个真实功能。结果在许多方面令人印象深刻。生成的结构很有用实施流程比普通提示词更好。但正如我所预料的它在选择正确的库和框架方面失败了。这个实验也为本文提供了实证支持截至目前使用SDD进行完全自主开发并不能在所有项目中取得最佳效果。1、背景当那些缺乏实际经验的人站出来宣称规范是软件开发的银弹时我的脑海中立刻回到了《人月神话》。这是一本40年前的书现在已经很少有人读了但它至今仍有深刻的启示。Fred Brooks写道“软件的复杂性是其本质属性而非偶然属性。因此抽象掉软件复杂性的描述往往也抽象掉了其本质。”不管是AI帮助编写的规范还是人类编写的规范其实都无关紧要。软件的本质复杂性永远无法被任何规范所捕获。我可以在这里结束文章。这句话足以解释和证明为什么仅靠规范是不够的。除了一个可能对非从业者/非程序员不太明显的小问题——软件的本质复杂性是在软件开发过程中不断演化的。这是SDD忽略的一个关键流程实际上是其最大的弱点。无论来自专家人类还是AI规范的初稿通常不是最好的。好的实施设计和框架选择来自于对代码的迭代改进。AI生成代码的情况也是如此因为在代码运行过程中会发现未知问题。软件偏离规范不是bug而是一个feature——用程序员的话来说。引自同一章节——“我相信构建软件的困难部分在于对这个概念结构的规范、设计和测试而不是将其表示出来的劳动……我们仍然会犯语法错误但与大多数系统中的概念错误相比它们简直微不足道。如果这是真的构建软件将永远是一项困难的工作。本质上不存在银弹。”规范是在代码和设计迭代过程中开发和更新的。从业者将这种做法称为原型开发Prototyping。我从未在不先编码/原型化一个新功能的情况下写过哪怕一个字的规范。软件开发中没有银弹。这在40年前是正确的在AI驱动的开发时代现在仍然正确。与其说《人月神话》不如写一本《AI加速的神话》仍然会非常接近真相。当我开始职业生涯时Rational Rose是市场上最被炒作的工具之一。UML被视为那个十年的银弹画框、箭头和图表工具就会神奇地将它们变成可运行的代码。我当时持怀疑态度从未认同仅靠图表就能替代工程判断的想法。随着行业吸取了同样的教训这种炒作最终消退了。因此当目前对规范驱动开发的热潮兴起时我有一种似曾相识的感觉。然而SDD复活了许多通常被社区弃置的最佳实践——前期分析、规划、设计、测试驱动开发。1.1 SDLC到底是什么SDLC这个缩写长期以来已经从大多数现代程序员的词汇中消失了——更多地与瀑布方法论联系在一起。亚马逊的AI聚焦IDE Kiro将其重新带回视野将其重新定义为AI原生SDLC或AIDLC的骨干。其核心描述的是分析→设计→实施循环。来源人们错误地认为SDLC意味着瀑布模型。像Scrum和敏捷这样的迭代方法论遵循完全相同的阶段——只是范围被限制在功能列表的一个子集通常一次一个功能——一个更小的子集称为用户故事和任务现在几乎所有现代软件开发组织都有自动化的CI和CD流水线。因此将其否定或与瀑布模型的所有旧问题联系起来是不正确的。如果你使用SDD来开发整个产品或大型功能——在Scrum术语中称为史诗——并给出类似我想构建一个新的数据库系统的提示词范围很大生成的工件数量巨大任务列表也很庞大。如果以这种方式使用这种批评是有道理的。如果整个项目一次性被规范人类不可能一次性处理如此大的认知负荷甚至在几天内也不行。结果是规范者最终放弃了变成了一个过度劳累的办事员盲目地签署文档在SDD驱动的代理循环中按是或确定——继续。然而SDD也可以用于更小的功能子集我认为这是更好的方式。另一个对SDD的反对意见是AI模型是非确定性的因此不同模型或同一模型在不同时间可能对规范有不同的解读。这在实践中不是主要问题。SDD框架充当结构化提示词现代模型在其指导下会产生高度一致的输出。1.2 真正的问题为什么代码成为真相来源以及为什么这是一件好事。好的设计和算法思想是在编码过程中打磨出来的。好的设计和算法思想是在编码过程中打磨出来的。这是一个对所有编写和交付复杂产品的人来说都显而易见的简单真理对那些不这样做的人来说则不然。这就是为什么初始的分析和设计规范会过时代码成为真相来源。SDD试图通过反转规范和代码的角色来改变这一点。SDD试图通过反转规范和代码的角色来改变这一点。其基本论点是可以在不修改代码和进行一些原型化的情况下事先规范出好的设计这在根本上是错误的。对这个论点的反驳是代码生成AI模型的能力。即模型足够强大能够打磨出最好的设计、库和框架决策。在严格的SDD下即使对非常强大的模型来说这也变成了更大的问题因为它试图严格遵循规范而规范中存在漏洞或不准确之处实际上产生了比平时更差的代码。这就像一个第22条军规式的困境。规范必须在一开始就非常严谨但为此它需要根据生成的代码进行迭代修改。在完全自主编码的情况下LLM进行代码和设计的自回归生成就像写一首诗一样。没有重构或返工。我们只能祈祷提示词或规范足够好。生成的代码量如此之快和庞大以至于不可能手动审查或重构它。完全自主的编码适用于快速原型开发或概念验证——但不适用于生产环境。2、一个端到端实验来验证SDD论点为了具体验证这一局限性我使用Spec Kit——一个流行的规范驱动开发框架——运行了一个端到端实验。我在实验中使用了Spec Kit但我认为结果并不仅限于Spec Kit。我预计使用OpenSpec、BMAD或任何通过AI编码代理从规范走向实施的类似框架都会出现类似的模式。我选择的功能是现实的且非平凡的一个用于处理跨越USGS 3DEP/NED瓦片的美国高程数据的Python模块。我之前曾处理过这个问题所以我已经知道从实际实施中最终会出现什么样的架构。目标很简单SDD流程是否能自行找到类似的架构实验地址https://github.com/alexcpn/speckit_test2.1 实验设置我遵循了标准的Spec Kit流程初始化→章程→规范→澄清→计划使用的工具包括Spec Kit v0.8.9Claude CodeClaude Opus 4.7初始章程围绕代码质量、测试驱动开发、一致性和性能创建了合理的原则。在这个阶段一切看起来都没有明显问题。事实上这些原则是合理的。但两个隐藏的力量已经被引入。首先章程要求每个新依赖都必须以书面形式论证其合理性。这听起来很好但它悄悄地给了Python标准库一种优势和偏见。标准库解决方案的论证成本为零而每个外部依赖都必须自我辩护。其次章程要求事先设定可衡量的性能预算。理论上同样合理。但如果这些预算是在理解架构之前猜测的它们后来就变成了人为的约束。这就是SDD开始显示其弱点的地方。早期的假设硬化为规则。初始规范从一个简单的用户请求开始构建一个Python模块来存储美国高程文件并计算两个经纬度点之间的高程剖面。代理生成了一个看起来干净的规范。但一些重要假设是错误的。这被SDD框架生成并传递给LLM的提示词在下一阶段正确地捕获了。2.2 澄清阶段第一个版本假设了一个更小、更简单的范围本质上仅限于美国本土的数据集和一个更业余级别的存储问题。实际需求要大得多覆盖美国本土加上夏威夷和波多黎各等所有美国领土约1,756个NED文件约230亿个高程样本约180GB的原始数据。澄清阶段确实很有用。这是工作流中最强的部分。代理识别了关于数据集规模、支持的源格式和性能预期的重要遗漏问题。一旦数据集规模得到澄清问题变得更加现实。但也有一个微妙的问题。当代理询问瓦片索引持久化时它提供了重建索引、存储小型元数据副件或缓存已解码的瓦片载荷等选项。推荐选项是小型元数据副件。该选项是合理的。但菜单本身悄悄地塑造了设计空间。一个更好的架构——将数据集转码为Zarr存储——并未被作为一等选项呈现。它在概念上接近缓存的已解码载荷但它没有被框架为不同的产品形态或架构路径。这是AI驱动规范工作流中被低估的风险澄清菜单本身就是一个设计决策。用户可能认为他们正在回答一个需求问题但代理已经缩小了架构可能性。相信SDD提示词能真正涵盖所有架构和设计需求确实是一个巨大的风险。2.3 计划阶段在计划阶段代理选择了使用标准sqlite3模块的SQLite配合R-tree虚拟表进行空间查找。孤立地看这不是一个糟糕的选择。它干净、可检查、简单且无依赖。它也与章程完美契合。但这恰恰是问题所在。当被问及为什么选择SQLite时代理严重依赖它是标准库的一部分且不引入新依赖这一事实。像Parquet、LMDB、DuckDB或者在这种情况下更好的Zarr或TensorStore等替代方案被部分地因为它们会增加依赖而被拒绝。换句话说章程已经倾斜了决策。该计划在通用SDD框架自带的模板内——在这种情况下是Speckit——是内部一致的。但它也是一个局部最优一个最小化与规范框架摩擦的设计而不是从数据问题的真实形状进行深度推理。计划确定后我挑战了这个决策因为我事先已经做过这个功能。为什么是SQLite为什么不是Zarr为什么不将所有源文件一次性转码到Zarr存储中以避免重复的启动/索引开销代理最初拒绝了这一想法因为一次性转码会违反早期为冷注册设定的性能预算。但那个预算并不是一个需求。它是早期作为规范流程的一部分引入的然后被当作了真实约束。一旦受到挑战代理收回了论证。它承认如果注册被重新框架化为一个可以耗时更长的一次性设置步骤Zarr设计是完全合理的。这是实验中最重要的时刻。更好的架构不需要新信息。它需要的是质疑由规范过程本身产生的早期假设的意愿。3、实验展示了什么这个实验并没有证明Spec Kit不好。事实上我发现其工作流很有用。它带来了结构暴露了遗漏的问题使开发过程比普通提示词更加规范。但它也展示了AI辅助开发中SDD的核心局限性。使用AI创建规范可能会引入一些遗漏这些遗漏只有在很久以后才会显现。即使一开始更慢由工程师手动编写规范的第一版然后使用AI来改进、完善和挑战它——往往比反过来更好。这让我再次回到Fred Brooks在《人月神话》中的话“软件的复杂性是其本质属性而非偶然属性。因此抽象掉软件复杂性的描述往往也抽象掉了其本质。”在这个语境下这句话有非常实际的含义。如果规范抽象掉了太多复杂性它可能也抽象掉了正在构建的软件的本质。这就是为什么代码往往成为真正的真相来源。不是因为规范没用而是因为规范很少能捕获在实施过程中出现的所有设计压力、边界情况、库限制、性能权衡和算法细节。好的设计并不总是在编码开始之前就被发现的。许多重要的设计和算法思想是在编码、原型化、调试、测量和重构的过程中打磨出来的。这也是为什么初始的分析和设计文档经常过时而代码逐渐成为系统最准确的描述。这不一定是问题。这就是好的软件被构建出来的方式。我们不会只通过阅读规范来修复困难的问题。我们最终会求助于实际运行的真相代码。SDD试图通过使规范成为主要工件、代码成为下游输出来反转这种关系。其隐含论点是好的设计可以通过足够严谨的前期规范来指定然后实施可以从中推导。这个实验表明对于非平凡的软件这个论点是有缺陷的。规范是有用的。计划是有用的。规范是有用的。但最好的设计通常在编码功能的过程中涌现出来。原文链接为什么规范驱动开发也不是银弹 - 汇智网