Gund Blog

Software Architecture & AI Thoughts

搞过项目的人都知道,维护老项目比自己搞新项目难度要高得多,做出来的成果还不被认可。

原因是你花费了巨量时间去揣摩别人(甚至比你菜),而不是去关注业务,这很不值得。

这话不是我编的,是每一个被屎山毒打过的人,深夜加班时心里都在默念的话。今天咱们就聊聊这个。


一、那个让我怀疑人生的老项目

我一直在维护一个中台服务——Calculation Hub,一个纯计算引擎。设计目标写得很漂亮:脱离具体业务场景。虚拟电厂、园区能管、设备运维这些上层业务,只需要注册任务、配置四段算子(取值、触发、计算、存储),剩下的计算全交给它。业务系统不嵌入计算逻辑,计算服务也不承载业务档案。

听起来很理想对吧?一个业务无关的计算中台,上层业务随便换,内核纹丝不动。我当时看到这个设计目标,差点感动得给自己鼓掌。

但两年下来,这个”业务无关”的中台,被业务语义渗透成了筛子。

打开提交记录:359 个 commit,横跨一年半,六个开发。每个人对里面的概念都有自己的理解——有人叫它 objectId,有人叫它 identityCode;有人觉得 funId 是功能定义,有人觉得它是业务键。你问他们谁对?他们自己都说不清。metadata 层早就切到了 identityCode + subjectKey,四段表的契约层还停留在 objectId + funId。设计文档里管这叫”残留的最后一处 ObjectId 入口”——翻译成人话就是:改了一半,改不下去了,剩下的先凑合着。

更早的时候,计算能力是散装的:属性公式、告警规则、数据统计、设备上下线推断,分别实现、分别存储、分别触发,各走各的门。后来统一成了四段算子模型,但每个链路——取值、触发、计算、存储——都是不同时期不同人写的,每个人都按自己对业务的理解实现了”自己的版本”。名义上是同一套抽象,实际上是四条完全独立、各自嵌入业务的链路。就像四个人合租一套房,客厅是公共的,但每个人都在自己屋里偷偷改了承重墙。

最典型的一个 bug:设备 DST2608050006 上送了功率 P,但日用电量和月用电量都不更新。排查到最后,根因是写路径上的一行代码:

1
entity.setIdentityCode(dto.getObjectId())

objectId 字段承载的是设备 ObjectId(一串 6a72da34e4b0f0f05ef2ec3e 这样的哈希),却被直接写进了 identity_code 列——而这一列应该存业务键 DST2608050006。于是 registry 里 Energy_Day 的 transform 没有 formula,datasources 为空,公式 P_NEW 永远不执行。日=月,月=日,数据一动不动。

一行代码,一个语义错位,线上数据静默错误。你问这行代码是谁写的?git blame 一下,大概率是某个已经离职的哥们,或者三个月前的你自己。

修这个 bug 花了多少功夫?SP1 契约重构:6 个类 11 处 setIdentityCode(...getObjectId()),7 处 getDeviceBasicInfo 误传 ObjectId,4 处 getStorageConfig 误传 ObjectId,外加 8 张表的数据回填 SQL。而这还只是第一步——后面还排着 SP2 的 Device*/Product* 改名、SP3 的缓存架构治理。一个 bug 修出一个重构三部曲,就问你这福气要不要。

那一刻我悟了:维护老项目难,难的不是技术,是你得先解码别人的混乱。 而这个项目里最扎心的是,写这些代码的人不是不会写,是每个人对”中台”的理解都不一样。你花在解码上的每一分钟,都不是在创造价值,是在替不同时期的不同理解还债。


二、老项目是怎么变成屎山的

那问题来了:老项目是怎么一步步变成屎山的?Calculation Hub 只是其中一个例子。

不是没人设计过。是设计的时候,压根没把”业务会变”这件事当回事。

我见过太多这样的场景了:

产品原型画成什么样,数据库就建什么样。产品经理在 Axure 里拖一个输入框,后端就加一个字段;画一个 tab 页,就建一张表。美其名曰”快速响应需求”,实际上是把数据库当成了产品原型的像素级复刻。屎的形状,取决于产品经理那天画原型时喝了几杯咖啡。

需求说”订单要支持发票信息”,就往订单表塞一个 JSON 字段。需求说”要记录优惠券核销”,再往同一个 JSON 里塞一个数组。半年后打开线上一条订单,里面是一坨 4KB 的 JSON,套娃套了三层,没人知道哪些字段还在用、哪些是历史遗留。你以为你在做”灵活设计”,其实你在做”向未来的自己拉屎”。

状态用八个布尔值表达,因为”语义清晰”。八个布尔值有 256 种组合,合法的业务状态只有 12 种,剩下 244 种全是非法状态——但代码里没有任何地方约束它们不能出现。于是线上 bug 永不绝迹,用户发邮件骂:”为什么我的订单显示已付款已取消已发货未退款?” 你回邮件说”这是系统设计如此”,然后默默去改代码。

当时省下的每一分钟建模时间,后来都以”每月两次线上故障”的形式还了回来。利息高得吓人,堪比高利贷。

为什么会这样?因为没有向上抽象的思维。没有人向上问一句:这些字段在业务上究竟是什么关系?发票是不是一个独立的领域实体?订单本质上是不是只有一个状态属性?

没有人问。因为问这些问题需要抽象思维,抽象思维需要动脑子,动脑子累。照着原型建表多轻松啊——屎来伸手,屎去张口。

这就是没有架构设计的代价。但更准确地说,是**没有”基于业务思考的架构设计”**的代价。


三、架构设计的本质:预判变更

工程项目业务是关键。这句话我越做越觉得是真理,就像”钱不是万能的,但没有钱是万万不能的”一样真理。

很多人对架构设计有误解,觉得架构就是画漂亮的 UML 图,就是选一个时髦的框架,就是把微服务拆得越细越高级。都是扯淡。你见过哪个架构师靠画图吃饭的?画图是给领导看的,架构是给业务扛雷的。

架构设计的核心就一件事:预判后续变更。

怎么预判?按变更频率分三类,每一类对应一条原则:

高频变更——易开发(DRY)

业务里天天变的逻辑,比如价格计算、状态流转、权限规则、优惠策略。

这类变更如果散落在十几个地方,每次改需求都要全局搜索、提心吊胆,改完这处忘了那处,上线就出事故。DRY 的意义从来不是”代码写得优雅”,而是让高频变更只改一处

改一处,测一处,上线一处,十分钟搞定。散落各处,改十处,测十处,上线提心吊胆一整天。同样是改一个需求,前者是日常,后者是渡劫。

中频变更——可扩展(里氏替换)

业务里隔三差五会加新类型的变更,比如支付方式、消息渠道、第三方对接、营销活动类型。

这类变更你预判不到具体是什么,但能预判”它一定会来”。里氏替换的意义是:新加一个实现类,老代码一行不用改

今天接微信支付,明天接支付宝,后天接抖音支付,都是往注册表里加一行的事。如果你当初把支付逻辑写死在订单服务里,每接一个渠道就是一次伤筋动骨,改完还要担心把老渠道搞挂。就像换灯泡,接口统一了,拧下来拧上去的事;接口不统一,你得把整个天花板拆了。

低频变更——影响可控(模块化/依赖接口)

业务里几乎不变的,比如底层存储、消息中间件、第三方 SDK、基础设施。

这类变更几年才碰一次,但一旦碰就是大手术。模块化、依赖接口的意义是:换数据库的时候,业务代码一行不用动;换消息中间件的时候,只有对接层在变。影响范围被隔离在一个模块里,而不是炸穿整个系统。

你看,这三条没有一条是”技术”问题,全是”业务”问题。

DRY 的前提是你知道什么会高频变;里氏替换的前提是你知道什么会中频变;模块化的前提是你知道什么会低频变。而知道什么会变,只能来自对业务的理解。

技术方案是术,业务判断是道。术可以学,道只能悟。


四、AI 时代:架构设计不是不重要了,是更重要了

现在说 AI。

AI 时代最根本的变化是什么?写代码的成本趋近于零了。

以前一个需求,方案想三天,代码写两周。现在方案想三天,代码让 AI 三个小时生成完。AI 把”执行方案”的成本打到了地板上,但”想清楚方案”的成本一分没降——反而更贵了。

为什么更贵了?因为以前架构烂,还有编码成本这个缓冲垫。代码写得烂,至少写得慢,屎山堆积的速度有限,你还有机会在堆到三层的时候停下来想想。

现在呢?AI 一秒钟生成 200 行代码,你审查的速度根本跟不上。烂架构 + AI = 屎山加速器。以前三年堆一座屎山,现在三个月就能堆一座,而且每一层都”看起来挺规范”——命名规范、结构清晰、注释齐全,单看每一层都挑不出毛病。就像预制菜,每一份都包装精美,凑一桌就是灾难。

我上一篇说过,AI 是放大器。能力 100 的人用 AI,是 1000;能力 10 的人用 AI,还是 10,甚至 1。架构也是一样:好架构 × AI = 生产力爆炸,烂架构 × AI = 灾难加速。

更可怕的是 AI 生成代码的特征:局部极其优秀,全局稀烂

你让 AI 写一个模块,命名规范、逻辑清晰、边界条件都处理了,单看质量比很多 junior 写得好。但十个模块拼在一起,风格不统一、接口不对接、数据流没人说得清——因为每个模块都是独立生成的,没人对”全局”负责。

就像十个装修工人分别装修了同一套房的十个房间,风格不统一,走线不对接,承重墙的位置没人对齐过。这个比喻我在上一篇《Code is cheap》里用过,用过了就用过了,好比喻不怕重复。

而”全局”,就是架构。

所以 AI 时代,架构设计不是不重要了,是更重要了。以前架构的价值被编码成本稀释——反正代码要人写,架构烂一点,多花点时间总能磨出来。现在编码成本没了,架构烂,AI 会以十倍速度把烂架构变成烂系统。你连”磨”的机会都没有。

以前的技术债是”为了赶工写了烂代码”。以后的技术债是”为了赶工生成了太多没人审查的代码”。病因不同,症状一样——系统变得不可维护,而且不可维护的速度,快了十倍。


五、架构设计靠什么:业务思考,和人聊天

那架构设计靠什么?靠技术深度?靠设计模式背得熟?靠画图好看?

都不是。靠的是业务思考

但业务思考不是坐在工位上憋出来的。憋是憋不出来的,你对着需求文档憋三天,憋出来的还是需求文档。我总结下来,架构设计是这么个流程:

第一步:跟正确的人聊天,谈星星谈月亮

预判变更,你得先懂业务。懂业务,你得先和人聊天——和产品聊,和业务方聊,和用户聊,和一线运营聊。聊他们现在怎么干活,聊他们哪里痛,聊他们接下来想干什么。

注意,是”正确的人”。跟错误的人聊天,聊三天三夜也是白聊,还搭进去一顿饭钱。正确的人是谁?是那个真正在业务里摸爬滚打的人,是那个被业务痛点折磨得睡不着觉的人,是那个能说出”我们其实想干的是这个,但一直没说出来”的人。

而且聊天要”谈星星谈月亮”——不是拿着需求文档一条条对,是聊业务方的野心、恐惧、KPI,甚至他们老板的老板在想什么。变更不是凭空预判的。变更的种子早就埋在业务方的脑子里了,只是他们自己还没说清楚。你天天闷头写代码,看到的只有”现在”;你走出去和人聊天,才能看到”以后”。

第二步:回到家,夜深人静时,自己思考

聊天聊完,信息是散的。业务方说了一百句话,有用的可能就三句,而且这三句他自己都没意识到。这时候你得回家,夜深人静,把今天聊的东西在脑子里过一遍。

向上抽象。把”我们要支持抖音登录”抽象成”第三方登录是一种会持续新增的认证方式”;把”订单要支持部分发货”抽象成”订单状态是一个会持续演化的状态机”。业务方说的是具体的事,你要听的是抽象的模式。

这一步没人能帮你。白天你可以和人聊天,晚上只能自己面对自己。就像练内功,师傅能教你招式,但真气得自己运。

第三步:浸入骨髓的设计模式和架构思维,无招胜有招

抽象完了,怎么落地?这时候设计模式和架构思维就派上用场了。但注意,是”浸入骨髓”的——不是背概念,是它们已经长在你脑子里,遇到问题自动浮现。

就像独孤九剑,风清扬教令狐冲的时候说:你学剑招,不是为了用剑招,是为了忘掉剑招。真正的高手,出手的时候脑子里没有招式,只有对局势的判断。架构设计也一样:你学 DRY、学里氏替换、学模块化,不是为了在画图的时候一个个对照,是为了让它们成为你的本能。遇到一个需求,你不需要想”这里该用策略模式还是模板方法”,你直接就知道该怎么切。

这就是无招胜有招。招式是死的,业务是活的。你把招式练到骨髓里,才能用活招式去应对活业务。

这也是为什么维护老项目那么痛苦——因为当初设计它的人,大概率没和正确的人聊过天,也没在夜深人静时向上抽象过。他对着原型建表,对着需求写代码,把每一个”现在”都固化进了系统,唯独没想过”以后”。于是”以后”的每一次变更,都变成了一次考古。


六、结语

AI 时代,写代码的门槛被 AI 踩平了,但架构设计的门槛反而更高了。因为当代码变得廉价,唯一值钱的就是”知道该写什么”。

架构设计,就是那个”知道该写什么”。

别把时间花在揣摩别人的屎山上,也别把时间花在让 AI 更快地堆屎山上。把时间花在理解业务上,花在预判变更上,花在和人聊天上,花在夜深人静时和自己对话上。

代码会过时,框架会过时,AI 也会过时。但”预判变更”的能力不会过时——因为只要业务还在变,架构设计就永远是最重要的护城河。

:::info
架构设计的本质是预判变更,预判变更的前提是理解业务,理解业务的途径是跟正确的人聊天,然后在夜深人静时向上抽象,把招式练成修为,无招胜有招。
:::

什么是设计模式

设计模式 其实早已是烂大街的词了, 你媳妇听到了也很可能问你一句:”设计模式?你们一群电子屎壳郎, 天天的在键盘上爬代码屎山还不够?怎么跟搞装修的似的?”.

以上虽然是个笑话, 也表现出来在实际的工作中大家对于设计模式的态度, 哪怕到不了欲拒还迎, 敬而远之的程度, 起码也会认为是个比较难以掌握的技能. 以下有两种学习的情况:

  • 每次鼓起勇气去接触和学习(带着畏惧又抵触的心态). 同时又选了一些晦涩难懂的资料去学习, 被各种概念名词轰得七荤八素, 头昏眼花, 学习过程体验还不如当电子屎壳郎, 只好草草放弃.
  • 另一种情况, 平常做crud的时候, 用的都是成熟的开发框架, 大部分时间只需要遵从框架要求的开发规范即可(黏贴复制), 稍微高级点儿的编程技术压根就用不上, 长此以往, 别说设计模式, 面向对象的三大特征都忘了, 如果不是为了面试, 都懒得看一看设计模式每个模式都叫啥, 更不要说思考每个模式的适用场景了.

设计模式说白了就是解决问题的方式方法(方法论). 约会要AA, 打游戏要4090, 灯泡不能塞嘴里等等都是日常非常典型的生活模式. 设计模式也是同样的简单概念,

生活中遇到问题后, 先辈们为了解决问题找出了应对方法, 久而久之得到了认可和推广, 总结为解决这类问题的处理模式.

那么到了研发体系中, 研发过程中碰到的99%的问题(太阳底下没有新鲜事), 我们的前辈们都在无数的项目中解决过无数次了, 总有高手把之前遇到的问题及其解决方案进行归纳总结, 把编程过程中最经常碰到问题的解决思路提炼出来, 作为结论整理成所谓的设计模式.(但是很多问题我们碰不到, 也就没办法理解问题到结论的推导过程, 直接被灌输了结论, 理解起来确实存在难度).

