HTML/CSS

大厂干了十年,然后呢?

技术人职业第二曲线

一、35岁不是终点,是拐点

每隔一段时间,“35岁被裁”就会冲上热搜。评论区一片哀嚎,好像到了这个年纪,代码生涯就自动进入倒计时。

我见过不少同行的真实经历。有人35岁确实被优化了,但转头拿了更好的offer;有人28岁就焦虑到不行,觉得35岁魔咒会落到自己头上。这两种人的区别,不是技术能力,而是对职业周期的理解。

越优秀,越难转型

有个场景你一定不陌生:一个技术很强的Leader,手下的活几乎都过他的手。白天开会,晚上写代码,周末review。团队成员反而很闲,等着他分配任务,等着他把方案定好。

这个人累得半死,团队成长停滞,业务推进缓慢。但他自己觉得挺充实——"至少事情没掉地上。"

这种场景太常见了。而且有个规律:越是优秀的IC(个人贡献者),转型管理者时越容易掉进这个坑。

优秀为什么会变成陷阱

做IC的时候,你的价值等于你解决问题的能力。代码写得好、架构设计得巧、线上问题处理得快——这些是你被认可的原因。

转成管理者后,评价体系变了。你的价值不再是"你做了什么",而是"你的团队产出了什么"。之前让你闪光的能力,现在可能正在拖你的后腿。

因为太擅长解决问题,你会本能地冲上去:"算了,我来吧。"每一次"我来",你就少了一次观察团队、思考方向的机会。更糟的是,团队会习惯等你兜底,主动性和成长空间都被你"优秀"地压死了。

说白了,做IC时,优秀是你的加速器;做管理者后,同样的优秀可能变成团队的限速器。

真正的转变不是做更多,而是学会不做

我观察过一些转型比较成功的技术管理者,发现他们有一个共同点:不是技术变差了,而是对"成就感来源"做了迁移。

同步不再将就

上个月,一个朋友在群里吐槽:他们的在线文档产品要加多人协作功能,技术负责人评估了一下,给了个方案——用 WebSocket 广播所有编辑操作,冲突了就提示用户"文档已被他人修改,请刷新后重试"。

我问他,你们打算让用户刷新多少次才能写完一段话?

这不是段子。在我见过的技术选型里,"广播 + 冲突提示"仍然是很多团队处理实时协作的第一反应。理由很简单——实现成本低,逻辑好理解。但这条路的尽头,是一个永远填不完的坑。

冲突不是边缘情况

想象一个场景:两个人同时编辑同一份文档的同一行。A 把"用户协议"改成了"服务条款",B 在同一位置加了个逗号。两个操作几乎同时发生,网络延迟让它们到达服务器的顺序不确定。

传统做法要么让 A 的修改覆盖 B 的(后到的覆盖先到的),要么把文档锁住让 B 等 A 改完。前者丢数据,后者体验差。

CRDT(Conflict-free Replicated Data Type,无冲突复制数据类型)提供了第三条路:从数学上保证,只要操作满足交换律和结合律,无论网络传输顺序如何、延迟多长,所有客户端最终都会收敛到同一份数据。不需要中心服务器仲裁,不需要锁,不需要用户手动解决冲突。每个操作本身就是一个独立的、可传播的、可合并的单元。

从论文到产品的距离

微前端落地两年,我们开始往回收了

上个月,我们默默地把三个微前端子应用合并回了两个。没有发公告,没有写技术复盘,就是安安静静地把代码挪了回去,删掉了两个仓库,关掉了四条CI流水线。

如果有人在半年前问我"微前端到底好不好",我大概率会给他列一堆优点:独立部署、技术栈无关、团队自治。但现在我的回答变了:看你的团队到底有没有拆的必要。

这个判断听起来像废话,但我见过太多团队在这件事上栽跟头,包括我自己。

拆的时候有多爽,合的时候就有多痛

故事的开始总是相似的。一个大型前端项目,十几个开发者在同一个仓库里撞来撞去,merge冲突是家常便饭,发版节奏互相牵制。有人提了微前端,方案评审会上大家眼睛都亮了——每个团队自己的子应用、自己的发布节奏、自己的技术栈,互不干扰,多美好。

