LLM出现后,有人说:完蛋了,程序员要大面积失业了。 我不这样看。 LLM对于软件开发,什么变了?什么没有变? 变化的是,基础编码能力的知识平权,进而带来局部效率的提升。 没有变的是,现代软件工程对应的是规模化场景下的各种问题,基于LLM实现的编程提效只是其中的一小部分,而其中最重要的需求和代码演进模式都没有发生本质的变化。 编程不等于软件工程,编程只是软件工程的一部分。 软件工程有四大内在特性:复杂度、不一致性、可变性、不可见性。这些并没有因为LLM的出现而发生本质的变化,而这些才是软件工程面临的主要矛盾。 软件的复杂度,说的是需求分析和软件设计部分是复杂的,而不是局部的编码变简单。 软件的不一致性,说的是软件依然是知识手工业,LLM出现并未解决这个不一致性的概率,反而可能放大这个不一致性的概率。
我们只有需求说的足够清楚,代码才足够准确,如何准确描述需求变成了关键。
但要想把需求描述到能让它写出代码,需要的工作量似乎已经接近甚至超越过编码了。
很多人不能很好的描述需求,但不影响他写代码。
还有,很多产品经理提的需求,背后其实有很多暗知识,就是程序员已经对产品需求中不包含的信息进行了补充。
软件的需求,不仅仅是功能性的,还有很多非功能性的,这两者都是需要描述清楚的。
总之,软件从业者高估了编程的复杂度,但低估了功能和设计的复杂度。 软件的可变性,说的是软件会随着需求不断演进和变化,所以架构设计和模块抽象只能面向当下,它天然是短视的,或者局限性的,这往往是优秀的架构师也难以逾越的。
也正因为此,敏捷开发模式才被倡导起来了,需求是零散的,目标是模糊的,在有限的视角下,架构自然是有局限的,对此LLM也无能为力。
需求变化之后,程序员一般是在原有代码基础上改动,而不是直接从头全量生成全部代码,而这种局部的改动,对程序员和LLM都不容易。
LLM写代码,本质上不是基于修改意见(Prompt)做代码修改,而是基于修改意见(Prompt)重新写了一份。
软件的不可见性,说的是软件不存在客观的形体,不同的侧面看会有不同的视图,这种强行可视化会造成构图的复杂,但无法可视化,就限制了有效的交流和沟通。 如果团队或者软件规模变得更大,这个问题就会变得更严重,软件研发过程中的沟通成本,决策成本,认知成本,试错成本都会变大。 这才是软件工程问题的本质,自始至终都没有变过,LLM对此也无能为力。 LLM只是实现了编程提效中的一小部分,而现代软件工程则需要应对规模化场景下的各种问题。 LLM时代,软件研发需要更多思考的是: 1. 替代的是码农,共生的是工程师,也就是编码的最后一公里,可以被LLM代替,而工程师需要关注业务的理解,需求的分析,需求的拆解,架构的设计,理解问题本质,机器是副驾驶,工程师是主驾驶; 2. 有利于控制研发团队规模,保持小团队的优势,一部分重复的工作可以通过LLM提效; 3. 暗知识,系统设计或者需求不一定全是以文档形式存在,往往是在程序员或架构师的脑子里,或者在讨论的过程中,即便是有文档,也是个结果文档,大量的推导过程,妥协过程也不是在文档上体现的,这些被称为暗知识,这些暗知识是没法喂给LLM的。总之,你想到的多过你说出来的,你说出来的多过你能写下来的; 4. Prompt即代码,代码不再只是代码,转换一种编程范式,当需求变更了之后,不是去修改代码,而是修改Prompt,基于Prompt版本做代码管理,这是编程范式的改变,我们用LLM重写低代码引擎,也是这个逻辑,Prompt即代码; 5. 直接可运行,Prompt to executable 软件开发范式的可能性,随着Prompt即代码,编程范式的变化,基础设施也会随之变化,CICD等一系列工程实践,最终直接向终端交付价值,Serverless是Prompt即代码的一种可能实现; 6. 计算机教育的反思,LLM证明了死记硬背+简单推理,就能超过大部分人,那教育的目的是什么?教育是应该把人培养成机器,还是把机器培养成人;
也许我们全都错了,我们需要新的思考与反思。