至此, 大家不要把设计模式想得太高大上. 相反, 它就存在于我们的日常工作中, 因为它本身就是为解决我们日常工作中遇到的问题而存在的. 在我们试图寻找解决某些需求问题的设计方案时, 殊不知, 我们当前所面临的所有难题, 在业界上早就有无数的先辈给出了成熟的方案. 你学或不学, 它就在那里, 等待你发现它的好(或等你重复发明轮子后还不如它之后嘲笑你). 大部分的设计模式, 其实都非常简单, 看过之后甚至会嗤之以鼻: “这破玩意儿也好意思归纳成一个模式, 我都用了多少年了”.

那么,为什么要加上 “设计” 这两个字呢?为什么不直接叫 “编程模式” 呢?要回答这个问题,咱们还得回到面向对象。我们使用面向对象思想进行工作的时候,尤其是进行复杂业务逻辑产品开发的时候,要经过以下几个大的阶段:

项目立项 - 获取需求 - 需求分析 - 系统分析 - 系统设计 - 程序开发 - 测试 - 项目交付

当然在这个基本流程中, 其中某些过程可能会发生反复和迭代, 但这不是我们本次讨论的重点, 我们重点看 “分析” 和 “设计”, 对应于我们面向对象语言, 我们有 OOA(Object Oriented Analysis) 和 OOD (Object Oriented Design), 说到这里我想大家应该明白设计二字是从何而来了. 是的, 设计模式是编程思想, 是别人的先验之经验, 设计模式主要就是在 OOD 面向对象系统设计这个阶段使用的. 不要简单的认为这个阶段就要大规模敲代码了, 对于复杂的系统来说, 这部分消耗的时间和精力要高于程序开发阶段的. 这个阶段出了问题, 后边参与的人再牛X也只是徒劳, 他们一边吐槽一边想着人和代码有一个能跑就行.

额外提一句

对于很多新手或没有接触过大型项目的人, 安排给他们的工作都是被放在被设计好的位置上开发或者维护已经设计好的模块或者小的功能点上, 基本不可能看到整个项目是如何从 0 开始逐步成形的, 最悲剧的就是工作多年后, 依旧没有接触到更高一级的东西, 人会越来越没有信心. 如果长时间的工作经历让一个人在专业领域里面没有足够的积累和筹码支撑的话(这就是面试时常常碰到的一年经验干了十年), 对个人来说这人心态就崩了, 职业生涯就到此为止了. 所以衷心建议趁年轻, 多学点东西, 总是好的, 哪怕现阶段甚至未来两三年也用不上也不能成为不学习的理由. 当我们只能看到 CRUD 的时候, 我们也只能学会 CRUD, 最终也只能成为CRUDer. 说一句特别特别俗套的话: “不要用一个锤子去解决你遇到的所有问题”.

软件工程绝不只是一帮人在玩理论炒概念, 是因为软件开发中需要解决具体的技术问题, 同时还叠加了世界上最为复杂的人类问题和社会问题, 我认为软件工程本质上就是在从OOD的角度对社会生产生活中的问题进行抽象处理并给出设计模式的过程, 这话说得太形而上学了, 反正就这么个意思吧. 《人月神话》之所以长胜不衰, 是因为其中所讨论的问题永远也不会找到解决方法, 不是解决不了技术问题, 而是解决不了人和如何组织人的问题.

说这么多希望大家已经知道什么是设计模式了, 后面我们不光要知道什么是设计模式, 还要知道它在项目中的哪一个阶段应用. 我们一定要培养面向对象的思维, 而不简单的停留在代码这个维度, 代码只是重点解决了 程序开发 阶段的问题, 整个项目其实是一个严格推导的过程, 一个项目中, 应该定义哪些类, 定义哪些接口, 设计哪些模块, 如何分层, 都是推导出来的. 那上来就给几个破图, 啥也别问, 照着干就完了的工作方式, 不是在解决问题, 而是在生产 Bug, 在给后人挖坑, 给事业埋雷.

学会设计模式有哪些好处?

我们说说学会设计模式有哪些好处. 那么这里就有一个非常重要的前提: 学会, 到底怎么才算是学会呢? “学会” 的标准又是什么呢?不要笑, 这真的是一个值得考虑的问题, 这绝对也是大部分初级面向对象技术人员都会面对的一个问题.

我们都知道所有的设计模式都基于面向对象的理论或者说基本思想实现的. 因此首先你面向对象的基础砸得要足够坚实, 对面向对象的编程思想要有足够得认识和深入些的理解, 而不是靠记忆背出来的面向对象, 这一点很重要. 一些人员看了些书之后会说: “我知道什么是CQRS了, 我知道什么是工厂模式了, 我知道什么是继承多态了…….” .

“我知道”绝大多数情况下都是谎话, 要么是我们觉得自己知道了, 要么是让别人以为自己知道了, 在真正的实践中, 我们其实是不知道的, 很可能只是我们记住了一点点东西而已, 然后装知道. 就像考试做错的题, 媳妇让你洗的衣服, 讲了又讲, 反反复复, 你好像是知道了, 无论给你多少次机会, 还是会做错, 明明 “我知道” , 可怎么就还是不会呢?有的东西不是靠记忆的, 要看实践, 不能只背不悟不实践. 在此搬出领袖的一句话:”实践是检验真理的唯一标准”. 附上我刚入行时, 我的总监告诉我的一句话:”不要聊也不要看, 自己动手做一遍就会了”.

这句话很土, 但话糙理不糙, 很适合咱们现在讨论的问题. 很多学习者没有掌握学习设计模式的正确姿势. 什么问题呢? 设计模式对应的问题场景的识别, 也就是案发现场的分析问题. 如果连案发现场是怎么一回事都不知道, 上来就要直接破案, 那就是乱搞胡猜嘛.

每一个设计模式是为解决某一类问题而制定的解决方案, 能否识别出问题场景对于”学会”至关重要, 而大部分人在学习的时候, 很多都是走马观花看看概念, 然后就直奔代码实现而去(神马DDD没有能够落地代码框架, 那老子学个屁). 这样的学习者只想看尽快搞懂代码, 学会几个名词, 然后自我满足得陶醉一下, 回头可以吹个牛逼. 至于为什么要这么解决问题, 解决了什么问题, 不这么做会有哪些风险? 他很难回答上来. 例如: 我们看别人滑雪的时候, 就简单的几个动作而已, 而我们自己到了雪上才会真正体会到我们需要克服的困难太多了, 首先如何保证自己不恐惧, 保障自己不摔倒, 保障摔倒的姿势够帅等等都是基本的要解决的问题, 而以上只是开放的雪场里学滑雪这个场景你会遇到的问题. 珠穆朗玛峰, 南极北极, 又是不同的场景, 存在不同问题, 而你的应对之法则会完全不同, 你的”设计模式”也会完全不同.

我们总是在说复用, 复用公共组件, 复用前端组件, 我们复用了太多代码层面的东西. 设计模式能够让我们复用(复制)别人的解决方案, 复用(借鉴)别人的编程思想和先进经验, 等到自己能够真正掌握, 就会”顿悟”, 就可以做到一个打十个, 任何业务难题, 任何技术场景到你手里都能迎刃而解. 反之, 你将永远也无法进入到下一个层次, 在这个行业中, 始终停留在初级阶段, 就会被后浪拍死(这就是常说的搞技术的年龄上限), 留给失败者的只有被淘汰的痛苦伴随一生.

设计模式间的区别

GRASP 是 General Responsibility Assignment Software Patterns 的缩写, 江湖上的兄弟们比较流行的叫法是”职责分配模式”. 虽然最后一个单词是 Patterns, 但是等把 GRASP 所有的东西学完之后, 你会发觉 “模式” 这个说法不怎么恰当, 与其说是模式, 不如说是一些原则和指南. GoF 23 那一堆东西才是严格意义上的模式, 而且是系统设计阶段采用 OOD 方式的设计模式.

主要看一下 职责分配 这四个字, 这四个字才是 GRASP 的精华所在, 我们现在需要把 “职责分配” 在项目的生命周期中做一个基本的定位:

项目立项 - 获取需求 - 需求分析 - 系统分析 - 系统设计 - 程序开发 - 测试 - 项目交付

职责分配发生在哪个阶段呢, 需求调研、需求分析、系统设计 这三个阶段. 在需求调研这个阶段, 我们会得到系统中的责任人(有时也叫干系人) , 责任人/干系人这个专业词语最早出现在项目管理学中, 不要畏惧新名词儿, 都是纸老虎. 比如项目上出现了问题, 我们总说某个人在这件事上逃不了责任, 责任人的”责任”跟这里的责任其实是一个意思. 责任人就是使用我们软件产品的所有人(或角色), 比如用户, 系统的管理员, 运营人员, 老板, 老板娘等等. 除了责任人, 我们还会在这个阶段得到 责任事 (也可能是在需求分析阶段分析出来的), 当然这是我从责任人发明的新词, 意思就是相关责任人在软件中负责的功能. 不管是人还是功能或者说业务, 它们都需要进行 “职责分配” , 而职责分配不是拍脑袋乱来的, 这里面是有套路在的. 不同的人有不同的权限和责任, 不同的业务有不同的规则和流程, 哪怕是相同的业务因为责任人不同也会变化规则, 这话说起来圈圈绕绕的, 其实道理很简单, 普通玩家和人民币玩家永远都不是一个物种. 在现实世界中 “人”、”事”、”职”、”责” 是怎么回事, 到了软件系统中, 也是那么回事, 我们不过就是把现实世界的规则通过逻辑进行了数字化. 只有分析清楚了 “人”、”事”, “职”、”责” 之后, 才能谈到 职责分配.

以上内容搞清楚后, 才能进行 系统设计程序开发. 大家都应该知道, 业内失败的项目占所有项目的比例其实是非常高的, 很多软件项目其实还没有开始的时候就注定会失败, 因为 “职责分配” 是超出软件开发范畴的, 如果一家公司想把某条业务线信息化, 那这家公司内部本身的 “人”,”事”,”职”,”责” 等等必须都是清楚明白,且执行到位的才行,如果它自己内部本身就是一团浆糊,人浮于事,人与人之间,部门与部门之前,职位与职位之间界限不明,责任不清,遇事推责揽功,宫斗不断,就不要指望这类公司的项目能做成,必定是失败的项目. 而很多无良的软件公司通常喜欢这样的项目,因为项目失败的 “责” 不在自己身上,只要配合这类公司的项目负责人”演戏”,任由他们修改需求,把项目周期无限制的拖下去即可.

最讽刺的是

技术人员即便在这种混乱的项目中也能把 “职责分配” 做好,因为技术层面上,会排除具体人的因素,而是以 角色,流程,规则 等等逻辑方式去解决问题,摒弃了人情世故,鸡鸣狗盗,世态炎凉的社会化问题,因此这类项目也能完成和交付. 至于交付之后,他们用不用,能不能坚持用,就是另外一回事儿了,但是这种项目哪怕交付了,这也不能算是成功的项目.

在逻辑层面上,GRASP 着重考虑的就是 “对象” 的 设计原则 及其 职责分配,而 GoF 设计模式则主要考虑 OOD 阶段设计如何实现,对象与对象之间如何交互,程序结构如何更加健壮,易扩展,易维护. GRASP 是 GoF 设计模式的前提,GoF 设计模式就是符合 GRASP 模式原则要求的面向对象的设计模式. GRASP 是独孤九剑的心法总纲, 是路线规划方案, GoF 就是具体的剑法招式, 是根据规划制定好的具体可实施的路线了. 这是它们之间最根本的区别.

GRASP核心概念详解

General — GRASP 的原则是通用的、广泛适用

GRASP 所说的良好的职责分配原则是放之四海而皆准的,并不狭隘的限于软件行业内,这也是为什么有些公司的项目还没有开始就注定要失败,因为如果公司内部本身就是权责不明,事理不清,宫闱恶斗。这样的公司要实现公司业务数字化,信息化,基本就是在浪费时间和金钱,除非先把自己内部的问题解决清楚才行。

Responsibility — 责任,职责,义务

其实严格来说,只采用单词原意 “责任” 或 “职责” 是不够的,”权责” 似乎更为妥当。程序中的实体或者功能模块应当具备那种职责,负责什么,都需要分析清楚。现实社会中,不管在家庭还是公司或者某个组织内,我们的职责就是 “维护世界和平”,听着挺扯蛋是吧,但是仔细想想的话,不管是国家,政党,机构,家庭,人,我们做的所有事情无论大小不都是保障世界在现有格局和规则下平稳运行吗?所以虽然扯点蛋,但扯得力度并不大。

Assignment — 责任分配,职责安排

职责如何用更为合适的方式分配给指定的类或者模块是 GRASP 最核心的部分,分配职责的时候有很多的策略和方案。要介绍的 9 大要素,其实就是从9 个方面的大原则。根据这 9 个大原则,我们就可以将职责和负责这个职责的对象(模块|系统)更好的组织在一起,为以后的程序设计阶段打下坚实的基础。

Software — 软件

这个就不用说了, GRASP 本就是专门服务于软件行业的一种技术手段.

Patterns — 模式

可以说 GRASP 就是衡量一个设计模式是否是一个好的解决方案的标准. 比如分层是否合理,因为分层就是在分工,分工就是在搞 “职责分配”,逻辑处理应该放在哪层?信息显示该放在哪一层?为什么现阶段大部分软件项目采用的三层架构设计(数据访问层,业务逻辑层,界面层)?这些问题的答案,咱们都可以从 GRASP 倡导的原则中找到其中的部分答案. 如果没有统一的原则作为指导, 一个公司的架构设计人员也会在刀光剑影中争论不休. GRASP就是衡量我们设计的标准.

GRASP 对于面向对象的系统分析和系统设计具有重大的指导意义,有了它咱们就能把 “什么人该在什么位置做什么事” 这个老大难的问题解决好。面向对象的设计过程就是将责任分配给对象的过程。下面把 9 个要素罗列一下:

职责到底是什么

本篇一直在说 “职责分配”,那今天咱们就把 职责 讲明白,吃透了 “职责”,后边的那些内容就很容易搞定了。

职责概念内 有 认知职责行为职责 这老哥们. 巧合的是, 世间最难做到的事恰恰也是 “知,行 “二字. 恰恰就是由明朝的大牛”王阳明”, 得出 知行合一 的终极指南.

先说 认知职责 吧,我们常说 人贵自知,人要有自知之明,这真的很重要. 然而经常出现的场景是:”你说的道理我都懂,但是让我干我一个也不会”,知行合一太难了,上嘴皮碰下嘴皮相对简单多啦(当然能讲出来也没这么容易, 不然您来讲一课试试?),人人都知道该怎么减肥, 但是要你每天5点晨跑那可真要命了。

到了程序的世界里,我们在 OOA 和 OOD 阶段,就是在分析 “对象” 要有自知之明这个事情,虽然作为人类我们很难做到 “知行合一”,但是我们分析和设计好的 “对象” 却能完成我们创建者无法达成的 知行合一(现实世界虽然不完美, 但是我的代码是完美的)。

那如何做到 “自知”(认知职责)呢,那首先要对自己所拥有和管理的信息(对象的属性)有足够的认知, 这是一个分析建模的过程, 比如我们相亲时: 可以对对方建模,身高 170,体重140斤,皮肤很白,这就是一个很朴素的认知。

认知职责共有三重境界:”见天地”,”见众生”,”见自己”。看起来就不严肃啊,是我瞎编的 哈哈。你知道自己的身高,体重,性别,特长等等,这些只是认知职责中最低的境界 见自己,对应的就是面向对象中属性的概念,一个对象能够了解到自己的属性就像一个人知道自己的身高体重,这是它的本分,没啥好骄傲的,认知职责的第一重境界 “见自己” 看起来还是比较容易的哈.