我们也是这么想的。2024年初,基于qiankun把主应用拆成了五个子应用,按业务域划分。前半年确实爽:团队A改了代码不用等团队B review,团队C想用新版本的React自己升,团队D甚至单独搞了一套构建流程。

问题是从第二年开始集中爆发的。

DRY的幻觉:你消灭的重复,正以耦合的形式回来找你

DRY——Don't Repeat Yourself。这四个字母可能是软件工程里被引用最多、被误解最深的原则。

每个程序员入行第一天就被告知:重复代码是邪恶的,看到重复就要提取,看到提取就要抽象,看到抽象就要泛化。于是我们疯狂地消灭重复——公共函数、工具类、基础库、共享模块......代码库越来越"干净",重复率越来越低,CI里没有任何duplicate code的警告。

然后某一天,一个业务需求来了——需要改动某个"公共"逻辑。你打开那个被47个地方引用的utils函数,改了一行,跑了一下测试——绿了。上线,结果三个业务线同时报警。你突然发现,那三个业务线依赖的是同一个函数的三种不同行为,被那个"公共"函数强制统一了。

你消灭了重复代码,但你制造了耦合。而耦合,是比重复贵十倍的技术债。

 

重复代码不是问题,问题是不知道为什么重复

 

所有关于DRY的讨论,都默认了一个前提:重复等于坏。但这个前提本身就是幻觉。

重复代码至少有三种完全不同的面目。

第一种是意外重复——两个开发者不知道对方写了同样的功能,造了两个轮子。这种重复才是真正需要消灭的,因为它意味着信息浪费和潜在的不一致。

微前端的悖论:拆得越独立,耦合越深

2021年前后,微前端是前端圈最火的架构概念。qiankun、single-spa、Module Federation,各种方案轮番上阵,每过几个月就有一篇"微前端最佳实践"刷屏。团队的架构升级PPT里如果没挂一个微前端的示意图,都不好意思拿出来汇报。

三年过去了,真正在线上跑过微前端的人,大多有一种心照不宣的沉默:方案落地了,页面跑起来了,但总觉得哪里不对劲。

不对劲的地方,通常不在PPT里。

 

三个承诺和一个现实

 

微前端刚出来的时候,给了三个承诺:技术栈无关、独立部署、团队自治。每一个听起来都很美,每一个在实践中都打了折。

技术栈无关意味着子应用可以自由选择框架。React的团队用React,Vue的团队用Vue,听起来皆大欢喜。但"无关"只存在于第一个版本。三个月后,你会发现共享组件怎么办——A子应用用React写了一套表格组件,B子应用用Vue想要相同的交互,是再写一遍还是搞iframe嵌套?六个月后,你的招聘成本翻倍了,因为新人得同时熟悉两套技术栈的代码风格。一年后,某个子应用的技术栈要升级,但它和其他子应用之间的样式隔离出了问题——因为当初"无关"的时候,没人定义样式边界的规范。

技术栈无关真正的代价不是今天允许你自由选择,是明天让你无法统一收口。

你写的不是代码,是期权:用金融思维重新理解技术决策

每次做技术选型的时候,我都会想起期权定价模型。不是因为我爱装,是因为这玩意儿真的解释了大部分技术决策为什么会翻车。

做金融业务的人应该对这个逻辑不陌生——一个期权的价值,不取决于标的资产今天的价格,而取决于它未来的波动率、到期时间和执行价格。

技术选型也一样。你选一个框架、一个架构、一个技术栈,本质上是在买入一个期权。而大部分团队在做这个决策的时候,只看了"执行价格"——也就是今天的采用成本,完全忽略了到期时间和隐含波动率。

 

执行价格:你以为的成本只是首付

 

选React还是Vue?选微服务还是单体?选自研还是开源?这些决策的讨论,90%都聚焦在"今天迁移要花多少人力"上。

这就是只看执行价格。

我见过一个团队花了三个月从Vue迁到React,理由是"React生态更丰富"。三个月后确实迁完了,但接下来的一年里,团队不断在解决React生态的碎片化问题——路由、状态管理、样式方案,每一个都要做一个子决策。而当初评估迁移成本的时候,这些子决策根本没算进去。

