跳转到内容

软件工程从来不只是写代码

“既然 AI 现在会写代码,开发者很快就会变得多余。”

如今,这种说法以各种版本反复出现。有时它听起来像预测,有时像威胁,而相当多的时候,它更像营销。

它的出发点并非完全荒谬。AI 确实会写代码,而且已经写得足够好、足够快,也能够以足够大的规模参与工作,以至于软件开发正在发生切实可感的变化。Coding Agent 可以实现 Feature、生成测试、执行重构、寻找错误、分析现有系统,并跨越大量文件进行修改。过去需要我几个小时完成的任务,如今有些确实能在明显更短的时间内完成。

我喜欢这样工作。甚至可以说,非常喜欢。

但代码生产变快,并不意味着软件开发这个问题已经被解决。

真正的思维误区出现得更早:

Coding 并不等于软件工程。

看得见的部分,从来都不是全部

Section titled “看得见的部分,从来都不是全部”

代码是我们工作中最显眼的部分。它存在于 Repository 里,可以计数、比较 Diff、Review,也可以执行。因此,人们常常把软件开发等同于写代码,这并不难理解。

只是,这种等同从来都是错的。

在有意义的代码产生之前,必须先有人理解,我们究竟要解决什么问题。Requirements 需要被解释,矛盾需要被识别,业务关系需要被理解。系统需要边界。数据必须在某处产生、被处理并被保存。组件要彼此通信,外部系统会发生故障,权限必须正确工作,已有数据最终还需要迁移。可维护性、性能、运维和故障场景,并不会因为一个函数能够更快实现而消失。

而且在某个时刻,总要有人决定:在现有条件下,众多可能方案中究竟哪一个才是合理的。

这些,全都是软件工程。

AI 并没有突然让它们变得重要。它们一直都很重要。

真正发生变化的是另一件事:当代码生产越来越快、越来越便宜时,我们就越来越难继续把它和 Engineering 混为一谈。

AI 并没有突然让软件工程变得更重要。它一直都很重要。只是当代码生产本身越来越便宜时,我们更难继续把软件工程误认为只是代码生产。

这也许是当前这场变化最有意思的副作用之一。

几十年来,我们一直在解释 Lines of Code 并不是有意义的生产力指标。现在,我们一个小时里就能生成过去几天才能写出的代码量——可我们有时却又出奇地容易把这种数量重新当成生产力本身。

更多代码,首先只是更多代码。更多 Agent Run,也只是更多 Agent Run。一个 Repository 下午比早上大了三倍,并不能因此证明它创造了更多 Business Value。

Agentic Work 的生产力杠杆依然是真实存在的。

一个表达清楚的任务,如果具备有用的 Context、明确的 Constraints 和合适的架构,往往可以以令人印象深刻的速度完成。Agent 能够稳定地应用已知 Pattern,协调跨越多个文件的修改,也能承担那些机械而单调的工作——过去做到某个阶段,人类开发者可能已经开始认真考虑,咖啡是否应该被正式记录为 Build System 的依赖。

当目标足够清晰时,这种方式尤其有效。

遗憾的是,反方向同样成立。

Agent 也可以同样一致地落实一个错误的业务假设。它可以把一个糟糕的抽象干净地贯穿多个 Layer,也可以把从一开始就错误的架构决定包装在测试、Interface、Mapper 和非常整洁的命名之中。

到那时,错误就不仅仅是错了。

它还会错得结构优美。

Agent 不会保护我们免受错误决策的影响。最糟糕的情况下,它只是把错误决策的实施变得更加专业。

这个问题本身也并不新鲜。开发者过去同样会实现错误的 Requirements、构建糟糕的抽象,或者为自己并没有完全理解的问题设计局部解决方案。

真正新的,首先是速度。

Agentic Work 压缩了时间。正确的决定更快产生效果,错误的决定也是。

也正因为如此,如今真正理解的不只是眼前代码的人,使用这些工具时会拥有非常明显的优势。理解流程、系统边界、Pattern、数据流、业务关系和 Trade-off 的人,不仅能够更准确地告诉 Agent 应该做什么,也更容易尽早发现它的理解是否正在偏离正确方向。

这一切从任务描述就已经开始。

如果提出了错误的问题,你完全可能得到一个对错误问题而言极其出色的答案。

而这往往比一个明显糟糕的答案更加麻烦。明显的错误容易被发现。一套看起来合理、实现整洁、测试充分,却解决了错误问题的方案,反而可能走得非常远。

在“10×”和“反正什么都不会”之间

Section titled “在“10×”和“反正什么都不会”之间”

公共讨论并没有让我们更容易理性地面对这项技术。

一边是如今已经非常熟悉的“10× Developer”、一人团队,以及号称一个下午就完成的 SaaS 产品。一段令人惊艳的 Demo,有时会直接被提升为一种新的软件生产力计量单位。

社交媒体上还流传着一个很漂亮的故事:据说某位 CTO 很自豪地分享了自己刚刚借助 AI 做好的应用链接——结果链接指向 localhost:4200