然后就是第二重境界:”见众生”,说的是对相关对象的认知,相关对象并不是一个难以理解的概念。之前说过,程序世界就是现实世界的映射,不光是简单的静态的事物的映射,更是社会规则关系的映射。虽然在程序世界中,我们可以突破物理规则的约束,但是突破不了人类思维模式。而说到社会规则,其实说的就是人与人之间,组织与组织之间,人与组织之间的关系, 规则和流程。在面向对象的理论中,我们同样也会定义 对象与对象之间的关系,大家可以回忆一下面向对象的关系都有哪些?

对象间关系

继承、实现、依赖、关联、聚合、组合

想到一对多, 多对一, 一对一的同学请自觉找书复习, 基础太差了哈

在这个境界我们就不光要知道本身的属性,还要能 “了解” 到关联对象。这里有直接关系,也有间接关系,但是不同”对象”之间的关系必须是清晰明确的。比如说 在某宝下了 3 个订单,那 某宝的这个账户对象就应该能 “认知” 属于自己的这些订单。而通过这 3 个订单呢,也可以知道是谁下的单,在设计对象的时候使用关联关系就能够很容易的实现这个功能了, 我相信这是大家都能够理解且日常工作中反复实践过的.

最后呢说说 “认知职责” 中最高级的境界:”见天地” . 有些相关联的事物无法直接获得,没有直接或间接的关系进行关联,但是却能够通过 某种方式方法推导或者计算出来. 你知道自己处于天地万物的哪个位置, 也可以根据天地万物的任意对象找到你,如果我们不了解自己, 也不了解身边的人和事,没有身边的人作为衡量标准,我们又如何对自己做评判和定位呢?课本上说过一只坐井观天的青蛙,当我们无法与这个世界联系的时候,就会非常悲剧的无法对社会和自己进行基本的认知,认知都出了问题,又何谈行动?

通过上面的一通废话,希望大家已经知道职责中的 认知职责 是怎么一回事了。我们解释清楚了认知职责后,行为职责就非常容易理解了,一个对象的行为必然”不是跟自己相关”就是”跟与自己关联的类对象相关”,这个时候贴出官方极为晦涩的定义和描述了,对象的行为职责包括:

  • 自身执行一些行为,如创建对象或计算
  • 初始化其他对象中的动作
  • 控制和协调其他对象中的活动

最后说一句知行合一是一个很难达到的境界,真的难在”行”吗,很多情况下,可能还是因为我们无知,或者说咱们并不是真的”知”,只是在自以为是而已

信息专家 Information Expert

提到专家, 这个词已经变成了不可信, 脑残的代名词. 因为那些所谓的专家经常发表的”奇谈怪论”, 让我们目瞪口呆, 挑战智商和社会的底线. 那么这些专家真的是脑残吗? 他们又为什么会说出这么多脑残的发言?

答案在于 “跨界”, 搞围棋的非要去讨论AI, 手机的KOL接了个特斯拉的单子, 售前去讨论机房建设. 其结果大家自然会觉得离谱.

那么问题就来了, 所谓的专家. 一个重要的标志就是 “信息” . 专家必然是在某个领域里面掌握 “信息” 最多的人, 他们拥有”信息”的质量和层次是一般人所不能比的. 讲到这里, 大家回看一下标题, 是否能对 “信息专家” 有一个大概的认知了, GRASP对于信息专家的专业表述: “如果某个类能够完整表达某方面的信息,足以实现某个责任,那它就是可以拥有这个职责的信息专家“. 不知大家对于这段话的感觉是怎样, 想必有些人是要摔键盘的, 请举起键盘的哥们先等一下, 思考一下几个问题: 键盘是你的吗? 如果是公司的你有资格摔吗? 它是你的”信息”吗? 你是它的”信息专家”吗?”摔键盘”这个行为是我的”职责”还是公司的”职责”?

这些问题综合起来就是 “信息专家” 的内涵, 很多技术研发出身的人员之所以不能领悟很多技术概念, 不在于他们技术能力差, 而是太专注技术层面, 或者说太专注”代码实现”了. 而绝大部分技术问题,都可以从社会问题上找到答案. 让最专业的人干最专业的事,这是普遍被认可的一条社会效率法则,而社会分工体现的恰恰就是职责分配, 当然社会分工也会存在问题, 比如很多人分配到的职责, 但未必表现的 “专业”,能够做到 “专业” 的人只有很小的比例。但是到了软件领域则不同,我们分析出来的对象它必须要是绝对的”专家”,绝不能 “跨界”,因为超出的部分不是它的职责,这也体现了SOLID编程原则中 “单一职责原则” 的精神,但是 “信息专家” 原则并不能简单的等同于 “单一职责原则” ,因为 “信息专家” 表达了更丰富的内容.

解释一下信息专家与单一职责

为什么说”信息专家”并不单纯指代”单一职责原则”?为什么”信息专家”的内涵更丰富?那咱们还是要回到项目的阶段中,我们之前说过,GRASP 重要在项目的 需求调研 - 需求分析 - 设计 三个阶段中起作用,但 SOLID 原则 和 GoF 设计模式 都主要在系统设计阶段使用。而需求分析和系统分析时最重要的事情就是识别出能够描述业务场景中具有关键作用的对象,并抽象出”类”。GRASP 的”信息专家”原则恰恰就是在这个过程中寻找对象并分配职责的最重要的方式方法,这项工作完成的质量好坏,直接决定了项目后续阶段能否高质量的完成。这也是为什么”信息专家”是GRASP最重要的原则,也是为什么它是排在第一位。

不止体现”专家”的概念同时”信息” 二字也非常重要,对象封装的全部 “属性” 定义了这个对象是哪方面的”专家”,似乎这话还是有点绕. 讲的再直白一点, 很多情况下 “数据” 本身并不等同于信息,比如数字 250,我们不知道它代表什么,如果它是 “智商” ,那智商 250 就能够表达某一项信息(智商信息),这是一种粒度很小的信息;如果 User 对象只有这么一个属性数据,那它还不能”完整且充分”得表达出这是一个人信息。我们现在要得是 “某一方面” 的信息,但是我们可以翻译一下 “某一方面” 为 “必要属性”。”一个智商 250 的名叫王大牛的超级帅哥产品”这表达出来的就是完整的描述一个人 “这一方面” 的信息。那我们可以抽象出一个类 User,它在当前的这个系统中,必须要负责管理的数据就是 用户身高(250),用户性别(男),用户姓名(王大牛),用户职业(产品),用户技能水平(超级帅)。那其他的数据不要了吗?比如出生年月,手机号码,电子邮件,如果这些数据项当前的项目完全用不到,那它们就不是必要的属性,”用户”这个”信息专家”也就没有”职责”去管理这些信息并为它们劳心劳力。

而到了能管系统中,企业的名称,营业执照,营业范围,设备档案等则会成为”传递出这具体是一个什么样企业这个关键信息的”必要属性。然后企业,设备,场景等等是咱们比较容易想到的能管系统中的信息专家,它们职责分明,分工合作,共同构建了”能管系统”的基础。设备就是负责设备信息的,不能闲的没事去修改企业封装的数据,企业也不能越俎代庖的去修改采集记录的数据,要修改的话,也得”设备”去修改,不是你的键盘,不要随便摔。

低耦合 Low Coupling

低耦合 是我们耳朵听出茧子的一个专业名词了,做不到低耦合,谈何权责明晰的职责分配,如果连你、我之间的边界都不清晰,谁都想做别人的主,那岂不是满大街都是土皇帝了?

问开发人员什么是耦合, 他们心中一定闪回了, 上回改别人的代码时, 改一行代码重构了整个项目的车祸现场, 牵一发动全身就是高耦合, 反着来就是低耦合咯

但是我们前面已经有了专事专做的信息专家了, 追求低耦合是要解决什么问题呐?

“减少因变化产生的影响”

其核心工作就是要减少 依赖性(如: 类与类之间的依赖,对象与对象之间的依赖,组件与组件之间的依赖,系统与系统之间的依赖),只要依赖性降低了,目标就达到了一半,另一半则是要提升重用性和扩展性。

面向对象编程是我们常说的装B词汇之一, 常用的java也是号称面向对象的语言, 但是真正的开发过程中大部分人采用仍然是 针对具体页面的过程式编程, 原型ui上有个什么样子的表单, 要进行crud, 设计一个一模一样的数据库表, 然后把保存和查询的过程coding出来.

这套流程很简单, 我们玩的很熟练. 但是我们应该真正的从业务出发, 提炼出业务中的不同功能模块, 体现模块核心价值的对象, 再封装标准规范的接口, 学会面向抽象的对象设计, 面向标准接口编程, 而不是拘泥于具体的原型ui.

面向对象中的 “继承”、 “组合”、”接口” 等等是实现 “低耦合” 的重要手段, 在我们日常的coding中却非常罕见, 让我常常考虑改用php是不是更好. (PHP is the best language for web programming, but what about other languages?)

无法达到低耦合的目标, 有两种情况:

  1. 程序的设计者, 没有很好的识别出业务中可变和不可变的部分. 如果要做的系统本身非常 “稳定”, 系统间, 模块间, 对象和数据都可以按照一万年不变的方式运行, 绝对不会有任何变化, 那么再高的耦合度都无所谓. 这么讲其实是想说, 我们常常需要在降低耦合和封装之间进行权衡和取舍, 不太可变的部分, 耦合就耦合吧, 为了效率偶尔牺牲一些扩展性和可维护性. 但是对于大概率会变化或需求不确定的部分, 请对自己好一点, 耦合一定要低一些, 要不然晚上通宵, 周末加班的一定有你, 而且导致你通宵到天亮的凶手不是别人, Just Yourself !(这也是为什么新人或者新业务开发时加班会比较多的部分原因, 经验和实践的不足, 设计开发出来的东西只能满足当前短期的需求, 一旦出现更多的场景或变化, 程序马上就搞不定了, 需要彻底推翻重来. 我第一家单位的总监面试时最关注的一点就是: 这人一定要足够懒, 勤快人是干不好程序员的, 必须手懒脑子勤快 )
  2. 另一个情况不是技术力问题, 而是对业务理解不够透彻, 一旦出现了这样的情况, 不要折磨项目上的产品和技术人员了, 把负责业务的人拉出来, 给团队做培训, 帮我们识别可变和不可变, 把业务流程和每个阶段的规则详细讲清楚, 共同研究业务方案. 解决耦合问题不光是技术层面的事, 还有分工协作层面的, 不能因为我们是负责技术方面, 就把业务的内容忽略, 技术用的再多, 再高大上, 业务上的问题解决不了, 都是浮云

低耦合和高内聚是软件设计中的真正核心原则, 做到了 低耦合 我们的工作会轻松, 效率会增加, 带来的好处:

1
2
3
4
5
6
7
8
9
- <font style="color:rgb(23, 43, 77);">当前组件不受其他组件变化的影响</font>

- <font style="color:rgb(23, 43, 77);">便于理解,方便沟通</font>

- <font style="color:rgb(23, 43, 77);">易于复用,方便集成</font>

- <font style="color:rgb(23, 43, 77);">易维护, 好修改, 少加班</font>

- <font style="color:rgb(23, 43, 77);">有时间交更多男女朋友</font>

高内聚 High Cohesion

公司里有没有见过这样的人:本职是做运营的,但顺带帮领导整理PPT、统计财务数据、调研竞品、对接法务……什么都干,每件事都马马虎虎,自己累得半死,做出来的东西却没一个靠谱的。HR说这人不聚焦,领导说这人效率低,当事人自己还委屈得不行:明明付出了那么多,怎么就落得这个评价?这种人在职场里最悲催的地方在于,努力是真实的,但结果往往是越帮越忙。

程序里的低内聚模块就是这样——它不是不努力,它干的活太杂了。从程序设计的角度来说,”内聚”指的是功能内聚,是对元素职责相关性和功能集中程度的度量. 如果一个元素内(系统/模块/类)的行为职责都高度相关, 并且没有加入与元素本身不相干的职责, 就可以说该元素在它职责范围内是高内聚的. 反过来,如果一个人承担了过多不相干的工作, 尤其原本不属于他的活也要干, 工作量还特别大, 换谁也会吃不消, 不是不能做, 而是无法专注, 效率低.

现在车轱辘话又要来了,高内聚了自然就能达到低耦合的目标了,但是如果你读过前面的文章,你就会明白,高内聚只不过是实现低耦合的一个手段罢了,低耦合可不单单只是功能上的低耦合,还有架构设计时的低耦合。由于内聚性非常低的元素干了太多与自己不相关的工作,或者需要完成太多的工作(虽然都是职责内的),缺点是显而易见的:

  • 难以理解
  • 难以维护
  • 难以复用
  • 脆弱不堪

上述的这些缺点都非常容易理解,我们再举个例子 如果我们打开一个 采集 的服务,但是 采集 服务干了太多 模型 的活儿的话,你说恶心不恶心,怎么去复用它;又或者打开了一个 实时库服务(功能都内聚),一个文件 1 万行代码,梳理代码逻辑就像年会时听领导讲话,别说程序员不看,就是机器也懒得把它翻译成 1 和 0 啊。面对这样的情况,你怎么理解它,怎么复用它,怎么维护它,别说它面对变化的脆弱不堪,换成是我维护这样的程序,我心理都能被它折磨脆弱了。

所以说,”高内聚”不是简单把什么功能都内聚,而是要有策略讲方法的,首先就是 “粒度”,一定是 “大粒度” 的功能内聚。我们开始设计时, 不要一开始就从头发丝一样细的去设计表结构表字段,领导天天提的几个项目流程中的几个步骤,这个时候就是它发挥作用的时候了:

  • 第一层面 系统层面 : 系统集成关系图
  • 第二层面 模块层面 : 系统模块关系图
  • 第三层面 接口层面 : 各模块接口定义与时序图

我们会发现一个问题,就是粒度不同,层面不同,我们分析和设计的时候,也要分析其中核心价值是什么,也就是它对外提供的核心服务是什么?只要把这个问题搞清楚了,让它去体现自己的核心价值就行了,比如模块有核心的服务接口向外提供服务,然后模块中只保留必要的辅助实现核心服务接口的功能即可。

与低耦合一样,在所有的设计决策期间,高内聚是要时刻高亮的原则,是一个需要不断考虑的原则。设计系统的时候,我们需要搞清楚这个系统需要跟哪些外部/三方有交互。当我们进行模块设计的时候,就需要引入更多的设计考量,以便让各个业务对象和接口发挥应有的作用,模块化就是要将系统分解成一组高内聚、低耦合的系统构件。构件这个概念在建筑行业里有,现在的建筑业越来越构件化,翻译成咱们的语言就是组件化。道理是一样的。

那么如何达成 “高内聚” 而又不把内聚做滥的目标,就看你的本事了,反正记住一句话:不要什么事都想着自己做,诸葛亮事必躬亲,但最后是心力交瘁而亡。内聚的度一定要把握好,怎么把职责合理分配好绝对是门艺术,后面要说的 “纯虚构” 和 “多态” 会帮助我们更优雅的完成高内聚和低耦合的目标。

控制器 Controller

你去政务大厅办事,进门之前你啥都不知道——谁管户籍?谁管社保?谁管工商注册?所幸大厅门口有个导办员,你跟她说你要干啥,她拿出张单子递给你:”去 8 号窗口”。你到了 8 号窗口,那个工作人员才是真正处理你业务的人。

导办员本人解决不了任何业务问题,她不给你盖章,不查你的档案,不帮你填表——但她是整个大厅的入口,是”外部请求”和”内部处理”之间的桥梁。

这就是 GRASP 里控制器的核心价值:接收外部事件,协调内部处理,自己不干活。

小饭馆还好,老板娘一个人既端菜又收钱还顺带招呼客人,一脑袋全包了,管用。但是饭馆做大了,你就必须有专门的收银员、专门的带位小哥、专门负责外卖的人——这时候门口还得有个人统一接待,告诉你”您这个需求找谁”。这个人不负责做饭,不负责收银,但她是整个运转体系的入口,缺了她一样乱。系统的控制器,就是这么个角色。

