概要:本文从Kent Beck的上周的推文谈起,介绍了一次使用ChatGPT构建React应用的实际经历和体验,展示了ChatGPT在编程框架和语言细节、通用业务领域的常识、按要求处理编程细节、代码理解和缺陷定位方面的能力,并在此基础上,介绍了“精益软件设计实践”的概念(一个根本问题,两个核心价值、三大设计原则和系列工程实践),以及它在今天的大模型背景下的价值。
一、引子
Kent Beck在上周发布了一则推文:
翻译成中文:
“我一直不愿意尝试ChatGPT。今天我克服了这种不情愿。现在我明白我为什么不情愿了。我90%的技能,其价值已经被归零了。但是,剩下的10%,杠杆率却上升了1000倍。我需要重新调整”。 |
哪些技能的价值归零了?哪些是剩下的10%?在这篇推文里,Kent Beck并没有说明。下面是我最近的一些粗浅的尝试和思考。
二、1个人,写个前端应用
2.1 应用背景
首先,介绍一下技能背景和应用背景。
2.1.1 业务背景
用户故事地图是管理需求全景图的非常好的工具。如果你对于这个工具缺乏了解,建议阅读Jeff Patton的同名书籍《用户故事地图》。尽管市面上有非常多的用户故事地图工具,但是我总觉得它们用起来不够顺手——大多数只是画图工具,缺乏对方法论的有效支持。
我对于用户故事地图的方法论有深入理解。后端开发也完全不是问题。以前的问题或许是“就差一个程序员了😊”。 那么,现在有了ChatGPT大模型,为什么不干脆自己做一个呢?
2.1.2 技能背景
虽然我有20年的后端开发经验和嵌入式开发经验,但是对于前端应用开发只能算是新手。有最基础的前端开发知识,使用Vue.js开发过简单应用,但是远远算不上精通。没有使用过React。
2.2 进展情况和惊喜时刻
我大概是上上周有了这个念头。从4.12开始动手的,中间有各种其他的事情,不过基本上每天都有代码提交,有时候多一点,有时候少一点。到今天为止,这个应用长成了下面的样子:
它还没连入后端接口。不过,作为一个用户故事地图,它的基本的雏形已经具备了:能够管理骨架故事、能够规划迭代、能够编辑卡片、能够重新排布迭代和骨架故事的顺序。当然,它还有很多信息需要添加,例如用户画像、故事卡的详情等等。
在使用ChatGPT构建这个应用的时候,遇到了不少惊喜时刻,下面给出四个例子:
(一)拥有各种编程框架的知识
例如,当我要求ChatGPT为卡片建立一个拖放功能时,ChatGPT能选择react-dnd库来支持该功能。
当然还有很多其他示例,例如它知道去恰当的选择antd的Card作为卡片的默认实现、创建导航栏菜单、增加路由等等,都可以很好的实现。
(二)拥有通用业务领域的知识
典型例子就是登录页面。我几乎一行代码都没写,而且也没有多余的提示,它默认就为我创建了如下的登录页面。特别值得一提的是,包括用户名和密码的图标、以及打开和关闭密码显示的功能,都是chatGPT自动选择的。
页面虽然很朴实,但是作为基本的功能起点,我已经很满意了,毕竟省下了自己思考和写代码的时间,这个也不是核心功能,后面慢慢优化就是了。
更为惊喜的是,它甚至拥有一些细分业务领域的知识。例如,当我要求它创建一个用户故事卡片的时候,它默认给出了id, title, description三个属性,而这确实也是用户故事卡片的常见属性。
(三)代替人处理大量细节
对我来说,记住各种样式是一个很难的事情。但是由于ChatGPT拥有这方面的知识,所以,我不用记住细节了,提出要求后,只要基于它的结果进行微调就可以。
(四)辅助调试、发现问题并建议修复
我为卡片增添了一个显示快捷操作的功能(包括编辑、删除和前向增加卡片、后向增加卡片)。但是,在拖放的时候,如果这些快捷操作也显示出来,就会很难看。所以,我需要在拖放的时候关闭这些显示。此外,在某些场景下(例如不需要编辑),就不应该显示这些选项。
但是,当我开始运行的时候,功能有些问题。我就把相关的代码给了ChatGPT,请它帮我进行查错。下面是ChatGPT的输出:
做个简单的小结,ChatGPT这类大模型,已经能够很好的扮演一个助手的角色。它能够处理大量的琐碎细节,例如css样式表、各种编程框架的选择(例如react-dnd)、选择合适的图标(例如登录页)、利用领域的通用知识等等。有时候,它还能扮演专家的角色,例如帮助我从复杂的代码逻辑中,查找到潜在的代码问题。有时候,我还会请它帮我汇总一段代码的逻辑和功能,它的表现也很不错。
其实,ChatGPT这个编程小助手已经比人类更让我得心应手。它随时响应,很少犯错,只要我的意图表达准确,它总是勤勤恳恳,尽职尽责。这让我想起了《人月神话》中Brooks推荐的“外科手术式团队”,最高效的团队,是主刀医生作为专家、带领一群助手一起工作。这样的团队,协同高效、概念一致,唯一的要求是主刀医生的水平和助手们的配合度。
现在,助手们已经就绪了,而且是自动化的。现在,有没有优秀的主刀医生,成了关键的问题:
一个优秀的主刀医生,在大模型帮助下,直接就是一个高效团队,能解决过去一个大规模团队才能解决的问题。
3 精益软件设计和主刀医生的技能
我在去年7月出版了一本书:《软件设计:从专业到卓越》,我在书中提出了一个“精益软件设计”的框架体系。但是坦白说,影响力不算大。这本书在豆瓣读书获得了9.9的高分,说明内容还是可以的,但是,为什么影响力不够大呢?
让我们先来看一下主要的内容。其实,精益软件设计框架完全没有发明什么新实践,它们都是已经在过去被证明行之有效的实践,诸如实例化需求、领域建模和领域驱动设计、契约式设计、测试驱动开发、持续集成等等。
它的核心是:
一个根本问题:软件开发的根本问题是复杂性问题。理解软件与生俱来的复杂性是理解一切软件工程实践的根本。这是软件工程巨匠Fred Brooks在《没有银弹》中论证的核心观点
两个核心价值:业务价值和资产价值。业务价值是,之所以我们会开发软件,是首先要达成业务目标。如何让业务目标拉动软件开发,是软件开发的首要问题。资产价值是,我们开发的软件,不仅仅满足了当下的业务需求,它更应该带来组织的长期竞争力。但是,现实中的问题是,很多组织不仅仅没有积累资产(尽管有很多代码),相反却被技术债务拖垮,如下面的图2。
三大设计原则:分而治之、持续演进、内建质量。面对复杂性问题,把大问题变成小问题,是软件开发的基本手段,也就是“模块化”。在空间维度化简还不够,在时间维度上,还需要把增量和迭代作为核心能力,让软件易改动,改得动,越改越好,这就是持续演进的设计原则。内建质量则是业务价值实现和可演进能力的核心。
系列工程实践:软件工程领域作为一个年青的学科,在近50年的专业实践中发展出了大量的工程实践,有些非常有效,有些则被证明是失败的活或错误的。从实践者角度,我遴选了“高质量需求”、“领域建模”、“由外而内”、“接口和契约”、“测试先行”进行了重点介绍。
上述工作说不上开创性,但是从系统性上做了一定的贡献:从价值导向的角度,把这些实践在软件开发阶段处于什么位置、它们之间是怎么联系的进行了清晰的阐述,当然也对其中最关键的实践进行简单阐述。我称这个工作为“藏宝图”,就是能引导读者,理解什么才是软件开发者最重要的,然后请读者按图索骥,去进一步提升技能。此外,清晰的定义什么才是最重要的,也比较容易建立团队共识。
我在那个时候没法预见大模型的爆发。但是,我惊喜地发现,当大模型真的来的时候,这个框架体系依然是基本正确的。这或许是一种幸运,或许,是在一定程度上,抓住了问题的本质。
我用了专门的两章介绍需求分析和领域建模。讲软件设计的书从“需求”开始讲并不是普遍策略,但是,需求才是设计和开发的源头。如果没有高质量的需求,好的软件设计就无从谈起。
我还用了两章介绍了设计分解和责任分配、以及依赖关系。软件的复杂性注定了需要把问题分而治之,如何把大的问题分解成小的问题,其实是主刀医生的一个重要能力。
我给了“设计契约”极其重要的地位。它包括了用契约描述接口、用测试描述契约、活文档、用由外而内推到设计和契约等等。既然协同是本质,就需要通过清晰的契约描述,说明白到底要完成的设计目标是什么。我能够和ChatGPT高效协同,一定程度上,也得益于这种对设计契约的深度理解。例如,下图就是我给ChatGPT的工作指令的一个示例:
下面是ChatGPT完成的任务:
这里应用的其实是使用测试描述契约的技巧,只是形式上略有变化。这种工作方式,很开心、很高效是不是?
我还给了“演进式设计”专门的一章。软件开发的复杂性,让我们一开始就定义完整的问题变得完全不可能。“边做边改”才是常态。而大模型的出现,让“边做边改”的成本降到了极低,如何有效的设计演进路径,变得非常重要。
4 总结
现在让我们回答前述的关键问题,在大模型的时代,KentBeck提出的,90%的能力价值被归零了,还有10%的能力会被1000倍的放大。到底是哪些是90%?哪些是那10%?
我的理解是:
定义问题的能力仍然是重要的。大模型对于通用业务领域,甚至在未来,对于企业特定的业务领域,能有很好的理解,如果对业务问题缺乏认知、“要解决什么问题”都说不清楚,高效的工具并不会带来本质的改变。
分解问题的能力也仍然是重要的。最起码在当前阶段,还没有看的大模型有极好的架构设计能力。架构师长期沉淀下来的架构分解能力,仍然具有很高的价值。
演进式设计的心智非常重要。前面已有说明,不再赘述。
框架能力和语言细节:已经不太重要。它们属于“标准技能”,很大程度上大模型比人类记忆力更好,处理琐碎的问题更快。
基础设施:软件开发和运维的基础设施有可能已经可以更好的标准化或实现自主运维。这方面仍然有大量的工作,但是应该看得到,它们有一个光明的未来。
重构、结对编程、测试驱动开发等已经被验证行之有效的支持演进式设计的实践,有可能发生重要变化。
重构的一个很重要的目标是提升代码的可理解性和可演进能力。现在看起来,大模型对于理解复杂的代码,相比于人类有更大的优势。如果代码理解不再是一个困难的问题,那么,我的大胆猜想就是,重构的方式可能就是在契约保持不变的情况下,完全重写。
结对编程,显然我现在的结对目标已经变成了大模型本身。
测试驱动开发,我仍然在使用测试驱动开发的基本思想,就是契约先行。但是,具体的实践形态,显然已经发生了很大的变化。
5 自我推广
今天是世界读书日。图灵出版的编辑老师专门为《软件设计:从专业到卓越》制作了海报,而且今天是半价优惠。
作为一本书的作者,辛苦创作的结晶总是希望能够被更多的人看到。可以点击文末的“阅读原文”,跳转到这本书的豆瓣链接。豆瓣是一个好的社区和中转站,可以进行评价和讨论,也可以跳转到京东、得到或者当当。希望大家予以转发和支持,如果觉得有价值的话,谢谢!
还有,如果你对于“用户故事地图”有什么样的期望或者评论,也欢迎留言!