我不知道这件事是否真的发生过。如今它大概早已更接近 Urban Myth,而不是可靠的事实记录。但作为当前 AI Hype 的一幅漫画,它实在太合适了。

浏览器里能跑起来。看来产品就完成了。

遗憾的是,软件工程中相当大的一部分工作,恰恰从 Demo 结束的地方才真正开始。

系统要如何运行?高负载下会怎样?谁可以看到哪些数据?数据本身是否正确?部分故障发生时会怎样?已有信息如何迁移?下一个 Requirement 到来时怎么办?生成出来的方案中隐含了哪些假设?六个月以后还有人理解这些结构吗?哪些外部系统可能故障?以及最重要的一点:这个应用究竟有没有解决它原本要解决的业务问题?

一个能够工作的 Happy Path,几乎回答不了其中多少问题。

但另一个极端也没有更有说服力。

“AI 反正什么都不会。我还是自己写代码。”

当然可以。

你完全可以批评 Provider,可以认为隐私存在问题,可以质疑成本,可以拒绝质量差的结果,也可以有意识地选择某些任务继续亲自完成。合理使用 AI,并不意味着一定要尽可能把所有工作都交给 Agent。

但如果一个人从未认真使用过这项技术,也没有真正研究过它的能力与限制,却直接宣布它毫无价值,那也并不是什么特别中立的立场。

他只是跳过了实验,直接来到了结论。

Hallucination 不能证明 AI 毫无意义。同样,一次成功的 Greenfield Demo Run 也不能证明软件工程已经被解决。

两边在某些具体问题上都可能有合理观点。真正的问题在于:工具还没有被认真研究,结论却早就已经确定。

在“软件开发已经解决”和“这东西什么都不会”之间,其实存在一个更加有意思的空间。

而那个空间里,必须真的工作。

这种工作的重要部分之一,就是 Verification。

AI 系统并不是真理机器。一个 Output 不会因为表达得很有说服力、语气很自信,就自动变成正确答案。即使是能力很强的 Agent,也可能错误理解假设、忽略 Context、虚构一个看似合理的 API,或者在一条起初完全合理的决策路径上,于某个节点拐错方向。

而且越好的模型,有时越能把这种错误说得令人信服。

这不是反对使用它们的理由,而是要求我们以专业方式使用它们的理由。

不要轻率。要验证。

验证 Requirements 以及从中推导出来的假设,也要验证代码、测试、Security、数据流以及对系统相邻部分的影响。最重要的是,要验证最终得到的方案是否真的解决了最初的问题。

Generation 和 Verification 是两种不同的任务。第一种任务越来越能够自动化,并不意味着第二种任务也自动完成了。

测试同样值得保持一定程度的健康怀疑。一个 Agent 如果实现了错误的理解,也完全可能为这个错误理解写出与之匹配的测试。于是,一个全绿的 Test Run 可以非常可靠地证明:代码和测试共享着同一个错误认知。

至少,这叫一致性。

遗憾的是,它还不叫业务正确性。

这也正是为什么架构规则、显式 Constraints、清晰的系统边界以及好的测试,对 Agentic Work 如此有价值。并不是因为它们能够神奇地让 Agent 永不犯错,而是因为偏离会更容易被看见,有些偏离甚至可以被机械化地检查。

因此,真正关键的问题并不是我们应该信任 AI,还是应该从根本上不信任它。

更有价值的问题是:我们能验证什么?

要找到这个问题的好答案,偶尔读一篇产品公告远远不够。

你必须真正使用这些工具。

因此,我越来越把好奇心看作一种严肃的 Engineering 能力。我指的不是追逐每一个新的模型名字,也不是把整个工作日变成永不停止的 Benchmark,而是培养实践中的判断力。

尝试不同模型,观察给它们太少 Context 或太多 Context 时会发生什么。让 Agent 接手更大的任务,观察它从什么时候开始 Drift。比较小模型和大模型,关注 Token 消耗和成本,找出哪些任务出乎意料地稳定,哪些任务即使反复尝试仍然非常脆弱。

也给它们一些困难或者不完整的 Requirements。让它们失败——最好偶尔让它们失败得足够有说服力,以至于你必须认真检查,才能发现错误。

这样的过程会产生一种任何 Feature List 都无法传达的知识。随着时间推移,你会逐渐形成感觉:什么时候应该追问,什么时候必须把 Constraint 明确写出来,什么时候 Task 太大,什么时候 Context 正在丢失,以及什么形式的 Verification 更适合什么任务。

不是每一条边界都会写在文档里。

有些必须亲自体验。

在技术快速变化的时期,好奇心不是玩乐。它是一种风险管理。

真正去实验的人,不仅会知道一个工具能做什么,也会知道什么时候绝对不应该盲目信任它。

我写代码已经将近 30 年了。但这并不意味着我已经理解这些关系将近 30 年。恰恰相反:对我而言,经验的一部分,就是逐渐意识到那些隐藏在可见代码背后的问题。

今天因为 AI 而重新变得格外重要的许多认识,在软件工程里其实一点都不新鲜。这个学科理解其中一些事情,比我作为开发者真正理解它们要早得多。