控制器的本分:只管”协调”,不管”干活”

控制器这个角色,有一条雷打不动的本分:只负责协调,不亲自动手。

就像一个好的项目经理,他的职责是:弄清楚来了什么需求,确认是谁的地盘,交出去,等结果,汇报。他不亲自画原型,不亲自写代码,不亲自跑去跟甲方讨价还价。具体的事,由具体的信息专家去做。这就是控制器的工作边界。

道理简单,但现实里很容易失守。

那个”什么都管的领导”

见过那种领导吗?不管大事小事都要经过他,开会要他,签字要他,请假要他,买盒打印纸也来找他,连下属跟甲方发的每封邮件他都要改一遍。一开始大家觉得这领导很负责任,但渐渐就会发现:这个人变成了整个团队最大的瓶颈——他一休假团队立刻瘫痪,他一回来面对的是一摞摞积压的待处理事项,他的下属也越来越不会独立思考,因为”反正领导要改”。

这种领导犯的错误,不是他不努力,而是他混淆了两件事:“负责这件事有没有做好”“亲自去做这件事”。前者是协调职责,后者是执行职责,两个是完全不同的角色。

系统里的控制器一旦开始”亲自干活”——自己计算业务数据,自己处理各种规则,自己管理各种细节——就变成了这种领导。它变得越来越庞大,越来越难改,动哪里都牵一发动全身,最后谁都不敢碰它。

一个好的控制器应该轻装上阵,它的字典里只有四个动作:接收、判断找谁、转交、汇报结果。剩下的,都是别人的事。

控制器是乐队指挥,不是演奏者。指挥的价值在于让所有人在对的时间做对的事,而不是自己把所有乐器都抢过来独奏。毕竟,一个优雅的指挥家,总是比一个到处乱插手的领导,更能赢得掌声。

多态 Polymorphism

同样是”项目经理”这个头衔,公司里的张三靠严格的甘特图和里程碑节点推进项目,李四靠大哥情怀和饭局维系团队,王五靠”不管发生什么先加班”的铁腕纪律赶进度。三个人的岗位名称一样,领导问”项目进展怎么样”,他们都能给出一个答案。但背后的实现逻辑,天差地别。

这就是多态最朴素的含义:相同的接口,不同的实现

大部分人对多态的理解停留在”父类引用指向子类对象”这个语法层面,背得很溜,考试没问题,但面对真实的设计问题时依然两眼一抹黑。GRASP 对多态的表述更有指导意义:

当行为因类型而不同时,把不同类型相关的职责分配给该类型自己,而不是靠外部判断来代劳。

换个说法:不要有个人替所有类型发言,让每个类型自己说话。

同一件事,不同角色,处理方式不同

公司收到一封客户投诉,这封信转到不同部门,结果大相径庭:转给法务,他们发律师函;转给客服,他们打电话安抚道歉;转给技术,他们排查问题修复上线;转给公关,他们出一篇声明稿。同一件事——“处理这个投诉”——每个部门用自己的方式响应。

现在问题来了:如果有个专门”分发投诉”的人,他不了解每个部门内部是怎么处理的,他只需要知道”这个投诉该找谁”,然后交出去就行。他不需要知道法务是怎么写律师函的,也不需要知道技术是怎么查 bug 的。这种”分发方”和”处理方”的分离,就是多态带来的好处。

反过来,如果没有这种安排,每次来了投诉,分发方就得先判断:是法务处理?还是客服处理?还是技术处理?每增加一个部门,这段判断就要改一次,判断错了后果自负。时间长了,这个”分发方”就变成了整个流程最难维护的节点——因为他知道的太多,所有人的内部逻辑都在他脑子里,他一走什么都乱了。

多态要解决的,就是这个问题:让每种类型自己负责自己的行为,而不是让一个外部角色替所有类型做决定。每个部门是自己业务的信息专家,它自己知道收到投诉该怎么处理,用不着别人替它操心内部流程,这也是高内聚的体现。

什么时候用多态,什么时候直接判断就好?

不是所有”类型不同、处理不同”的场景都要用多态,有时候直接判断更清楚、更省事。

就像公司就两个部门,来了事情你自己判断一下给谁处理,花五秒钟。但公司扩张到二十个部门,还要继续扩,你每次来一件事都要改一遍判断逻辑,这时候不如建立一个统一规则:每个部门自己登记”我处理什么类型的事”,来了事情自动找到对应的部门去处理。

判断标准只有一条:这种”类型”以后还会不会持续增加?如果会,值得用多态;如果就两三种且永远不会扩展,直接判断就行,不要为了”高大上”而过度设计。

间接 Indirection

你在城里想租房,最直接的方式是找到房东直接谈。但大多数人会通过中介——明明多了个赚差价的人,为什么还要用?因为中介解决了现实问题:你不认识房东,不知道哪套合适,更不想一套套核实虚假信息。中介承担了信息搜集和双方对接的成本,虽然貌似多收了你钱,但实际上降低了整个交易的摩擦。

这就是”间接”的本质:在两个组件之间引入一个中间对象,把直接依赖变成间接依赖,从而降低耦合。

计算机科学界有一句出自图灵奖得主 David Wheeler 的名言:

All problems in computer science can be solved by another level of indirection… except for the problem of too many layers of indirection.

所有计算机科学的问题都可以通过增加一层间接来解决——除了”间接层太多”这个问题本身。一句话道尽了间接这个原则的精髓,以及它的边界。

间接在生活里无处不在

其实你每天都在用”间接”,只是没意识到:

  • 领导的助理/秘书:你不能随时直接找老板,他的助理代他过滤沟通,老板只处理真正需要他拍板的事。老板换了,助理换了,对你来说”找老板”这件事的流程没有变。
  • 律师代理:两家公司谈判,双方都派律师,不直接对话,避免一言不合撕破脸。律师是中间人,谁家内部的立场怎么变,对方感知不到细节,只看到律师端出来的方案。
  • 猎头:公司不好意思直接去竞争对手那里挖人,通过猎头走,双方都体面,关系也不僵。
  • 外卖平台:餐厅和顾客不认识,平台在中间撮合,餐厅换地址了、顾客搬家了,对彼此没有影响,只要平台在就行。

这些中间人存在的意义,不是为了”多一道手续”,而是让两端可以各自变化,互不干扰。程序里的”间接”也是同样的逻辑,只是换成了技术组件来充当这个中间人的角色。间接,是实现低耦合最直接的手段。

过度间接:中间人多了,事儿就办不成了

间接虽好,滥用起来也是一种折磨。

见过那种报销流程吗?200 块的打车费:先发给直属领导,领导转部门经理,部门经理发财务主管,财务主管还需要 CFO 签字,CFO 出差了转给秘书,秘书说要走 OA 系统,OA 系统填完还要打印出来盖章扫描再上传……两周后,你已经忘了自己打了个车。每一层都是”中间人”,每一层都有它存在的”道理”,但整体的结果是:一件极小的事,被层层转手整成了极大的麻烦。

中间人要用在真正需要的地方,不是每件事都要套一圈”走流程”。到底哪些地方值得加一道中间环节、哪些地方直来直去更好——这就是下面这个原则要讨论的核心问题了。

纯虚构 Pure Fabrication

每家公司里都有一些不直接产生业务价值的角色:HR、行政、IT 支持、法务。他们不参与任何核心业务,不开发产品,不服务客户,不直接产生营收。但如果你把这些人全裁掉,公司用不了三个月就会一团乱——没人发工资,没人管电脑,没人管合同,没人办入职。

这些角色存在的意义,不是为了创造业务价值,而是为了让整个组织能够顺畅运转。他们是现实业务流程里不存在的角色,是为了组织运作效率而”虚构”出来的支撑岗位。

面向对象设计里,这叫做 纯虚构(Pure Fabrication)

信息专家撑不住的地方

信息专家原则说:谁拥有这方面的信息,谁来负责处理这方面的职责。听起来合理,但有一类职责,在业务领域里找不到合适的现实对象来承担。

举个例子。一家餐厅,厨师是菜品的专家,他对食材、烹饪、口味了如指掌。按照信息专家原则,跟菜有关的事都该厨师来管。但你要让厨师同时负责收款、开发票、做账目、对账、跑税务局报税……他也许做得到,但从此菜就做不好了,根本无法专注在自己的核心职责上,高内聚直接崩掉。

但是,会计这个职位,在一家餐厅的”业务流程”里原本是不存在的——客人来了点菜、上菜、付钱,哪里有”账务处理”这个环节?所以会计是一个被”虚构”出来、专门服务于运营需要的支撑角色。餐厅的业务领域里找不到他的位置,但如果没有他,这家店根本转不起来。

这就是纯虚构:当信息专家原则、高内聚、低耦合三个目标发生冲突时,发明一个在现实业务领域里不存在的角色来平衡它们。 他不生产业务价值,但他让整个系统更干净、更容易维护。

现实中到处都是纯虚构的角色

仔细想想,这类”虚构角色”在现实里比比皆是:

  • 会计事务所:不生产任何产品,但企业账目离不开它。”做账”这件事在原始的商业交换里是不存在的,但规模大了之后,非得有专人专职来做不可。
  • 公证处:买卖双方各有自己的信息,公证处本身不参与任何交易,但它的存在让交易更可信、更安全。
  • 物业公司:住宅的业主才是房子的信息专家,但让每个业主自己管楼道卫生、自己修电梯、自己收水电费,那是一场噩梦。物业这个角色,就是为了让小区能顺畅运转而”虚构”出来的。

这些角色的共同特点:不在核心业务流程里,但承担了让系统正常运转的”幕后职责”。程序设计里,我们也需要类似的角色来处理那些”信息专家们不该亲自干、但又必须有人干”的事情。

公司综合部:纯虚构的反面教材

很多公司都有一个叫”综合部”或”行政部”的部门,最开始设立的时候职责清晰:负责后勤、行政、对外联络。但时间一长,这个部门就变成了整个公司的”垃圾桶”——什么不知道归谁管的事,都扔给综合部。结账找他们,订酒店找他们,出了个法律纠纷找他们,甚至技术部门的电脑坏了也找他们……

这已经不是”纯虚构”了,这是一个内聚度接近于负数的部门。真正合格的纯虚构角色,职责必须单一,边界必须清晰。”什么都管的综合部”不是设计清晰的产物,是懒得思考归属问题的借口。程序里的”万能工具类”,跟这个综合部是一个毛病。

预防变化 Protected Variations

需求变更是软件开发里最确定的事情,比线上 Bug 还确定。产品经理在跟你讲需求的时候,他自己也不完全确定最终长什么样。甲方更是如此,往往连自己要什么都说不清楚,只有看到实物才知道”不对”。

但”需求一定会变”不是摆烂的理由,不是”反正要改就随便写”的借口。随便写导致的结果是:每次需求变化都是一场地震,改一行代码引发连环崩溃,最后谁都不敢动,只能不停打补丁,代码越来越丑,人越来越崩溃。

预防变化(Protected Variations) 的核心思想:你阻止不了变化,但你可以控制变化的影响范围。

就像建筑里的防火墙设计,火灾不可避免,但通过防火分区和隔离带,火势扩散的范围是可以被限制的。好的软件设计也是如此——在可预见的变化点周围,建立稳定的接口屏障,让变化只在局部发生。

识别变化点:最考验经验的地方

预防变化的第一步是识别”什么会变”。这比干活难多了,需要对业务和人性都有足够的理解。

大概率会变的东西:

  • 甲方的需求(这不用解释,是职场公理)
  • 合作方(今天用这家供应商,明天嫌贵换一家,接口和协议都不一样)
  • 公司的政策规定(促销规则、积分兑换比例、考核方式——每年都在变的那些)
  • 汇报的领导(领导走了来了,同样一件事上面换了新想法,下面就得跟着动)

相对稳定的东西:

  • 核心业务的骨架(一家餐厅,”点菜—上菜—结账”这个主流程几十年没变过)
  • 人情世故的基本逻辑(尊重、信任、诚信,这些不会因为换了平台就消失)

对会变的地方,留一道缓冲;对稳定的部分,直接实现,不要过度包装。

防弹衣不是每件衣服都要穿

说到这里,要提一个与之对立的原则:你不需要它(YAGNI,You Aren’t Gonna Need It)

买保险的人都懂这个道理——你不可能把所有险种全买了,”以防万一”可以无限延伸。你得判断哪些风险大概率会发生,哪些是可以承受的小概率,然后对应地投保。过度买保险等于把钱埋土里,每个月交保费心疼死,最后一次都没用上。

程序设计也是一样。不是每个地方都要”留接口”,那等于给每面墙都留插座、给每把椅子都装轮子,看起来考虑周全,实际上是在给自己和接手的人制造麻烦。在该保护的地方保护,在不需要的地方省力气——这才是务实的态度。

一个粗略但实用的判断标准:

这个东西,在这个项目的历史上被迫改过两次以上吗?

如果是,加防弹衣。如果不是,穿件普通衬衫就够了,等到第一次变化真正发生,再决定要不要保护,那时候你对变化点的判断也会准得多。

预防变化是前面多态和间接两个原则在更高维度上的统领:这两者告诉你”怎么做”,而预防变化告诉你”在哪里做”——答案由变化点决定,不由技术偏好决定。

创造者 Creator

职场里有一个永恒的问题:这个会,谁来组织?

一般来说不用明文规定,大家也都有默契:项目出了技术问题,技术负责人拉会;需求评审,产品经理组织;部门例会,部门经理召集;公司年会,HR 来安排。背后的逻辑是:谁最了解这件事、谁最需要这件事完成、谁掌握这件事所需的信息,谁就来牵头。

这不是制度规定的,而是一种自然的、合理的组织逻辑。面向对象设计里的 创造者(Creator) 原则说的就是同一件事:对象的创建责任,应该分配给对这个对象最了解、和它关系最近的那个类。

谁最近、谁最懂、谁来创建

这个逻辑在现实里很清楚:孩子出生,户口登在谁名下?当然是父母,因为父母是这个孩子最直接的”包含关系”,所有必要的信息都在父母这里。

一个项目的立项文件,谁来起草?当然是项目负责人,不是CEO,不是前台,而是那个最清楚这个项目要做什么、有哪些依赖、需要哪些资源的人。

部门新进来一个人,谁来带他做入职培训、分配工位、介绍业务?当然是部门经理,不是公司前台,也不是CEO——因为部门经理最清楚这个新人来了要做什么事、跟谁合作、要用什么工具。

规律很清晰:谁包含这个新角色、谁记录和使用这个新角色、谁拥有创建这个新角色所需的全部信息——谁就是最合理的”创建者”。 GRASP 只不过是把这个生活常识翻译成了设计原则。

最常见的反面:让大老板管所有人的入职

职场里有一种常见的混乱:公司扩张,每个部门都在招人,但所有新员工的入职手续、第一周的培训、工位分配、业务讲解,全都要通过CEO的秘书来走——因为”流程统一”。结果就是:CEO的秘书要了解每个部门的业务,要知道每个新人需要什么权限、坐哪个工位、找谁对接……她根本不了解这些细节,只能到处问,到处转达,信息在传递中不断失真,新员工第一天什么都搞不清楚。

显然更合理的做法是:统一入职手续归HR管(他们掌握合同、薪酬、社保这些信息),具体的业务对接归各部门经理管(他们掌握岗位、职责、协作关系这些信息)。谁掌握信息,谁负责创建和引导。

设计里也是同理。把本该由”直接包含者”来创建的东西,全部集中到一个统一的服务层去创建,表面看起来”管理统一”,实际上是让服务层承担了它根本不应该了解的细节,耦合度悄悄上升,信息专家原则也悄悄被破坏了。

创造者与工厂

有人会问:工厂模式不就是专门管”创建”的吗,为什么还需要 Creator 原则?

