PageSourceSearch

http://ibeetl.com/assets/index.html-BIE-TKEX.js

js ibeetl.com collected 2026-10-03 23:20:48 UTC 36,107 bytes, 30 lines download raw bytes

1import{_ as i,c as t,b as a,o as l}from"./app-CNefOTx1.js";const e="/assets/se_ai_1-D_RaWA6F.png",n="/assets/se_ai_2-CthAWvIr.png",h={};function p(k,s){return l(),t("div",null,s[0]||(s[0]=[a('<p>  本书的目的是掌握架构和其关键质量的实现方式,构建高质量的软件系统。架构从多个视角多个层次描述如何构建系统,质量驱动是完成现代软件系统必要的方法。 除了架构外,从另外一个视角看,应用软件工程也是构建高质量系统的路径,实时上,随着软件系统越来越复杂,团队人员较多情况下,软件出现了交付延期,质量低下,即使拥有优秀的程序员,也不能按时保量的交付软件系统。导致所谓的“软件危机”事件,全球的软件专家通过多年的摸索,根据其他行业的工程经验,得出一套软件工程方法指导完成复杂软件系统,架构正式是软件工程的很重要的一个环节。</p><p>  随着现在AI编程发展,程序员的开发效率得到了极大提高。以前需要数天完成的开发任务,在AI的帮助下可能仅1小时就能完成。这是否意味着架构不重要,软件工程不重要。AI和AI编程是更有利于架构和软件工程实施,还是会颠覆软件工程的方法论,这是本节需要讨论的,如果不能很好的理解软件工程和AI编程,可能会导致第二次软件危机,系统出现延迟交付和低质量的交付。</p><h3 id="_1-11-1-初代软件危机" tabindex="-1"><a class="header-anchor" href="#_1-11-1-初代软件危机"><span>1.11.1 初代软件危机</span></a></h3><p>  上世纪60年代起,随着软件系统普遍应用在各行各业,个人构建系统被团队构建系统代替,人们发现团队构建复杂软件系统,通常都会带来严重的超期、功能实现错误、以及软件系统难以维护和后续迭代。</p><p>  北约科学委员会在1968年和1969年主办了两次会议,否定了危机是因为缺少合格的程序员导致或者缺少优秀的开发工具造成的。借鉴了建筑工程,电气工程等其他行业中的经验,得出根本解决办法是构建建软件也应该是需要工程化。工程化的含义是指导一个团队一定的规范和流程帮助下,借助工具,能高效完成软件系统和持续维护软件系统,并能重复这一个过程。许多人认为,这会议标志着软件工程专业的正式开始。</p><p>  软件工程试图解决以下问题.</p><ul><li>软件进度难以控制</li><li>软件成本超出预算</li><li>难以满足系统利益相关方</li><li>开发团队内部难以沟通</li><li>软件系统质量不高:比如开发软件可靠性不高,频繁宕机。</li><li>运行错误较多,给客户造成损失</li><li>软件难以维护,软件系统后续迭代开发乏力。</li></ul><h3 id="_1-11-2-软件工程" tabindex="-1"><a class="header-anchor" href="#_1-11-2-软件工程"><span>1.11.2 软件工程</span></a></h3><p>  软件工程是包含了生产系统软件原则、方法、技术和工具,指导和支持软件系统的生产活动,以降低软件生产成本 、改进软件产品质量、提高软件生产率水平的目标。它借鉴了建筑,电气等行业的工程概念,明确提出了软件生命周期的模型发展了许多软件开发与维护阶段适用的技术和方法,并应用于软件工程实践,取得良好的效果。</p><p>  其中,软件生命周期模型是最重要的概念,它定义了软件开发过程中各个阶段的顺序、任务、交付物以及各阶段之间的衔接方式。</p><table><thead><tr><th style="text-align:left;">阶段</th><th style="text-align:left;">描述</th><th style="text-align:left;">产出物</th></tr></thead><tbody><tr><td style="text-align:left;">需求管理</td><td style="text-align:left;">收集系统利益相关者及其需求,对需求进行收集、分析、记录、跟踪和变更等活动</td><td style="text-align:left;">企业战略,需求描述书,非功能性需求描述,业务架构,需求变更。</td></tr><tr><td style="text-align:left;">建立模型</td><td style="text-align:left;">将目标系统抽象为模型的过程。每个模型代表了系统的某一方面。通常使用UML来描述模型,如时序图,类图ï¼
1ŒçŠ¶æ€å›¾</td><td style="text-align:left;">用例模型,概念模型,时序图,状态图。</td></tr><tr><td style="text-align:left;">架构(概要设计)</td><td style="text-align:left;">多角度,高层次的的建立系统的模型,用于后期设计和实现</td><td style="text-align:left;">数据架构,应用架构,软件架构,部署架构,开发架构,安全架构等</td></tr><tr><td style="text-align:left;">详细设计</td><td style="text-align:left;">对架构阶段的产出物进行细化设计,应用设计模式,设计原则,数据库范式和反范式等完成系统详细设计</td><td style="text-align:left;">UML类图和时序图,设计模式,系统原型,API接口文档,数据库DDL.</td></tr><tr><td style="text-align:left;">实现</td><td style="text-align:left;">程序员将设计转化为可运行的代码,并包含了多个产出物,如代码工程,打包软件,配置说明等。</td><td style="text-align:left;">软件系统,单元测试,集成测试,配置管理,数据库脚本,以及依赖的相关基础设施使用说明</td></tr><tr><td style="text-align:left;">软件测试</td><td style="text-align:left;">系统部署到测试环境以及验收环境,验证系统功能是否符合需求。</td><td style="text-align:left;">测试用例、测试脚本、测试报告</td></tr><tr><td style="text-align:left;">软件发布和维护</td><td style="text-align:left;">发布软件到生产系统,上线运行。后期持续修复BUG、迭代实现新需求</td><td style="text-align:left;">可发布的软件系统,上线说明书,安装说明书,系统使用说明书,版本说明书。</td></tr><tr><td style="text-align:left;">风险管理</td><td style="text-align:left;">包含风险识别,分析,规划,监控。比如外包公司人员频繁变动被识别为其中的一风险。组织机构调整识别为风险</td><td style="text-align:left;">包含系统、产品、人员的风险说明,也包含竞争对手带来的风险。</td></tr><tr><td style="text-align:left;">质量管理</td><td style="text-align:left;">对软件质量和软件工程进行管理,符合客户需求,符合ISO 25010,或者CMMI等其他标准。软件测试是质量管理一部分,针对的是软件系统是否运行正确,是否符合质量要求。 质量管理目标还包括了软件工程本身,比如确保需要变更被持续记录,确保项目计划合理</td><td style="text-align:left;">质量规划和软件质量报告</td></tr></tbody></table><p>  实现软件生命周期,针对不同的软件系统,通常有俩种工程方法实现, 分别是瀑布模型和敏捷开发,这俩种工程方法都符合软件生命周期各个阶段,但各个阶段执行时间,频率以及产出物有所不同</p><table><thead><tr><th style="text-align:left;">工程方法</th><th style="text-align:left;">适用</th><th style="text-align:left;">描述</th></tr></thead><tbody><tr><td style="text-align:left;">瀑布</td><td style="text-align:left;">适用于需求(功能和非功能)有明确规划的系统,比如电信从3G到5G的整体规划。</td><td style="text-align:left;">完整实现了上述软件系统生命周期各个阶段以及包含了必要的产出物。通常需要半年以及数年时间。如果需求变更,需要记录到需求变更说明书,并规划到下一次迭代</td></tr><tr><td style="text-align:left;">敏捷</td><td style="text-align:left;">需求频繁变化,系统需要快速实现的场景,期待运行后的反馈。如电商,AI Agent</td><td style="text-align:left;">敏捷开发过程会压缩从需求分析到软件发布阶段的时间,通常会从需求中先选出最有值的部分,在数周内完成一次迭代开发(比如Scrum提倡2周一次)。敏捷开发不像瀑布模型那样要求较多的产出物,比如不需要详细的需求说明书如果需求变更,可以在下一次迭代中完成。敏捷工程提倡积极应对需求变化</td></tr></tbody></table><p>  详细讨论软件工程超出了本书的写作范围,以作者的经验来看,未满足客户期望的系统,多半是没有按照软件工程严格执行或甚至没有执行软件工程,比如忽略了需求分析和变更管理,忽略了质量管理等. 我曾后期参与的一个金融类项目,原来计划半年完成,最后花了1年半。分析原因,需求分析投入时间太少就仓促投入设计和实现。项目进展了大半年,权限系统,业务流程都被推翻重做。</p><h3 id="_1-11-3-软件工程和架构" tabindex="-1"><a class="header-anchor" href="#_1-11-3-软件工程和架构"><span>1.11.3 软件工程和架构</span></a></h3><p>  架构是软件工程的一部分,在前面章节中,我们看到架构衔接了需求和系统实现。</p><p><img src="'+e+`" alt=""></p><p>  系统架构是从多角度,多层次来描述了软件系统,指导软件系统实现,保证了软件交付时间和后续可迭代,以及实现风险管理。</p><ul><li>多角度: 从业务架构角度,数据架构角度,应用角度,还有软件架构,部署角度描述系统。多角度本身就是描述一个事物的方式,不局限于软件系统。如多角度描述一个6代战斗机实现,多角度规划一个小区建设。</li><li>多层次: 采用自顶向下的设计,比如数据架构,先根据需求得出概念模型,然后根据概念模型,有了逻辑模型,以及用于开发的物理模型。软件架构也是这样,通常有个高层次的软件架构,比如1.3中物联网的应用架构,先高层次的划分了应用模块包含了APP,物联网,以及设备。然后在详细的架构中,设计了设备网关,用户网关,主网关,网关管理系统,代理系统等应用。自定向下本身也是构建一个系统的方式,不局限于构建一个软件系统</li></ul><p>  系统架构是软件工程重要的衔接一环,指导了软件的实现以及后续迭代。但软件工程执行过程中经常被忽略,这是因为</p><ul><li>
1团队缺少专职的软件架构师,团队会偷懒默认采用一些架构,比如无架构的系统,或者流行的架构直接用,比如团队直接使用Spring Cloud这种分布式架构而判断是否需要,不了解使用其架构的负面作用。</li><li>时间紧迫,需求分析完毕就直接进入开发环境。这是通常需求和需求分析占用了大量时间,比如一个规划6个月的项目,可能需求阶段占用了3个月。软件设计和实现占用1个月(留给架构的时间可能不足一周),测试2个月。</li><li>系统建设初期,在不考虑系统质量和后续迭代情况下,架构显得不那么重要。我个人认为,如果只能保留2种架构产出物,对于传统企业应用,数据模型中的概念模型和业务架构的流程图很重要。对于电商和物联网来说,保留业务架构中的业务流程和业务术语比较重要。</li></ul><p>  软件工程缺少架构环节,或者质量不高的架构,依然解决不了上世纪60年代就提出的所谓的“软件危机”。所幸的是,现在是一个AI时代,它极大提高了AI编码和测试效率。软件工程其他环节,也开始得因为AI得到效率提升,程序员在AI辅助下能完成软件架构工作,软件架构也将有充足的时间实现。 本章后面两节介绍AI编程,以及AI编程的目前一些副作用,导致可能带来的第二次软件危机。</p><h3 id="_1-11-4-ai-编程" tabindex="-1"><a class="header-anchor" href="#_1-11-4-ai-编程"><span>1.11.4 AI 编程</span></a></h3><p>  毫无疑问,AI和AI Agent极大的提高了编码效率。AI编程有点像许愿,肯定是灵,但结果未必如自己预期。北京有一系列著名的雍和宫很灵的笑话。比如</p><ul><li>有人在雍和宫许愿这个月发大财,结果出门就被车撞了,获赔10万。显灵很快。</li><li>有女孩去求一个当兵的男朋友(“兵哥哥”),结果没过几天,自己的亲哥去当兵了。这属于“人给你了,但没说是哪种哥哥”</li><li>许愿能跟暧昧对象“尽快有个结果”,结果不出半个月,被对方“拒绝了”。</li><li>来自我身边人的一个真实经历,许愿自己儿子考上985高校。结果当年没考上复读了,第二年才考上。悔恨的把腿拍肿了,因为许愿时候忘记说是具体哪年实现。</li></ul><p>  现在AI编程,通过程序员反复提示,以及Skill帮助下,生成的代码能满足功能,但一些非功能(质量)常常被忽略,这主要是依赖程序员是否具备架构经验。</p><p><strong>高可用实践</strong>,程序员不清楚高可用有哪些挑战和应对方法,无法指导AI生成代码。比如,对关键业务进行流量管理,对第三方调用进行超时处理等。</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//AI生成代码</span></span>
2<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">rest</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">call</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">url</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">para1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">para2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
3<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//高可用代码</span></span>
4<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">future </span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> executor</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">submit</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(()-&gt;</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">rest</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">call</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">url</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">para1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">para2</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">))</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">;</span></span>
5<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> ret</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">=</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">future</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">
5get</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#2F798A;--shiki-dark:#4C9A91;">1</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> TimeUnit</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">SECONDS</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>高性能实践</strong>,AI通常按照训练模型的大概率输出代码,并非包含高性能代码和设计。比如AI输出的日志框架大部分是使用占位符输出,而效率较高的是Spring那种字符串拼接输出风格</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//AI可能生成的代码</span></span>
6<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">log</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">info</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">hello,{}</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">para</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
7<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//Spring 性能较好的风格</span></span>
8<span class="line"><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;">log</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">.</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">info</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#B56959;--shiki-dark:#C98A7D;">hello,</span><span style="--shiki-light:#B5695977;--shiki-dark:#C98A7D77;">&quot;</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">+</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">paras</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p><strong>可修改实践</strong>,如果能在生成代码前,就告知AI一些可修改战术方法,AI生成的代码会共容易阅读和修改。比如需要生成一个SQL语句解析并替换关键词的工具,AI可能给你一个超过5000行的单一方法的代码。你掌握可修改实践,你会提示AI:“应该先把SQL解析成AST,然后提供方法遍历AST,找到特定节AST类型节点进行替换。最后新的AST能还原成SQL语句”。</p><div class="language-java line-numbers-mode" data-ext="java" data-title="java"><button class="copy" title="Copy code" data-copied="Copied"></button><pre class="shiki shiki-themes vitesse-light vitesse-dark vp-code"><code><span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//未约束的AI 代码</span></span>
9<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> String </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">newSQL</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String sql</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String keyword</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String replace</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">){</span></span>
10<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">    ///5000行,包括若干for循环</span></span>
11<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    for</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
12<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">        for</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
13<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">            for</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">()</span></span>
14<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">        }</span></span>
15<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
16<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span>
17<span class="line"></span>
18<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">//完整提示的AI代码</span></span>
19<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">public</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> String </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">newSQL</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String sql</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String keyword</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String replace</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">){</span></span>
20<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    SQLAST</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> root</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> build</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">sql</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
21<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">    SQLAST</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]</span><span style="--shiki-light:#B07D48;--shiki-dark:#BD976A;"> matchsNode</span><span style="--shiki-light:#999999;--shiki-dark:#666666;"> =</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> serch</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">root</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">keyword</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
22<span class="line"><span style="--shiki-light:#1E754F;--shiki-dark:#4D9375;">    for</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(){</span></span>
23<span class="line"><span style="--shiki-light:#A0ADA0;--shiki-dark:#758575DD;">       //替换matchsNode</span></span>
24<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">    }</span></span>
25<span class="line"><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">    reutrn </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">toSQL</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">root</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
26<span class="line"><span style="--shiki-light:#999999;--shiki-dark:#666666;">}</span></span>
27<span class="line"></span>
28<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">private</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> SQLAST </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">build</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">Stirng sql</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">){...}</span></span>
29<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">private</span><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;"> SQLAST</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">[]</span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;"> serch</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">SQLAST root</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">,</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">String keyword</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span>
30<span class="line"><span style="--shiki-light:#AB5959;--shiki-dark:#CB7676;">private</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;"> String </span><span style="--shiki-light:#59873A;--shiki-dark:#80A665;">toSQL</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">(</span><span style="--shiki-light:#393A34;--shiki-dark:#DBD7CAEE;">SQLAST root</span><span style="--shiki-light:#999999;--shiki-dark:#666666;">);</span></span></code></pre><div class="line-numbers" aria-hidden="true" style="counter-reset:line-number 0;"><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div><div class="line-number"></div></div></div><p>本书包含了大部分高性能,高可用,可修改的战术方法,可以用来提示AI</p><h3 id="_1-11-5-第二次软件危机" tabindex="-1"><a class="header-anchor" href="#_1-11-5-第二次软件危机"><span>1.11.5 第二次软件危机</span></a></h3><p>
30  AI工具使用和AI编程极大提高了工作效率,以软件工程为例子,各个阶段都在AI帮助下得到效率提升。下图展示了有无AI的情况下,软件工程效率</p><p><img src="`+n+'" alt=""></p><p>​ 在软件工程体系下,使用AI能提高各个阶段的交付效率。这是目前很多软件工程师得出的感受。但当时使用AI,如下问题需要注意</p><table><thead><tr><th style="text-align:left;">AI风险 </th><th style="text-align:left;">描述</th></tr></thead><tbody><tr><td style="text-align:left;">软件工程其他环节成为瓶颈</td><td style="text-align:left;">比如需求需要与较多的利益相关者交流确定,仍然要较长时间完成。在整体环节没有用上AI前,系统的交付效率不会如预期的飞快提速。以我曾经完成的一个项目为例子,其中需求分析持续了7个月(需要与多个系统和多个设备生产公司交流),开发只给出一个月时间,就算AI开发能压缩到一周甚至更短,对于项目来说,交付周期较长的现象未改变</td></tr><tr><td style="text-align:left;">草台班子行为得不到限制</td><td style="text-align:left;">软件工程方法保证了即使团队是一个没有经验的团队,按照软件工程方法论也不会出现太大的问题,AI编程会诱惑团队忽略软件工程的某些环节,比如忽略软件系统自顶向下的设计,忽略各种产出物的评审,忽略数据模型,忽略系统质量目标等。取而代之的是直接AI编码和交付</td></tr><tr><td style="text-align:left;">分工和流水线</td><td style="text-align:left;">软件工程带来的效率提升的根源是分工和流水线。 类似一个3甲医院每天高效完成多个4级手术,得益于分工和流水线。 流水线上每个阶段的医务人员只专职手术的部分工作,如检测,会审,手术和康复。目前AI编程还缺少对分工和流水线的支持,截止到目前为止,AI Loop或者AI Graph 已经在尝试分工和流水线。</td></tr><tr><td style="text-align:left;">缺少权衡</td><td style="text-align:left;">AI模型的智能建立在预测下一个词,依据现有训练数据的一个高概率回答。利用AI辅助软件工程各个环节中,AI给出的答案缺少权衡。比如一个管理系统,使用单体架构和分布式架构,需要基于客户数量,公司预算,基础设施运维能力等多种考虑的权衡。这种权衡通常存在团队的每个人大脑里,很少能直接的,完整的告诉AI大模型。</td></tr><tr><td style="text-align:left;">量变引起质变</td><td style="text-align:left;">AI未能感知软件中量变引起架构变化, 比如响应时间从1秒提高到0.1秒,架构师判断增加部署节点无助于性能提升,可能需要改成微服务架构,或者从无状态改成有状态服务架构以提高性能。AI必须架构师指导才能完成</td></tr><tr><td style="text-align:left;">南辕北辙</td><td style="text-align:left;">如果没有能力驾驭AI编码其正确方向,那么导致AI越快,系统越错,后果可能是屎山代码,不得不推倒重来</td></tr><tr><td style="text-align:left;">锁定AI供应商</td><td style="text-align:left;">由于AI发展非常快,锁定AI大模型或者AI Agent,导致未能使用更先进的AI模型</td></tr><tr><td style="text-align:left;">AI编程耗时</td><td style="text-align:left;">AI编程仍然需要时间,强调使用AI编程后,不再手工编写代码,但忽略为了让AI准确输出,需要时间写的提示词和Skill。这部分仍然需要经验和付出时间</td></tr><tr><td style="text-align:left;">AI固有的问题</td><td style="text-align:left;">对于大型系统来说,Tokens花费较高、AI幻觉存在等</td></tr></tbody></table><p>  因为有了软件工程中使用AI的问题,可能会导致软件系统的第二次危机,即用了AI未能如预期提高交付速度和质量: 表现在系统的研发成本不如预期有很大的降低,交付时间也未能加快,软件系统的质量缺少早期设计缺少权衡,交付质量依然不高。与第一次软件危机类似,第二次危机让然是时间和成本,以及质量的危机。亚马逊团队曾经在全部使用AI后,短时间出现了多个P0故障。解析为因为AI生成代码太快,程序员没有时间去审查所有代码造成的。</p><p>  学过政治的同学都知道生产生产力决定生产关系。传统绿皮火车通常需要3人驾驶,正副司机互为备份,司机操控,副司机负责瞭望和辅助,另外还有个司炉负责提供燃料。 然而,高铁只需要一个人,司机只做确认、操作、应急处置。AI的发展,虽然不会改变软件工程方法,但会改变涉及到角色的职责。 AI会要求团队呈现实现各个都是通才。即同时具备需求分析能力,架构能力和质量的权衡,也具备使用AI 开发以及测试。这样才能解决AI开发带来的问题。 这对程序员来说,既是一次职业跃升的机会,也是一次工作挑战。这AI目前对老程序员来说,更是一次职业续命的良好机会。这也是软件工程,软件架构不会过时的原因。</p><blockquote><p>写到这里,对第二次软件危机判断,其依据基于AI在遵循软件工程时,出现了生产工具和生产关系暂时不匹配的情况。第二次软件危机可能发生,也可能不会发生,取决于团队AI实践。另外,如果未来AI发展,现有的软件工程被颠覆。那就另当别è
30®ºã€‚</p></blockquote>',41)]))}const r=i(h,[["render",p],["__file","index.html.vue"]]),g=JSON.parse('{"path":"/article/se_ai/","title":"第二次软件危机:软件工程、架构、AI","lang":"en-US","frontmatter":{"title":"第二次软件危机:软件工程、架构、AI","tags":["架构","新书"],"createTime":"2026/07/31 13:06:15","permalink":"/article/se_ai/","description":"本书的目的是掌握架构和其关键质量的实现方式,构建高质量的软件系统。架构从多个视角多个层次描述如何构建系统,质量驱动是完成现代软件系统必要的方法。 除了架构外,从另外一个视角看,应用软件工程也是构建高质量系统的路径,实时上,随着软件系统越来越复杂,团队人员较多情况下,软件出现了交付延期,质量低下,即使拥有优秀的程序员,也不能按时保量的交付软件系统。导致所...","head":[["meta",{"property":"og:url","content":"http://ibeetl.com/article/se_ai/"}],["meta",{"property":"og:site_name","content":"闲大赋"}],["meta",{"property":"og:title","content":"第二次软件危机:软件工程、架构、AI"}],["meta",{"property":"og:description","content":"本书的目的是掌握架构和其关键质量的实现方式,构建高质量的软件系统。架构从多个视角多个层次描述如何构建系统,质量驱动是完成现代软件系统必要的方法。 除了架构外,从另外一个视角看,应用软件工程也是构建高质量系统的路径,实时上,随着软件系统越来越复杂,团队人员较多情况下,软件出现了交付延期,质量低下,即使拥有优秀的程序员,也不能按时保量的交付软件系统。导致所..."}],["meta",{"property":"og:type","content":"article"}],["meta",{"property":"og:locale","content":"en-US"}],["meta",{"property":"og:updated_time","content":"2026-07-31T05:33:55.000Z"}],["meta",{"property":"article:tag","content":"架构"}],["meta",{"property":"article:tag","content":"新书"}],["meta",{"property":"article:modified_time","content":"2026-07-31T05:33:55.000Z"}],["script",{"type":"application/ld+json"},"{\\"@context\\":\\"https://schema.org\\",\\"@type\\":\\"Article\\",\\"headline\\":\\"第二次软件危机:软件工程、架构、AI\\",\\"image\\":[\\"\\"],\\"dateModified\\":\\"2026-07-31T05:33:55.000Z\\",\\"author\\":[]}"]]},"headers":[],"readingTime":{"minutes":17.34,"words":5203},"git":{"updatedTime":1785476035000,"contributors":[{"name":"lijiazhi","username":"lijiazhi","email":"[email protected]","commits":1,"avatar":"https://gravatar.com/avatar/1b5114831459724ad4acc394423b4b48ecfa4a7e0659fbe07a0ce5181a1050a7?d=retro"}]},"autoDesc":true,"filePathRelative":"article/架构/se_ai.md","categoryList":[{"id":"92a2b5","sort":10000,"name":"article"},{"id":"9a9aed","sort":10005,"name":"架构"}]}');export{r as comp,g as data};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.