就像买房只算了首付,没算物业费、维修基金和房产税。

设计系统的尽头是没人用

每个前端团队最终都会走上同一条路:建组件库,搞设计系统,画设计规范文档。

然后看着它慢慢死去。

不是夸张。我见过太多团队花大力气搭了一套设计系统,上线时热热闹闹,半年后只剩一个人在维护,一年后连那个人也转岗了。业务线该自己封装的还是自己封装,该重复的还是重复,设计系统变成了一座精美的鬼城。

这个现象太普遍了,普遍到已经不值得用"执行力不够"来解释。问题不在人,在设计系统这个事情本身的逻辑里。

 

建设者的幻觉

 

设计系统的出发点通常很理想:统一视觉规范,提高开发效率,减少重复劳动。听起来无懈可击。

但这个逻辑有一个隐含前提——业务足够稳定,需求足够规范,变化足够可控。

现实呢?

金融产品恨不得每周换一轮视觉,大促活动页面跟日常页面完全是两套设计语言,某个业务线因为合规要求必须用特殊样式,另一个业务线因为老板拍板要用新风格。你精心设计的 Button 组件有十二个 variant,但业务要的是第十三个。

设计系统的建设者往往是架构团队或基础设施团队。他们离业务远,有时间做抽象。但离业务远恰恰是问题所在——你抽象出来的东西,天然跟不上业务的节奏。

Serverless:复杂度没有消失,只是换了地址

2018年前后,Serverless在国内技术圈火了一阵。各大云厂商轮番布道,"按需付费"、"零运维"、"自动扩缩容"——每个口号都精准戳中了团队的痛点。我当时也投入了不少精力研究,毕竟谁不想不用管服务器?

几年过去了,当初那些All in Serverless的团队,相当一部分已经在往回走。不是Serverless不好,而是很多人慢慢意识到:当初以为消灭的复杂度,其实只是搬了个家。

 

那些承诺里没写的小字

 

Serverless的核心承诺有三条,每一条都有对应的现实版本。

"不用管服务器"——开发者只需写业务逻辑,基础设施平台托管。这对前端团队尤其有吸引力,写完函数丢上去就能跑,不用折腾部署和运维。但现实是,你很快会发现自己需要关注函数的内存配置、超时时间、并发限制、冷启动策略、VPC配置、IAM权限……这些不叫"服务器运维",但本质上还是在管基础设施,只是换了个仪表盘。

"按需付费"——代码不运行就不收钱,空转成本消失。但下一句没人告诉你的是:按需付费的反面是成本不可预测。一个函数死循环触发重试,一个爬虫突然疯爬你的API,一个配置错误导致无限调用——这些异常场景下的账单,会让你深切怀念固定成本的日子。

发布恐惧怪圈:你加的每道门禁都在让发布更危险

上周有个做支付系统的朋友跟我吐槽,他们团队每次发版要过六道门禁——代码审查、单元测试覆盖率、集成测试、安全扫描、性能基线、人工审批。听起来很严谨对吧?结果他们每次发布的变更量越来越大的同时,线上故障却没有减少。反而因为每次发布都是"大手术",一出问题就是大问题。

这不是个例。我观察过不少团队,尤其是金融、支付这类对稳定性要求极高的业务线,都有一个共同的倾向:发布越怕出错,就越加流程;流程越重,发布频率越低;频率越低,每次发布承载的变更越多;变更越多,出错概率越高——然后更怕出错,继续加流程。

这就是发布恐惧怪圈。而最反直觉的地方在于:你加的每一道门禁,都在让下一次发布更危险。

 

门禁越多,发布越重

 

这是最直接的后果,也是最容易被人忽视的。

假设一个团队每周发布一次,每次发布平均包含 15 个 commit 的变更。后来因为一次线上事故,决定加强管控:发布前必须经过安全扫描和性能基线验证,流程从一天变成了三天。发布频率自然从每周一次降到了每两周一次。但开发节奏没变,两周的变更量是 30 个 commit。

看到了吗?单次发布的爆炸半径翻倍了。

页面