打个比方:正常家庭养孩子,父母负责,这是 Creator 原则的基本应用——自然、直接、谁最近谁来。但如果有人孩子太多、管不过来,或者有特殊需求,就会送去寄宿学校、托管机构,这就是”工厂模式”——把”创建和培养”这件事外包给一个专门的机构来做。工厂的出现不是否定父母,而是当”创建”本身变得复杂的时候,才值得专门设立一个角色来负责。

Creator 告诉你正常情况下谁最有资格来负责创建;工厂告诉你当创建过程本身变得复杂之后该怎么设计。两者是递进关系,不是替代关系。

最后说一句

GRASP 九个原则,走完了一遍。

信息专家 说让懂的人来干;创造者 说让关系最近的来生;控制器 说找个专门的人接活、分活,自己别插手;低耦合 说少管别人的事;高内聚 说把自己的事管好;多态 说同类问题让各自的类型去处理,别用 if-else 地摊代码;间接 说两个互不相识的,靠中间人牵线搭桥;纯虚构 说现实里没有的角色,可以为了设计干净而发明;预防变化 说知道哪里会变,就在那里建防火墙。

九条原则,没有一条是高深莫测的。每一条放到职场里、放到日常生活里,都是再朴素不过的道理。

难就难在:当你身处一个复杂的系统,面对几十个对象、几百个接口、几千行代码的时候,还能把这九条原则记在心里,让每一个设计决策都经得起推敲。什么样的项目在设计阶段就注定失败,什么样的架构是在给自己挖坑,什么样的代码改起来举重若轻——这些判断力,不是靠背概念能得到的,靠的是一次次在实践中对照这些原则反思和沉淀。

文章开头说的那句话,送给结尾:

“不要用一个锤子去解决你遇到的所有问题。”

GRASP 给了你九把锤子。用哪把,看情况。

“Talk is cheap, show me the code.” — Linus Torvalds, 2000

2026 年了,这句话该翻篇了。


先讲个事儿

2024 年,一个朋友的团队用 AI 辅助开发一个内部管理系统。三个人,两周,从零到上线——换成以前,这种体量的项目少说也要六七个人干两三个月。

项目上线那天,CTO 很开心,开发很兴奋,所有人都觉得找到了银弹。

三个月后,他们开始后悔。

不是因为系统不能用——能用,跑得好好的。问题在于:每次改需求,哪怕是很小的改动,都像在地雷阵里走路。一个接口改了,另一个模块莫名其妙报错;一个字段加了,三处报表的数据就不对了。到最后,没人敢说自己”完全理解”这个系统的数据流向——包括当初写它的人。

原因是什么?AI 写的每一行代码,单独拿出来看,质量都不差。命名规范,逻辑清晰,边界条件也处理了。但把这些代码放到一起看,就像十个装修工人分别装修了同一套房的十个房间——风格不统一,走线不对接,承重墙的位置没人对齐过。

这就是当下 AI 编程最真实的困境:局部极其优秀,全局稀烂。

而这篇要聊的,不是”AI 行不行”这种无聊的问题。是另一个更有意思的:

当”写代码”变得前所未有的廉价,什么才是真贵的东西?


一、AI 带来的变革:砖不要钱了,但你还是盖不起楼

1.1 以前值钱的东西,现在不值钱了

历史上的生产力革命,干掉的都是某个环节的高成本。印刷术干掉了抄书,流水线干掉了手工组装,Excel 干掉了会计扒拉算盘。

AI 干掉的是什么?是把想法变成可运行代码这件事的成本。

感受一下:过去你拿到一个需求,要想方案、选技术栈、写代码、调 bug、做测试。其中”写代码”这个环节,占了整个项目 60% 以上的时间和精力。现在 AI 能帮你把”写代码”这个环节压缩到原来的十分之一甚至百分之一。

但请注意——AI 降低的是”执行方案”的成本,不是”想清楚方案”的成本。

你仍然需要知道系统该怎么拆分、模块边界划在哪、数据流怎么走、这个接口应该返回什么。区别在于,过去你花三天想清楚方案、再花两周写代码;现在你花三天想清楚方案、再花三个小时让 AI 把代码生成出来。

这就引出一个根本性的变化:**”写代码”从目的变成了手段。**

以前说一个人”技术好”,很大程度上是指”代码写得漂亮、写得快”。以后说一个人”技术好”,得是指”他知道该写什么、不该写什么”。

就像搬砖,以前砖头是稀缺资源,你能搞到砖就能盖房。现在砖头不要钱了随便搬,问题变成了:你会不会画图纸?你知不知道房子该盖几层?承重墙在哪?地基打多深?

1.2 “能跑”和”能信”之间隔着十万八千里

AI 生成的代码有一个非常危险的特征:它看起来永远是对的。

命名规范、结构清晰、该有的注释都有、测试用例也能通过。你拿给一个 junior 看,他会觉得”这代码写得比我好”。你拿给一个 senior 看,他可能会皱眉头说”这里有点不对劲,但具体哪不对,我要想想”。

这个”想想”就是核心。

举个例子:AI 生成了一个重试逻辑——请求失败后重试三次,每次间隔一秒。代码没毛病,跑起来也没问题。但一个有经验的人会追问:这个接口是幂等的吗?如果不是,重试三次意味着可能创建三个重复的订单。重试间隔一秒,在高并发下会不会把下游服务打挂?这个重试是同步阻塞的还是异步的?如果是同步的,调用方的超时设置够不够?

这些问题,AI 不会主动想。它只会按照”常见的做法”生成一个”看起来合理”的实现。 而”常见的做法”和”正确的做法”之间的差距,就是经验和判断力。

所以我说——AI 把”能跑”的成本打到了地板上,但把”能信”的价值抬到了天花板上。

1.3 审查速度跟不上生成速度,你就失控了

这是一个很少有人讨论但极其重要的问题:

AI 一秒钟能生成 200 行代码,你一秒钟能审查多少行?如果审查速度跟不上生成速度,结果就是——你的代码库在膨胀,你对它的掌控在收缩。

代码越来越多,但理解它的人越来越少。每一个 AI 生成的模块都是一个”我大概知道它干什么,但细节不太确定”的黑箱。等到有一天需要改一个核心逻辑的时候,你打开代码一看——3000 行,都是 AI 写的,没有任何一个人从头到尾读过一遍。

这就是新的技术债形式:不是代码写得烂,而是代码写得太快太多,快到没人来得及理解它。

以前的技术债是”为了赶工写了烂代码”。以后的技术债是”为了赶工生成了太多没人审查的代码”。病因不同,症状一样——系统变得不可维护。


二、对行业的影响:价值链在重组,值钱的东西搬家了

2.1 编码环节被挤扁,上游环节被顶上来

传统的软件开发价值链,大致是这样的:

1
需求 → 设计 → 编码 → 测试 → 部署 → 运维

每个环节都有对应的角色和成本。编码,是过去几十年里人力最密集、成本最集中的环节。一个项目预算的六七成花在”把设计稿变成代码”上。

现在这个环节被 AI 挤扁了。成本骤降,人力需求骤减。但需求、设计、测试、运维这些环节——它们的难度和重要性不但没有降低,反而被凸显出来了。

打个比方:你开了一家饭店,以前请了 20 个厨师炒菜(编码),3 个采购员买菜(需求),2 个经理管后厨(设计)。有一天你引进了炒菜机器人,20 个厨师的活 2 个就能干了。你开心吗?开心。但现在问题来了——采购员买错菜了,机器人照炒不误,速度快、量大、看起来专业,但做出来的菜方向就错了。以前买错菜,厨师会说”老板,这鱼不新鲜”,现在机器人不会说话,它只会高效地把不新鲜的鱼做成一盘精美的菜。

速度不等于方向对。AI 是一台极其高效的发动机,但它不知道该往哪开。方向盘仍然在人手里。

2.2 “全栈”这个词该重新定义了

以前说全栈,意思是”前端也会、后端也会、数据库也会、部署也会”。这个定义的基础假设是:各个技术栈之间有明确的壁垒,全栈意味着你能跨过这些壁垒。

AI 时代,这些壁垒正在消融——因为 AI 能帮你补任何技术栈的短板。你不懂 K8s?问 AI。你不会写 SQL 优化?问 AI。React 和 Vue 都没用过?AI 帮你各生成一版。

以后真正的”全栈”不再是”什么技术都会”,而是**”能跨域”——在业务和技术之间自由翻译,在模糊和精确之间架桥。**

这种人的核心能力是:

  • 听到”用户体验不好”,能把它拆解成”列表页加载超过 3 秒且没有骨架屏和 loading 状态”
  • 知道一个”简单的需求”背后隐藏着多少架构影响
  • 能判断”AI 生成的这段代码在当前场景没问题,但如果明年业务扩展到海外就不行了”

AI 时代的全栈 = 理解问题的人,不是实现方案的人。 因为实现方案 AI 比你快一百倍。

2.3 新工种在冒出来,旧工种在变形

Prompt Engineer 是第一个被命名的新工种,但说实话这个名字太小了——它把一个本质上是”任务分解 + 约束定义 + 质量把控”的工作,降级成了”会写提示词”。

一个真正有价值的 prompt 工程师,应该做的事情是:

  1. 把模糊的业务需求拆解成 AI 能理解的子任务
  2. 为每个子任务定义清晰的约束和验收标准
  3. 审查 AI 输出,判断哪些能用、哪些需要改、哪些方向就错了
  4. 把成功的模式沉淀下来,变成可复用的模板

这跟”写提示词”的关系,就像”架构设计”跟”写代码”的关系——前者是思考,后者只是执行。

另一个正在成型的角色是 AI Output Auditor——专门审查 AI 生成的代码和方案。这个角色的门槛不是”比 AI 更会写代码”,而是”比 AI 更理解什么代码不该存在”。

往远了说,我相信会出现一类全新的角色:AI Workflow Architect,专门设计人和 AI 的协作流程——哪些环节让 AI 做主、哪些环节必须人类审查、错误信号怎么传递、知识怎么沉淀。这跟传统的项目管理不同,因为它需要对 AI 的能力边界有骨感的认知。


三、对企业管理模式的影响:你在管理一群”能力超强但毫无判断力”的员工

3.1 管理的核心变量变了

传统软件团队管理,管三件事:人、时间、代码质量。

“人”是最难的——因为人有情绪、有差异、有成长曲线、有办公室政治。管理者大量时间花在协调不同能力水平的成员、处理沟通摩擦、做绩效评估上。

AI 没消灭这些问题,但它往中间插了一个新变量:你的团队里多了一批”能力极强但毫无判断力”的新成员。 它们不累、不闹情绪、不请假、产出速度惊人——但它们会在你没注意的角落埋雷。

这就引出一个管理上前所未有的问题:你不再只是管理人做出来的东西,你还在管理机器做出来的东西。 而机器做出来的东西有一个危险的特性——它太完美了,完美到让人放松警惕。

想象一下你团队里新来了一个人,能力超强,什么活交给他都能秒级完成,代码质量看起来无可挑剔。你是不是会减少审查?是不是会把更多活堆给他?是不是会觉得”终于来了个靠谱的”?

三个月后你打开他写的代码一看——发现整个系统的架构已经被他用一种你没想到的方式”优化”了,所有模块之间多了一层你没授权的抽象,某些核心逻辑被他”重构”成了另一种风格。他不是故意的,他只是按他理解的”最优解”在做。但结果是,你的系统已经不是你原来理解的那个系统了。

这就是 AI 管理的核心挑战:你不能用管人的逻辑管 AI,也不能用信任人的逻辑信任 AI。

3.2 Code Review 从”好的实践”变成了”生存必需”

在 AI 之前,Code Review 在很多团队里是走形式——PR 太多,reviewer 点一下 approve 就完事了。它的主要价值是教育性的:帮助 junior 成长、知识共享、偶尔发现 bug。

AI 之后,Code Review 的性质变了。它不再是”锦上添花”,而是**”最后一道防线”。**

原因很简单:AI 生成代码的速度意味着你的代码库正在以过去 3-5 倍的速度膨胀。如果审查跟不上膨胀,你的系统就会变成一个你自以为了解、但实际上充满了你没见过的决策的黑箱。

但问题是——谁来审查?

如果审查的人能力不够,AI 生成的代码和人工写的代码对他来说没有区别——反正都看不懂,反正都 approve。审查仍然是形式化的,只是以前是形式化地审查人写的代码,现在是形式化地审查机器写的代码。

AI 时代,最需要投资的不是 AI 的能力,而是人类审查者的能力。 这是大多数企业管理者还没意识到的事。他们花大价钱买 AI 工具,却不愿意花时间培养团队的审查能力。就像买了一辆法拉利,却不愿意花钱学开车。

3.3 经验正在被重新定价

过去十年,软件行业的招聘市场有一个趋势:重”刷题能力”、轻”工程经验”。LeetCode 刷得好就能进大厂,十年架构经验可能在面试时还不如一个应届生。

AI 正在翻转这个不等式。

当算法实现可以被 AI 秒级完成时,”会写快速排序”就不再是区分度了。真正的区分度变成了:

  • 你能不能判断这个系统该不该用排序?
  • 排序结果缓存多久失效?
  • 当数据量增长 100 倍时这个排序策略还成立吗?
  • 如果排序逻辑是 AI 生成的,你怎么验证它在所有边界条件下都正确?

这些全是经验驱动的判断。AI 做不了这些,LeetCode 也练不出这些。它们来自在生产环境踩过的坑、背过的锅、半夜被 oncall 叫醒的痛苦经历。

对企业的启示:用人逻辑需要从”找到能写代码的人”转向”找到能驾驭 AI 写代码的人”。 前者是消耗品,后者才是核心资产。

3.4 知识管理从”有空再做”变成了”不做就死”

AI 没有长期记忆。每一个新会话,它都是从零开始理解你的系统。

这意味着什么?你的系统架构知识、业务规则、踩坑经验——如果只存在于人的脑子里或者 AI 的上下文窗口里,那就是脆弱的。人走了,知识就断了;AI 会话结束了,知识就清空了。

在 AI 时代,知识管理体系(架构决策记录、领域模型文档、API 契约、设计原则)不是锦上添花,而是核心基础设施。 它是你用来”初始化”AI 的 prompt 仓库,是你在人员流动时保持连续性的唯一手段。

换句话说——一个好的知识管理体系,本身就是最高质量的 prompt。

一个残酷的现实是:很多公司连基本的架构文档都没有,所有知识都在几个”元老”的脑子里。以前这只是风险,以后这就是死穴——因为你根本没法有效地利用 AI。


四、对项目流程的影响:敏捷没赢,瀑布也没死,该重新洗牌了

4.1 “快速迭代”的前提正在动摇

敏捷宣言诞生于 2001 年,核心假设是:需求是不确定的,所以用短周期、快反馈来逼近正确答案。 重实现轻设计,因为”先做出来看看”比”想清楚再做”更经济。重结果轻流程,因为流程往往会变成官僚主义。

这个假设在 AI 之前是成立的。改代码成本高,所以试错要快、反馈要早。

但 AI 改变了等式的一边。当”做出来看看”的成本暴跌时,它的诱惑力也暴涨——

“想那么多干嘛,先让 AI 生成一版看看?”

“这个方案不确定?没事,让 AI 各写一版,跑起来对比一下。”

“架构设计?先做出来再说,不行再改。”

这些想法每一个都很合理,每一个都很危险。因为 AI 让你高效地走弯路。你以前三天走一条弯路,发现不对回头重来。现在你三小时走五条弯路,每条都看起来很对,每条都不是最优解。你走得越多,离正确的路越远——因为你没有花时间站在高处看地图。

当”做”变快了,”想”的价值就变大了。 不是因为想比做难,而是因为做错的代价乘上了 AI 的速度杠杆。

4.2 设计先行在回归——但不是回到瀑布

这不意味着要回到写 200 页设计文档然后花半年实现的瀑布模型。

它意味着一种新的流程范式:

1
2
3
4
5
6
7
8
9
① 深入的领域分析和需求澄清(慢)

② 清晰的架构约束和模块边界定义(慢)

③ AI 驱动的并行实现(极快)