经验也并不只是职业生涯中已经过去了多少年。理想情况下,它会改变我们对系统本身的模型:我们能看到哪些关系,会提出哪些问题,以及能够意识到一个决定会带来哪些后果。

而当 Agent 突然能够加速相当大一部分机械实现时,这种系统理解就会变得极其有价值。

因此,我也不太认同等待某个人在未来某一天给出一套权威答案,告诉我们“专业的软件开发现在到底应该怎样使用 AI”。

这本说明书并不存在。

雇主不会完整地提供它。大学面对如此快速的变化,必然只能有限度地跟进。证书无法替代实践经验。Framework 厂商不了解你的系统 Context。而 LinkedIn Timeline 大概依然不能算 Peer Review。

所以,开发者必须形成自己的判断。不是因为害怕自己明天失业——那只不过是同一种廉价的未来预测,只是换成了负号。真正的原因是:面对不确定性,适应能力本身就是合理的应对方式。

这意味着学习、实验、自己验证各种说法,并在出现更好的工作方式时愿意改变原有习惯。它也意味着弄清楚,自动化究竟在哪里真正带来帮助,又在哪里暂时只是在制造更多复杂度。

企业承担着同样的责任。

现在对 AI 的投资热潮是可以理解的。购买 License、引入 Coding Agent、评估模型、提供 Compute、建设 Agent Platform,这些事情很多都可能非常合理。

但 Tooling 对 Capability 的描述远远不完整。

为什么仅有 Tooling 并不能产生 Engineering Capability,以及为什么学习空间是一种投资,我已经在第 13 篇 – Agentic Work 的经济学中详细展开。

人仍然需要机会去积累领域知识、系统理解、技术广度和经验。

这绝不仅仅是对 Junior 的要求。

十年或二十年工作经验,并不自动等于深刻的系统理解。如果一个人二十年来始终只在一个非常狭窄的切面工作,他也不会因此自动拥有二十年的架构能力。

Engineering Capability 不会因为工龄自然产生。

它产生于这样一种环境:人可以积累知识、承担责任、理解系统之间的关系,并从决策中学习。

因此,当企业把“投资未来”主要理解为“投资自动化”,与此同时却在培训、Junior 培养、技术广度或者学习空间上不断承受成本压力时,我认为这里存在真实风险。这样做也许能够改善某些短期效率指标。但它是否同样提升了一个组织长期理解并继续演进自身系统的能力,则是完全不同的问题。

一张 AI License 还不是 Engineering Capability。

投资软件未来的人,因此不应该只投资模型和自动化。还应该投资于组织本身使用这些工具、判断其结果并继续理解背后系统的能力。

工具是这项投资的一部分。

人也是。

最后,还有一个始终悬在这些讨论之上的问题:从长期来看,这一切究竟意味着什么?

我不知道。

AI 发展得很快,Robotik 和其他形式的自动化也一样。思考这些变化可能对工作岗位、企业和社会意味着什么,完全合理。但从今天 Coding Agent 的状态,我们几乎不可能严肃地推导出 2036 年的劳动力市场。

也许会出现新的职业和完全不同的工作模式。也许一些工作会消失,另一些会发生根本变化,同时又出现新的活动。也许今天看起来仍然像乌托邦的社会模式,未来会变得稀松平常。也许很多事情最终远没有想象中那么戏剧化。

未来是一片未知之境。

正因为如此,我更关心我们今天能够影响什么。AI 已经能够大幅加速代码生产,而拥有系统理解的人目前尤其能够有效利用这种杠杆。可靠的 Agentic Workflow 依然需要 Context、清晰的问题定义、Constraints 和 Verification。与此同时,也没有任何合理理由假设模型在这些方面会永远停留在今天的水平。

这些事实完全可以同时成立。

如果我们无法严肃地预测未来,那么适应能力也许就是今天最值得投资的能力之一。

因此,我不想用一个预测来结束这个系列,而更愿意把它变成一个邀请:去真正使用这些工具,给它们真实的问题,而不只是准备好的 Demo。观察它们的边界,理解它们的成本,并验证它们的结果。学会提出更好的问题,也不断积累对自己系统的理解。不要等着某一天由别人把一套成熟方法完整地交到你手里。

我们现在才刚开始真正学习 Agentic Work 在现实软件系统中如何运作。今天使用的一些方法,我们以后很可能会重新抛弃;另一些则可能变得理所当然。新的模型会带来新的可能性——也几乎肯定会带来新的、足够有说服力的错误方式。

所以,这个主题远没有结束。

但在所有这些实验之后,有一个想法对我而言显得异常稳定:

软件工程从来不只是写代码。AI 没有发明这个事实。它只是让我们越来越难继续忽视它。

也许 AI 并没有让软件工程变得更重要。

也许它只是迫使我们更有意识地去做好那些一直都很重要的事情。

而在这个过程中,我们学习的也不只是如何与新的模型协作。

我们正在重新学习,软件工程应当如何与它们一起运作。