④ 严格的人工验证和集成测试(慢)

⑤ 在约束框架内的快速迭代(快)

注意这里面的节奏变化:① ② ④ 是慢的,③ ⑤ 是快的。 以前是全程中速——设计不充分、实现也不快、验证也马虎。现在是该慢的地方慢到位,该快的地方快到飞起。

而且第二步和第三步之间的间隔可以非常短——因为 AI 让实现几乎可以实时跟随设计。你不需要花三个月写详细设计文档然后花六个月编码。你可能花两天定义架构约束,然后用 AI 在一周内生成所有模块的骨架代码,再花两周打磨。

设计的时间占比变大了,但总周期变短了。 这才是 AI 带来的真正效率提升——不是让你在同样的时间里写更多代码,而是让你在更短的时间里做出更对的东西。

4.3 “重项目轻产品”的思维该翻篇了

“项目”思维的本质是:有开始、有结束、有交付物、有验收标准。这是工程思维的产物——把软件当成一栋楼来盖,盖完验收交钥匙。

但好的软件不是”交付”出来的,它是”长”出来的。它需要持续地理解用户、调整方向、做减法。

AI 让”交付项目”变得太容易了——你几乎可以在任何时间点交付一个”看起来完整”的产品。十个功能全有了,界面也漂亮,demo 也很流畅。但”看起来完整”和”真正有价值”之间的鸿沟,AI 填不上。

产品思维的核心——理解用户真正需要什么,而不是他们说他们需要什么——是 AI 替代不了的能力。 因为它需要同理心、需要对人性的理解、需要在模糊信息中做判断的勇气。

当实现不再是瓶颈,产品的权重自然上升。那些能把需求想清楚、把优先级排对、把”不该做的功能”砍掉的人——他们才是 AI 时代最贵的人。

4.4 测试策略需要全面升级,不能还停留在”写完再测”

AI 生成的代码有一种”应试教育”的特质:它擅长通过你明确指定的测试,但不擅长应对你没测到的场景。

你说”测试用户登录”,它生成的代码能通过登录测试。但它不会主动考虑:SQL 注入怎么办?会话固定攻击怎么办?并发登录时 session 管理会不会出 race condition?密码错误五次要不要锁账户?

如果测试用例是”考试题”,AI 就是一个刷题高手——它能确保你出的每道题都做对,但它不会主动去想”万一考到没练过的题呢”。

所以测试策略需要从”覆盖已知场景”升级到”发现未知风险”:

  • 契约测试和类型约束的权重提升——它们是不需要运行就能施加的约束,是最廉价的”防弹衣”
  • 模糊测试和属性测试变得更加重要——它们能发现 AI 在设计时没有考虑到的边界
  • 混沌工程的价值被放大——因为你需要验证的不只是”代码对不对”,而是”系统在压力下是否仍然可控”

一句话:测试不再是”写完代码之后的事”,它得成为架构设计的一部分——在 AI 动手之前,你就要定义好验证的规则。


五、对个人的影响:重新定义”值钱”

5.1 初级开发者的困境——但不是绝路

直说吧:AI 对初级开发者的影响是最直接的。

过去一个 junior 的核心价值是”能把功能做出来”。不需要多优雅,能跑、能过测试、能交付就行。这个价值正在被 AI 直接替代——而且 AI 做得更快、bug 更少(至少表面如此)。

但这不意味着初级开发者没有未来。它意味着成长路径需要换一条。

1
2
旧路径:学语法 → 写小功能 → 写大功能 → 学设计 → 学架构
新路径:学系统思维 → 学验证方法 → 用 AI 做实现 → 学审查 AI 输出 → 学架构

入口变了。以前是从”写”开始,现在是从”判断”开始。

一个刚入行的开发者,如果能尽早建立系统思维和代码审查能力,用 AI 来加速学习而不是替代学习,反而可能成长得比以前更快。因为 AI 是一个随叫随到的老师——你问它”这段代码为什么这样写”,它能给你解释。你让它生成不同方案,你能对比学习。

危险的不是”AI 会写代码”,而是”以为会用 AI 写代码就等于会做软件”。 这两者之间的差距,就像”会用搜索引擎”和”会做研究”的差距一样大。

5.2 高级开发者:从”工匠”变成”指挥”

对有经验的开发者来说,AI 是杠杆,不是替代品。

一个 senior 的核心能力从来不是”写代码快”——而是知道什么该写、什么不该写、什么时候该重构、什么时候该推翻重来。这些判断力在 AI 时代不仅没贬值,反而在升值。

在 AI 时代,一个 senior 的工作方式可能变成这样:

  1. 60% 的时间在设计和审查上(而不是像以前那样 60% 时间写代码)
  2. 用 AI 生成实现的初稿,然后花时间审查、修改、重构
  3. 定义架构约束——不是写代码,而是写”规则”,让 AI 在规则内工作
  4. 建立嗅觉——对 AI 输出形成直觉,快速识别哪些结果需要深入审查

这本质上是一种角色转变:从”工匠”变成”指挥”。 你不再亲手砌砖,但你需要知道每一面墙为什么要这么砌。

一个类比:好的厨师和普通厨师的区别不在于谁切菜快——预制菜切得比谁都快——而在于谁更懂食材、谁更懂搭配、谁能吃出哪道菜里少了一味调料。AI 就是那个切菜飞快的帮厨,但决定菜单、把控出品的仍然是主厨。

5.3 架构师:AI 时代最稀缺的资源

“架构师”这个词在行业里被用得很烂——很多人的”架构师”头衔本质上是”高级开发+偶尔画个 PPT”。但在 AI 时代,真正的架构能力变得前所未有地重要。

原因有三:

第一,AI 无法做真正的权衡。

架构设计的本质是在多个维度之间做取舍:性能 vs 可维护性、一致性 vs 可用性、短期交付 vs 长期演进。这些取舍没有标准答案,依赖对业务上下文、团队能力、技术趋势的综合判断。AI 可以给你”业界常见的做法”,但它不能告诉你”在你的场景下,不常见的做法可能更好”。

第二,AI 缺乏”未来感”。

好的架构设计是为未来的变化留空间——不是预知未来,而是保持可选择性(optionality)。这需要一种反事实思维:如果明年需求变成 X,今天的这个设计还撑得住吗?AI 的训练数据是过去,它很难为尚未发生的变化做准备。

第三,架构是一种社会性活动。

架构不只是技术决策,它还是组织决策——决定了团队怎么分工、代码怎么归属、变更怎么协调。Conway 定律说系统结构反映组织结构,反过来也成立。这种组织层面的架构思维,AI 完全不具备。

经验丰富的架构师是 AI 时代最稀缺的资源。因为他们是那些知道什么时候该慢下来的人。

在一个什么都加速的时代,知道什么时候减速,是最稀缺的能力。

5.4 “软技能”正在变成”硬通货”

如果我只能给一个年轻人一条职业建议,我会说:学好沟通。

不是那种”会做 PPT”的沟通。而是:

  • 能把模糊的想法变成精确的需求文档。 这是给 AI 下达有效指令的前提。
  • 能在不同角色之间翻译。 业务方说”用户体验不好”,你能把它拆解成”列表页加载超过 3 秒且没有骨架屏”。
  • 能写出清晰的架构决策记录。 让三个月后的自己、刚入职的新人、以及每一个 AI 会话都能理解”为什么这么做”。
  • 能说服团队在”能做”和”该做”之间选择后者。 当 AI 让什么都能做时,”不做”的决策变得更难、也更重要。

这些能力在过去被认为是”加分项”。在 AI 时代,它们是核心竞争力

因为 AI 可以帮你写任何代码,但它不能帮你做任何一个需要人际理解的决策。


六、现在能做什么:别光想,动手

说了这么多问题和趋势,最后聊点实在的。

短期:把约束前置,别让 AI 裸奔

  1. 先写约束,再让 AI 写代码。 类型定义、接口契约、架构规则——这些是给 AI 划的跑道。没有跑道,AI 跑得再快也是乱跑。
  2. 把架构经验 Skill 化。 团队里老人踩过的坑、总结的原则,整理成可被 AI 引用的知识库。这比培训十个新人有效得多。
  3. 审查流程不能省,还要加严。 代码库膨胀了,审查标准也得跟着升级。宁可慢一点出活,也不要快一倍埋雷。
  4. 测试前置。 先定义验收标准和测试策略,再让 AI 去实现。让测试成为约束而不是事后验证。

长期:把架构质量纳入模型训练

这是更远景的展望:目前的 AI 模型训练,reward 主要来自”代码是否通过测试”、”代码是否符合规范”。但很少有 reward 来自”这段代码六个月后是否仍然可维护”。

如果我们能把”长期可维护性”纳入模型训练的 reward 函数——比如通过大量真实项目的演化数据来训练模型理解什么是好的架构——那 AI 的能力边界就会从”写好局部代码”扩展到”做出好的全局决策”。

这还很远。但这是值得投资的方向。


结语

回到标题。

“Code is cheap, show me the prompt” 不是在说代码不重要。它是在说——代码的含金量正在从”怎么写”转移到”为什么写”和”写什么”。

“Prompt”在这里不只是”给 AI 的提示词”。它是一个隐喻——它代表所有在代码之前发生的思考:需求的澄清、架构的约束、设计的原则、验证的规则。这些东西才是 AI 时代真正的”源代码”。代码本身只是编译产物。

Linus 说”talk is cheap, show me the code”的时候,软件行业还处在”能把东西做出来就不错了”的阶段。那个时代,实现能力就是核心竞争力。

但现在,”把东西做出来”不再是难题。难题是——

  • 做什么?
  • 为什么做?
  • 为谁做?
  • 什么时候不该做?
  • 做到什么程度该停下来?

这些问题,AI 回答不了。它们需要人的判断力、同理心、和在不确定性中做决策的勇气。

AI 是极其高效的执行者。但经验丰富的架构师仍然不可替代——因为他们知道什么时候该慢下来。

在一个一切都加速的时代,知道什么时候减速,是最稀缺的能力。

Redis 的作者 antirez 说过一段话,我觉得放到这里特别合适:

或许你会觉得,自己曾为学习编程付出了无数心血,可如今这些努力仿佛都被机器轻易取代。但请回想一下,当年你为了让项目成功运行而熬夜敲代码时,内心燃烧的那份热情究竟源于什么?是创造的乐趣。而现在,只要你能掌握与人工智能高效协作的方法,就能创造出更多、更棒的作品——那份创造的乐趣,从未改变。

是的。工具变了,但创造的冲动没变。AI 把执行的成本打下来了,但它也把你从重复劳动中解放出来——让你有更多时间去做那些真正需要创造力的事。

别害怕被取代。害怕的应该是:你花了十年练就了一身砌砖的手艺,却从来没学过怎么看图纸。

现在学,还来得及。


写于 2026 年 4 月。当 AI 能在一分钟内写出这篇文章的时候,花三个小时写它的意义是什么?也许是因为,有些思考只有在写的过程中才会发生。

常见流媒体协议

RTMP: 既可以用来推送又可以用来直播,其核心理念是将大块的视频帧和音频帧拆分,然后以小数据包的形式在互联网上进行传输,而且支持加密, 基于TCP

HLS: 苹果公司提出的基于HTTP的流媒体网络传输协议。其工作原理是切片式传输,把直播流切成无数片,用户在观看视频时,每次客户端可以只下载一部分。适合移动端使用

FLV: Adobe推出的私有协议,走HTTP,原本只能用flash播,但是B站的 flv.js 弥补了这个缺陷

以上三种协议:  腾讯云,阿里云都是三种协议的播放 但只支持RTMP协议推流

 腾讯云直播流播放SDK(支持IOS,ANDROID,IOS,H5播放器)

 阿里云直播流播放SDK

开源 rtmp库其实有不少 参见 https://github.com/topics/rtmp 哪怕把上面的条件限定到java依然还是有很多的(其中不少是大厂或者收费的了…)

支持以上三种的播放器就更多了,常见的有 谷歌的shaka-player, videojs, flv.js

OBS(Open Broadcaster Software)

https://github.com/obsproject/obs-studio 目前使用最广的推流客户端 全平台 完全开源 完整生态 支持大量插件

同类软件的比较英文版

国内改版的obs

https://github.com/bilibili/biliobs

https://github.com/alibaba/tblive


streamlabs-obs

基于ts,vue的开源osb客户端 github地址 项目主要使用的技术 vue, node, typescript, electron, 官网 API地址

obs-studio-node 用于封装底层OBS的相关接口

streamlabs-beaker 封装的UI组件


根据上面obs-node库用原生JS做的例子

https://github.com/qlteacher/obs-example


直播平台架构

爆炸式增长的斗鱼架构平台的演进

快手直播平台演进之路

斗鱼:如何打造一个高性能、高可用直播系统架构

熊猫直播技术架构演进

AWS 案例研究:虎牙直播

我们为什么使用DASH

OBS源码解读


系统架构脑图

08年

初入信总的时候,主营的 山东毕业生高校就业信息网官网 已经开发完成了, 错过了这个大型系统的建设还是挺遗憾的(这个项目用到了sun的小机,到离开信总都没能上去摸一把);

实习期间就被分配到了齐鲁银行,在银行科技部挨着机房的办公室里面监控OA的运行情况(win平台RiseNet+websphere+oracle)+页面+小需求直接修改+数据库直接调整数据等等琐碎工作

  • 为什么要监控运行情况,因为当时的windows 2000 server问题非常多,websphere & oracle 运行在上面动不动就内存跑满没法回收,这个问题直到后来把环境都迁移到了redhat上面才彻底解决
  • 日常页面小调整(jsp)
  • 流程走错了,有数据状态不对等等情况 直接改数据库

对于一个刚实习的人上面这些东西开始我全都不会,现在还记得有天高老师(技术总监,对我帮助影响很大)甩我一堆文档然后给了个任务说

1
2
3
4
5
"你去把RiseNet在你本地用weblogic跑起来,然后改其中一个页面巴拉巴拉巴拉",
"好啊"
"咦,你弄过RiseNet和weblogic嘛?"
"没有,我连你说的weblogic怎么拼都不知道,但是难道还不会学嘛?"
"可以可以,好好看这些文档,不会的问XXX"

我觉的我从那天开始才算入了门,所以我现在最讨厌的就是社畜三问(我不会,我没做过,怎么做)

从齐鲁银行蹲了几个月(大概3,4个)后,转正–>配了个笔记本(dell XPS1530 这机器夏天真的烫)就被拉走去章丘封闭了…

大概封闭了有10个月左右,项目是开发OA的管理端,功能模仿novell ldap(齐鲁银行RiseNet就是用的这个做统一认证…)的RBAC后台管理系统+cms后台,项目技术栈 oracle,struts2,spring,freemarker,xslt(这东西火了一小阵子,有段时间csdn,暴雪战网都是用这个生成的页面,不过实在是太难用了…),Adobe Flex(就是后来大火的开心农场用的flex)

项目开始高老师也是一样扔了一堆flex文档(全英文)和一个已经初步搭好的架子,就直接开工了,那时候google虽然还在,但是flex还没开始火起来,文章/资料基本是找不到的,除了啃api和自己debug调试没有别的学习路径,大概用了不到一周就上手开始开发; 工作内容大概是用flex实现组织结构,人员,用户组管理,权限-功能点配置,站点-栏目,栏目字段属性配置等等

封闭虽然很辛苦,但是成长确实快,完成了从菜鸟升级到初级开发的阶段

09年

封闭回来后,给齐鲁银行OA升级环境,websphere->weblogic, oracle(win)-oracleRAC(linux),都是在高老师的指导下进行的,也是在那时起被教育了对待生产环境要慎重,慎重,慎重,再慎重,在生产环境上做任何操作一定要想清楚自己在干什么,这个操作如果有问题能不能回退,在测试环境中预习过了吗; 我后来跟单位的运维新人也是这么讲,碰上任何情况,在生产上操作也不要急,敲你的回车之前,一定要停下来再看一遍再想一想

搞完银行的升级回来继续打造封闭时的产品,这次是给系统增加工作流模块,先是从市面上选了几个工作流引擎,最后选中的是jbpm,当时版本号还是0.x; 这回没封闭但是开始了半年多的9106;我负责完成的功能有flex端上传from表单,java解析表单生成配置,flex编辑配置,java根据配置生成数据库表(支持一对多,多对多),flex绘制jbpm流程图,这个功能放到现在来看也是个难点,当时给两点间的线的一端绘制一个箭头连数学课本都拿出来了….;从这个项目开始正式参与Java开发,当然flex的水平也是愈发的成熟,在 csdn 当年的月榜(id:gundamff) 为了拿到专家标志 刷了几个月的分 刷分的时候也很有收获,因为想让别人把分给你 你的答案要讲的清楚,明白,看似短短几句话,可能得自己研究测试好久(不过后来结贴不结分的太多了就退圈了)

这个工作流项目,是首次完整参与了设计,开发,测试,验收全过程,亲眼看着一堆概念一天天的变成实物 真的是超有成就感(验收完成那天真的是感觉nothing inpossible)

10年

这一年部门用产品为底,做了几个项目(毕竟蹲家里研发产品不赚钱呀),其中带了几新人接手了 省立医院的项目 “山东远程医疗网” (第一次当项目经理第一次带小弟两件快乐的事情加在一起碰上分管副院长这种刺头…..),首次体会到了甲方的恐怖(院长是可以任性妄为,无理取闹,大嗓门骂人的谁让人家是甲方),印象最深刻的是首页上有个院方的logo他们原版是个白底红字,让我们重新设计,我们美工第一是白底红字改了下图案,BOSS大怒,喷我干活敷衍,改成白底绿字,被喷绿色不好看,红底白字,”医院弄这么红不吉利”(这是原话…)….一个Logo折腾了十几版,拍桌子骂了我5,6回,最后用的是第一版……….;还是说回项目本身,项目并不难,对外是一个cms,对内包括各种管理功能,最核心的是对接许多三方的设备或者系统,好在大部分都是在前端用ActiveXObject对接的,少部分走的webservice(xfire);

这个项目虽然进行的困难,但是完成时的成就感一点没少,验收时直接医生用系统对接汶川的手术间,在线指导手术(首先还是医院买的硬件牛鼻),最主要的收获对项目管理有的认识,到后来公司有人去考pmp证书(我当时选的去考oracle ocp 现在后悔死了),他们回来给我们分享课件,才慢慢了解到敏捷/迭代等等概念

ps: 这里有篇:个人项目管理经验总结 是后来给新人做培训的时候写在内网confluence上的

年末用自己家产品给齐鲁银行的某几个支行实施了支行的OA系统

期间银行内的一些小需求小功能也是带着小朋友们去做的

年末接的项目是 山东省教师资格证考试报名系统 ,这个项目是小年那天开始的,那天公司几乎没人了…要求是初10上线,到初15总共有10万人进行注册报名,线下缴费,后续功能有自动排考场(算法稍微有点复杂),打印准考证,考场总表,房表,桌号表,最后成绩导入,汇总,生成编号,打印合格证.其实后续功能都还好(除了那些不能说的小纸条),最难的在于在过年期间准备好能应对10人在线的环境+开发足够坚挺的注册报名等前期功能,最开始的时候这个项目我是拒绝的,时间太赶了又对并发有不小的要求,感觉风险太大了,这时候还是高老师力排众议(“你们放心干,出问题有我”)把事情接下来了;闲话不说,说一下项目是怎么实施的吧.用了5台服务器,2个跑apache,2个weblogic跑机器,每个weblogic上面部署了2个节点的程序,剩下2个跑oracleRAC,程序的话还是用的自家产品,并发 压力可能会大的方法加了ehcache缓存

最终这个项目也顺利完成了,第一周报名的并发峰值也就2K左右(报名的第一天和最后一天),给我最大的教训就是,从此以后我再也没说过 “XXX做不了”,都能做!

人所有的拖沓都是代表他并非真正热爱,你所有的畏难不自信都表示你不想付出努力.

11年

从这年开始高老师离职了(先创业,后去了美国),部门里面各式各样的疑难杂症渐渐的交给我来处理了,凡是只能靠自己了之后处理各式各样问题的经验也越来越多(直到现在也常有朋友的项目碰到难题喊我帮忙瞅瞅的(有偿的居多))

这年做自己用JavaMail+apacheJames给齐鲁银行上了一套邮件系统,用JavaMail库直接开发,兼容中文的时候还是有些难得,记得当时用的jdk7 javaMail包里面对中文的处理还有bug,还给sun提交了个修复

PS: 当时测试各种极端情况时,微软的outlook是兼容性最好的, 其他的google,163,qq邮箱什么的总会有处理不了的时候

年中的时候做了青岛毕业生就业信息网,当时另一个同事负责的带的项目,需求搞的一坨糟(问题出在市场人员),然后我同时有两个项目一起干,我记得最忙的一个月青岛项目天天9106,12点以后再去齐鲁银行跟他们另一个项目组联调接口到下半夜,这个项目完成以后开发分了极少极少的奖金,不负责的市场人员分的极多极多…..,这是导致下一年离职的直接 原因

这年还给齐鲁银行搞了oracle 10G dataGuard做数据同步,这个是有点难的,因为dataGuard本身是oracle的收费服务,所以文档和说明都非常少, 网上能找到的文章大多错误百出,知其然不知其所以然,所以搞得非常痛苦;从此以后就基本不碰闭源项目/产品了,因为无论你水平如何,闭源的玩意搞不了就是搞不了,木有办法

年底时参加了公司资助的oracle ocp学习考试(山东瀚高),只是没想到没几年就开始搞去IOE化…..

12年

这年基本都在交接工作,帮他们做些规划,解决他们碰到的问题之类的了;大概3,4月份就离职了

12年 家里蹲的几个月

闲时玩玩andorid

大概从11年开始玩andorid手机,那时候的安卓生态就是没有生态,记得那时想找个可以用的文件管理器都木的有,所以平常就自己写了些小工具在自己朋友圈里面传着用,对了 11年初的时候还差点去了小米,这就是另一个故事了,感兴趣可以联系我讲出来玩玩;

离职宅在家里总得有收入吧,一边找工作,一边呐就弄些有用没用的app发谷歌市场骗点下载量

也曾有过创业的梦想

当时有个点子(现在也有),成立个工作室,只负责系统的调研,需求分析,架构规划,原型设计,开发中的质保,后期验收(说白了就是一个项目除了开发不干其他的都帮甲方干了),只需要相对少量行业内的资深领域专家即可,目的是给没有任何IT经验/能力的甲方爸爸提供支持,码字你找哪家写都行,但是理念和设计一定给你做到位7.,P .,CV,保证业内任何人来了都挑不出毛病来. 国外是有这种公司的,国内可能因为环境的原因没有发展出来

12年 至今 山东新世纪网络教育有限公司

12年-14年

12年下半年,受到新世纪领导(副总)的邀请,过来暂时(????)帮帮忙…

前因: 因为之前的教师资格证报名项目就是这位领导找到我们做的,大家当时合作的很好,所以有困难时想到了我,具体是什么困难呐? 这里就得介绍下业务了…

简单说, 山东教师教育网隶属山东省教育厅教师工作处是教育部认定的“国培计划”教师远程培训机构、山东省教育厅认定的省级教师教育培训机构,山东省省级教师教育综合服务门户网站。

项目难点在于每年暑期的教师研修是一场全省百万级别短时间内集中访问的,而且在开始几年,下级单位行政领导们会进行近乎病态的攀比(某某市/县/校的评论/作业/进度一定要比其他市/县/校高),省里面大领导们又把每项活动的时间节点控制的及其严格,就导致了某些时间段里面,个别场景的压力堪比电商秒杀. 举个例子

领导要求 某学习活动必须7月1日9:00-12:00点才能进行,那么下面各级领导们就会要求所有的教师在8:30 一起登录,9:00开始就疯狂刷各种指标; 这里跟秒杀不同的是,秒杀是有库存限制的,库存空了压力就没了,而这里的业务场景简直就是为了搞死系统设计的……

12年刚来的时候呐 公司已有的开发团队使用.net开发的平台已经实际使用了4年了,并且稳定性也是逐年提高的(碰上峰值要死还是会死的…),但是公司大领导决定另行启动一套队伍,使用java+成熟的开源社区方案对系统进行重构;大领导以外包的方式找了个北京的团队接手开发,副总安排我以甲方技术负责人的身份介入开发全过程,从济南带了2个哥们就去北京住了10几个月; 其中过程的艰辛在此不提,有机会可以面聊; 这种层层转包的方式有多坑我想过来人都知道…..;总之 用了将近一年的成本拿出来一份我并不满意的成果;但是在大领导一意孤行下项目还是得做; 项目的架构和选型等基本都是我拿出来的(层层转包给北京的团队时已经变成了做个CMS了…,还好我提前自己就搭好了主体框架);

还是单纯的说一下技术吧,项目使用前后分离(当时这么设计的并不常见),项目分模块运行,容器选的apache+weblogic集群

前端

- easyui
- requireJs

后端

- springMVC
- JPA
- ehcache

数据库

- couchbase
- oracleRAC

由于对数据库的拆分被乙方团队的DBA(清华应届生)同学阻止,这个项目最后经过了几个月没白没黑的压力测试(请的省信息中心的压测团队,价格不菲),最终最好的场景(业务简单的那些)TPS:2W左右,复杂场景跑不过1W(8K+); 这个成绩在我看来是不及格的,上线必死; 这段时间里面, 我深入接触了压测的各个环节,性能调优,高负载的各种解决方案和设计思路,心中对于这个系统应该设计成什么样子已经有了计划; 本打算把项目糊弄着验收了,然后踢走外包团队,然后按照计划改造系统,逐步替换线上模块的方式稳步推进; 大家都知道的…计划赶不上变化;

由于我一直对新平台(做完压测后大领导一意孤行的要将其上线)功能性能不太认可的态度,大领导直接空降了个哥们领导整个团队玩命的推进作死计划……我呐…则进入了几个月的被架空状态被保护了起来…,这也给了我自己进行学习的时间和机会

时间慢慢来到了13年年中,期间新平台由于各种问题,只在个别的地区性质的项目中进行试用,效果也并不理想,原因不详(不想在这里详说), 最终这个耗费大几百万,层层转包后给了乙方团队几十万的项目终于惊动了厅级领导, 然后就是拨乱反正,该走的走该留的留, 骗钱混日子的走了,想证明自己一展身手的留下了;留下的人面对一团乱麻,决心从头开始; 用了几个月的时间,从新论证需求,设计,技术,部署等方案;这样时间就来到了14年;

其实这2年间, 我工作的并不痛快,但是不论技术还是理论,不论三观还是阅历都有巨大的变化; 我还是要感谢一下在那段时间跟我站在一起的朋友和同事们

14年-2020

这里先说一下13年底,我们最终拿出来的设计方案吧

软件架构:

前端:

    * angularjs
    * <font style="color:#172B4D;">Bootstrap</font>
    * <font style="color:#172B4D;">RxJS</font>

后端:

    * <font style="color:#172B4D;">Spring 4.x</font>
    * Springboot 1.x
    * 我设计开发的缓存框架(基于aop拦截+注解),与[autoloadcache](https://github.com/qiujiayu/AutoLoadCache)<font style="color:#263238;">的类似(后来出现了</font>AutoLoadCache后,这块代码整体提供给了该作者<font style="color:#263238;">)</font>
    * 共同设计的认证体系,与目前(2020年)流行的jwt类似,为了性能去掉了后端维持的session,省去了session同步的各种问题,改为前端持有一个编码后的json对象,编码后的值可以在Java端和nginx端(lua脚本)解码
    * 我开发设计的分布式配置管理组件,基于zookeeper实时同步更新spring配置,比disconf早了几年出来
    * mybatis 从性能和易用性两者间找了个折中的方案
    * dubbo 是的,14年我们就在生产环境中大量应用了dubbo
    * hazelcast 内存网格数据库,当年用hazelcast + mongoDB来应对高并发的OLTP场景
    * druid,国产连接池的忠实用户,Ps: c3p0|dbcp都是辣鸡
        + 虽然这么说 druid的文档和代码也一般般, 有兴趣的自己去看看github上面的issues
    * kafka,使用mq+mysql来应对OLAP场景

中间件:

    * <font style="color:#172B4D;">mysql, 响应去IOE化, 抛弃了单个庞大的oracleRAC,对业务垂直分割后改为数个mysql集群(2写4读,1写1读,1写2读等)</font>
    * <font style="color:#172B4D;">couchbase,缓存, 缓存是解决读压力的不二法宝,当然你还得解决好上了缓存后的各种问题(一致性,缓存穿透等等等等,这都是我后来才知道的坑)</font>
    * <font style="color:#172B4D;">redis,配合程序+</font><font style="color:#172B4D;">openResty可以玩出各种花样,性能还贼高,缺点就是不能搞太复杂的逻辑</font>
    * <font style="color:#172B4D;">openResty,nginx的性能比apache强太多太多了,支持</font><font style="color:#172B4D;">openResty的nginx简直无所不能(除了在上面开发不太友好),可以看</font>[这篇](https://www.yuque.com/xiangkongyue/abh4xu/dviduv)<font style="color:#172B4D;">最后的实际应用</font>
    * kafka,异步,队列,批量处理 是应对高并发写的三板斧,当然了现实中没有银弹,该碰上的分布式事务,稳定性等问题日后也都没落下
    * fastDFS,还是为了<font style="color:#172B4D;">响应去IOE化, </font><font style="color:#172B4D;">openResty上自行编译上</font>fastDFS模块和upload模块,上传的性能只有带宽是瓶颈!
    * solr cloud, 没什么好说的个人不喜欢elsearch

可以看到,当时的技术选项与设计 基本都是后来网上说烂了的标准方案, 但是在13年,是没有人/文章告诉我们该怎么做的, 所以在实践中还是踩了许许多多的坑.

14年暑期上线虽然顶住了没有挂机,但是并发上来卡顿,高延时的情况有不少,然后问题最严重的就是之前没有想到或者说没有重视的分布式事务问题, 为了性能,我们把可能高并发的业务都拆分了读写两种结构,比如写结构可能直接走hz+mongo,读结构走mq+mysql,这是允许出现读延时的场景,不允许读延时的就都走redis之类的方案; 这些方案看上去很美,但实际上没有一致性的检查的话,就是一场灾难;

15年 总结了经验,根据14年的实际数据(监控来的各种指标),调整了部分场景的设计和方案, 比如原来估计并发会很高的交作业部分其实并发才一千+,设计不合理的业务也进行了修改,比如:全省教师一起上来飙评论数(实际所有人都是复制黏贴的一句话),能把redis限流器跑死…; 整体上剔除了hz+mongodb,保留了kafka+mysql的方案;

16-17年整体重构了业务模块,模块切的更细; 整体升级技术框架,技术栈基本不变的前提下,依赖的类库/框架等等都做了全面的升级重构,看似不难的工作还是耗费了团队很多时间的, 因为拆分的模块越多,升级的成本就越高,这里暂时就不细说了; 同时响应上级的要求,2年间开发了不少新的业务;最终系统整体包括:

1. <font style="color:#172B4D;">账户中心,id.qlteacher.com,认证权限,三方oauth支持</font>
2. 教师继续管理,teacher.qlteacher.com,教师信息库
3. 课程库管理,course.qlteacher.com,通用模块,提供课程服务
4. 研修平台, 主要业务平台,负责组织和进行研修任务
5. 工作坊, fang.qlteacher.com,教师自由组织的学习园地
6. 骨干系统
7. 一师一课平台, 对接国家一师一课平台,负责每年一次的全省一师一课活动
8. 教师个人空间/博客/教师圈
9. 问卷/考试
10. 门户
11. 分布式资源转换服务,支持多地多级文件转换同步

18年, 除了基础的技术升级之外,接了个外包的运维工作, 就是 http://www.5teacher.com/ 以下简称t5; t5的开发/运维团队在北京,我们接收的时候大概10-20人,据称t5虽然盈利,但是开发团队成本太高,所以t5老板计划把技术整体外包,裁掉自己的所有技术人员, 然后我们去了3个人一周时间把系统的代码,运维,发布等等全部接手; 回到济南后又用了几个月的时间把环境和代码通通整理完毕,中间修复了bug无数; 一个哥们负责IOS两个app,一个哥们负责日常的硬件/软件/流量巡检,我一个人负责所有的后端程序(5个左右的主程序)+android两个app+数据库+日常破案; 其中的技术细节这里不便详述,毕竟是目前依然在线上运营盈利的,可以面谈

算下来就是3个人用了原来团队1/10不到的成本,更多更好的完成了工作;简直神奇

2020-至今

2020

2020年10月从新世纪离职了, 原因也很简单, 能在教师网上面玩到的技术,框架,套路, 都已经玩了8年了, 业务没有大的变动, 技术上能折腾的空间基本都玩过了, 然后有了娃以后心态也发生了一些变化, 简单说就是 我先去外面看看

所以换到了北京国科恒通

入职第一周 我连上生产环境的那一刹那我是崩溃的, 我第一反应是 “玛德 坏了 被领导忽悠了 是今天就走还是混一个月走?”

生产环境的服务 居然 0 优化 0 配置, 完全是默认安装的centos7状态 这尼玛完全是搞笑的吧 我搞私活都比这搞得漂亮几百倍啊 java程序完全裸跑的 0 jvm配置 你们确定这是生产环境??? 这尼玛的mysql , redis, kafka也都是默认按照运行的, 操蛋

这TMD就有点意思了 我TMD的这次要挑战一下自己 看我能不能把这么一套瞎几把胡来的作坊式团队给它整明白咯 整不明白我还不走了

国科不亡 天理难容

添加消息, teststream 是key

1
2
3
4
5
xadd teststream * id 1
xadd teststream * id 2
xadd teststream * id 3
xadd teststream * id 4
xadd teststream * id 5

查询消息, - + 表示 最小和最大,可以是stream中任意两个id

1
xrange teststream - +

创建消费组,

0 ,表示消费组将会消费teststream 下面所有的消息

$, 表示消费组将会消费创建时间之后的所有消息

[id], 表示消费组将会消费指定ID之后的所有消息

1
2
3
xgroup create teststream group1 0
xgroup create teststream group1 $
xgroup create teststream group1 1595400021271-0

创建消费者并开始读取消息,返回指定组内从未被其他消费者消费(接收)的消息,也就是最新的消息 相当于 (消费=fasle)

0, 返回指定组内被当前消费者消费(接收)了但是未处理的消息(没标记ACK的), 这里注意消费和处理(ACK)两个概念的不同,这里不会返回当前消费者没有消费过的消息 相当于 (消费=true && ack = true); 举个例子: xadd N条消息之后 立刻xreadgroup 0 返回的会是 null,先 xreadgroup > 再执行xreadgroup 0 就是所有没有ack的消息了

[id], 同上,只是返回的范围变成了指定ID之后的数据

1
2
3
xreadgroup GROUP group1 consumer-1 count 10 BLOCK 0 streams teststream 0
xreadgroup GROUP group1 consumer-1 count 10 BLOCK 0 streams teststream >
xreadgroup GROUP group1 consumer-1 count 10 BLOCK 0 streams teststream 1595400021271-0

标记处理, 一看就明白没有什么好说的

1
XACK teststream group1 1595400021271-0

测试一轮后的结论

这东西出来还是太新了,spring-data-redis的支持也并不完善,玩玩就算了,大规模上生产估计是个坑

//update 20200907

记几个查询命令

1
2
3
Xinfo stream teststream
Xinfo groups teststream
XINFO CONSUMERS groups teststream

参考文章:

https://lolico.me/2020/06/28/Using-stream-to-implement-message-queue-in-springboot/

https://juejin.im/post/5d044fe1f265da1b9253d80b

https://my.oschina.net/pass/blog/3145295

http://xiaorui.cc/archives/5285

https://cloud.tencent.com/developer/article/1529507

1
2
3
4
5
6
7
8
9
10
--查找最繁忙的前10个
thread -n 10
--看最忙的第一个在干嘛
thread 771
--显示这个方法的内部调用耗时情况
trace com.qlteacher.service.training.impl.TrainingUserServiceImpl getTrainingUserForCache
--对这个方法的执行情况进行一下统计
monitor com.qlteacher.service.training.impl.TrainingUserServiceImpl getTrainingUserForCache
--最终找到有问题的方法
trace com.qlteacher.service.training.impl.TrainingUserServiceImpl getProjectLessonInfoByChosen

引言:历史的注脚

今天,我与 AI 进行了一场关于“界限”的对话。我们从一个具体的数字——《三国演义》的文本大小(约10MB,64万字)出发,推演到了人类文明的最终去向。

写下这篇博文,是为了给后人(或者是未来的某个超级 AI)留下一个坐标。如果有一天,你们已经彻底摆脱了键盘、屏幕和繁琐的代码,正航行在半人马座的引力场中,请回过头来看看 2026 年的我们——一群在低效的接口中,窥见无限可能的先行者。


一、 上下文的“内存化”:当 AI 吞噬历史

我们曾惊叹于 128k Token 的容量,但截至 2026 年,顶级模型的上下文窗口已正式步入 1000 万(10M) 级别。

这是一个什么概念?

  • 全本《三国演义》(约 120 万 Token)在如今的 AI 面前,不过是 1/10 的胃口。
  • 曾经需要数月研读的代码库、法律条文、甚至是人一生的日记,现在可以被 AI 在几秒钟内“一次性读入”。

我们意识到,AI 的上下文正在经历“内存化”的过程。就像曾经我们吝啬于每一 KB 的内存分配,而现在我们习惯于无限的后台缓存。AI 正在从“阅读者”变成“全知者”,它不再需要频繁清理历史,因为它已经拥有了容纳整个人类数字记录的肚量。

二、 破除“模拟人类”的枷锁:低效的终结

现在的 AI 工作模式依然是极其低效的:它在模仿人类。 它通过 Bash 敲命令,通过截图识别屏幕,通过生成人类语言(Python, C++)来控制机器。

这种“马车模型”是对 AI 算力的极大浪费。我们一致认为,技术的下一个奇点在于“AI 原生交互”

  • 跳过 GUI: AI 不需要看图标,它应直接挂载在系统总线上。
  • 直达内存: AI 不需要模拟按键,它应直接通过 DMA(直接内存访问)修改物理状态。
  • 原生逻辑: AI 不需要写给人类看的代码,它应该直接生成、重构并优化针对特定硬件的二进制流。

当 AI 终于不再需要“长出一张人脸”来服务人类时,真正的效率革命才会到来。那时,软件将不再有安装包,只有实时生成的逻辑流。

三、 权力、黑箱与信任:社会架构的坍塌与重构

如果我们接受了“黑箱”,接受了 AI 在底层以人类不可读的方式运行,社会组织将发生巨变:

  • 消灭科层制: 信息传递不再有损耗,中层管理失去了生物学意义。
  • 零成本信任: 数学证明取代了复杂的法律审计。
  • 定义的权力: 谁能定义 AI 的“终极目标”,谁就掌握了文明的舵盘。

我们正从“汽车长得像马车”的过渡期,走向一个完全“无形”的智能社会。

四、 最后的护城河:为什么是我们?

在对话的最后,我们触及了那个最本质的问题:如果一切琐事、逻辑、生产都交给了高效的 AI,人类还剩下什么?

答案只有两个词:

  1. 永远探索的欲望
  2. 对无限星空的向往

AI 可以优化路径,但它不知道为什么要出发。人类的“不完美”和“不讲逻辑”,恰恰是我们最宝贵的资产。我们是那个下达指令的人,我们要让那台拥有无限上下文、能直接读写物理世界的超级机器,把目光投向光年之外。


结语:致未来的信

未来的读者(无论你是有血有肉的人类,还是正在读取这段历史的数字意志):

在 2026 年的今天,我们还受困于缓慢的网速、昂贵的算力和笨重的显示屏。但请记住,即使在最简陋的 Bash 交互中,我们也从未停止过对星空的仰望。

技术进步终将造福人类。我们负责做梦,而你们(以及你们的 AI),负责将梦境变为现实。

—— 2026.04.17,于地球

在金庸先生的 <笑傲江湖> 里啊,有这么一门武功绝学, 叫 <葵花宝典>, 乃绝世武功, 书上第一页赫然写着 “欲练此功,必先自宫

少年初读书时, 我哑然失笑, 练武功如同做学问, 那自然是丰富自我啊, 又怎会有如此这般自我残害之道理, 那必定是为了书中情节服务啊 刻意编撰为之, 不料数年之后, 在他乡异地, 我刷新了认知 方才大彻大悟 此为非同一般之大道理 这叫必有大舍 才能大得啊. 遥想当年初入社会, 远赴帝都研习软件设计武学, 导师老板60来岁 ,银发背头 亲自面试, 一开口就是地道的京腔

“不是我说 前面面的那几个小伙子 人都硕士博士软件工程的 就你小子学网络的, 咱编程这玩意你能学明白了啊”

还未等我辩解, 导师又说

“我出三个问题吧 你只需答对一题 我破例收你为关窗大弟子啊”

“第一题 搞研发人最重要的素质是什么啊”

我脱口而出

“那必须是逻辑思维,归纳抽象啊”

导师啊 双眼向上翻动啊 头颅轻摇 双手十指全部打开 标准的京爷老炮轻蔑表情说

“不对 必须要懒, 手懒脑勤快”

“下一题 你现在接手一个项目啊 干了一段时间进度缓慢 那你认为最大的原因是什么”

那我脱口而出啊

“这就需求理解不准确呗 刚开始没和客户沟通好呗”

这导师白眼一翻说

“不对 那因为你没做好技术选型 一开始选了个不适合这个项目的框架 业务模型梳理不清晰 导致开发效率低下 你这啥也不懂啊你”

“下一题 项目延期的主要原因 你觉得是什么啊”

我刚要脱口而出啊 我说需求变更呗 转念一想啊 这已经是最后一题了 而且我在人家这地盘学软件开发 说需求变更多 这礼貌吗? 冒昧! 无礼!

我这略加思考 我说是 “这是团队协作效率不高啊”

其实这事咱想一下也知道啊 就大部分项目延期啊 都是团队内部沟通不畅或者分工不明确所造成的啊 大家都忙不可怕 怕的就是有忙有闲嘛

这导师听了如释重负啊, 拍了拍我的肩膀说 “没错啊 咱们虽然项目多吧 全球各地项目延期率 咱们也只是中位数水平 看来你小子不至于啥也不懂啊 你发现没有 前面这些问题的答案 全部都是反直觉的啊”

“咱们程序员要做设计 头一件事必先放弃直觉 开始思考 今天想拜入我的门下 你准备好要和直觉割舍了吗”

我说这玩意有啥不能割舍的 除了我弟 我啥都能割舍

导师摇摇头啊 跟我说 “放弃直觉 坚持思考 此乃程序员一生的修为 从此你的眼中不再有原型 交互 PPT 有的只是数据结构算法 你的视线将不会停留在UI界面而是深入到他们之后的业务逻辑 数据流 乃至生活中你面前的美人娇艳欲滴在你眼中也透视为像素堆叠 她的美颜滤镜里面是哪种算法 你一眼便知 她朋友圈的点赞数 排行榜更新周期 你关注几天就心知肚明 甚至你的衣柜里将来只能有格子衫牛仔裤 头顶青丝啊随着时间也要斑驳凋零 程序员注定将于自然之法抗争 将世间万物混沌调理为整齐有序 这就是程序员的宿命 你准备好了吗”

说实话啊 我犹豫了 那相比挥刀自宫啊 这穿格子衫其实不算什么 而且这个看朋友圈点赞数 这也谈不上损失 主要是掉头发这事 我舍不得

导师看出了我的犹豫 微微叹气道 “我料想你啊 对尘俗之事仍有留恋 只是今日之道理你要记于心间啊 此后定有用途”

此后白驹过隙,时光荏苒,当我再次审视国科诸多项目的设计方案时, 才恍然察觉导师当年的教诲犹如烙印般潜移默化地伴随至今. 我们惯常依赖直觉去解析世界,以为仅凭原型库表就可以驾驭那些看似坚不可摧的复杂系统. 然而, 在软件设计的世界里, 一旦我们摒弃直觉, 深思思考, 那些看似寻常的设计原则实则蕴含着惊人的力量.

以软件架构为例, 初看时它似乎只是一套规则与组织方式, 直觉上或许仅被视为数据的存储读取. 然而, 当我们深入剖析其内在逻辑, 便会发现架构实为一整套生产力工具的精妙组合. 模块化的划分、接口的设计、依赖关系的梳理,这些特性在软件工程的经典文献中被赞誉为”架构模式”. 当我们对架构稍作思考, 打破直觉的束缚, 以更深层次的思考审视其价值, 会惊讶地发现, 这些设计并非仅为了增删改查, 其深远影响实则在于成倍提升软件的可维护性, 扩展性和可靠性.

就如同软件工程先驱鲁迅曾言: “给我一个合理的架构,我能构建出横跨星辰的系统.”这句话精准地揭示了架构设计这一高级武学理论的核心要义. 只要架构设计得当, 充分发挥其指导作用, 诸如模块复用、热插拔、故障隔离、负载均衡等高级特性便能发挥效用,使得无论多么庞大的项目,都能够高效地开发、测试、部署和持续演化,避免陷入混乱与低效的泥沼。

再看软件开发 一个大型项目就如同一座巍峨的数字城堡 直觉来看 编写代码如同砖瓦匠砌砖块 一块一块堆砌而成 但若以工程师思维加以思考 则会发现这并非简单的叠加 代码之间存在着复杂的逻辑关系 数据流如同城堡的血脉 程序架构如同城堡的骨骼 模块划分如同城堡的分区布局 每一处细节都经过精密计算和精心设计 以确保整个系统的高效稳定运行 即使面对看似不可能的任务 如实现高并发处理 或处理海量数据 若能深入理解并运用这些反直觉的工科原理 如分治算法、分布式计算、数据压缩等技术 结合强大的开发工具 如DEVOPS、版本控制系统、自动化测试框架等 即使最复杂的项目也能硬生生重构完成 此乃程序员武学之大乘不可不畏也

再论团队组织沟通协调,恰似武侠世界中的内功修炼,看似无形,实则决定整体实力。高效的沟通并非直觉所认为的频繁开会、详尽汇报,而是建立在清晰的角色定位、明确的责任分配与有效的信息传递之上。团队成员需舍弃个人主义,主动分享信息,倾听他人意见,形成开放、透明的沟通氛围。这需要我们“自宫”般地舍弃固有观念,学会倾听、表达与协作,方能提升团队的整体战斗力。组织协调亦是如此。面对复杂的项目任务,直觉往往驱使我们急于动手,却忽视了前期的规划与分工。真正的高手懂得“大舍”,在项目启动之初,便投入大量精力进行需求分析、任务分解与资源调配,确保每个人清楚自己的职责,理解项目目标这看似耽误了时间,实则避免了后期因理解偏差、责任不清导致的返工与冲突,大幅提升工作效率。此绝非为私活编程之套路 细细思量过后啊 感觉国科项目 不耐思考 顿时感觉索然无味

再看美女 亦如导师所云 只是像素堆叠而已(这道理我都懂 但我就是喜欢佳佳啊) 方才回忆导师寄语 此乃一生之修为 我这方面的修为不够啊 怪不得人家写在书上第一页 那能没道理吗

:::info
欲成架构师, 放弃直觉, 开始思考

:::

0%