Administrator
发布于 2025-10-27 / 3189 阅读
28

八年 Java 之路:技术成长的阶段与反思

入行第八年,回头看自己踩过的坑

十月底做年度复盘,翻出了 2018 年到现在的 git 提交记录和几份老的设计文档。有些代码现在看会脸红,但正是那些代码让我走到了现在。这篇不写技术,写成长路径上几个真实的转折点和代价。

前两年:我以为技术就是知道更多 API

2018 年刚入行,在一家做仓储系统的公司。那时候的学习方式是每周啃一个技术点:这周 HashMap 源码,下周 AQS,再下周类加载。收益是有的,面试确实好过。

但真正写代码时有个很明显的毛病:会用一个技术,却不知道什么时候不该用它

典型的一次是做库存扣减。我刚看完线程池源码,觉得「异步化」很酷,就把同步扣减改成了异步。上线第一周就出事——异步任务堆积,用户看到的库存数量和实际不一致,客服接到一堆投诉。

问题不在线程池用错了,在于库存扣减需要强一致反馈,根本不该异步。那时我完全没有「业务语义决定技术方案」这根弦,只想着把刚学的东西用上。这个阶段结束的标志是:我开始问「为什么不用这个方案」,而不是「怎么用」。

第三到五年:从写代码到写设计文档

2021 年我第一次被要求负责一个完整模块——订单履约,涉及 6 个服务的改造。我以为架构师就是画几张框图,写出来的第一版设计文档通篇是「订单中心调用库存中心,库存中心返回结果」,没有一行关于失败的处理。

带我的老架构师在评审会上问了三个问题,我到现在还记得:「库存服务超时了,订单算成功还是失败?」「用户重复提交,怎么保证只扣一次库存?」「要回滚的话,数据怎么兼容?」我一个都答不上来。

那之后我花了两周重写文档,重点全在异常路径:超时重试、幂等键、补偿流程、灰度方案、回滚脚本。第二版通过了。这个项目上线用了四个月,中间真正出问题的地方,全部在第二版文档讨论过的范围内。

这段经历让我明白,架构能力的核心不是「设计正常流程」,是穷举异常流程并且给出对策。正常流程谁都能画。

踩过的三个具体的坑

坑一:过度设计,把简单问题复杂化

2022 年我做过一个内部消息推送的小功能,需求是「配置变更时通知到各个服务」。我设计了一套基于自研事件总线的方案,支持事件溯源、事件重放、多订阅者分组,写了 4000 多行代码。

上线半年后统计,实际只用了两个事件类型、三个订阅者,事件重放功能一次都没用过。而维护成本是实实在在的——事件格式变了要兼容,序列化问题排查了三次。

教训很朴素:为三个月后「可能需要」的需求做设计,八成会错。现在我的原则是要支持 N 个场景,至少先有 N-1 个真实需求。

坑二:迷信性能优化,忽略了可维护性

2023 年优化过一个报表查询,原始版本 8 秒。我用了一堆技巧:手写字节码生成 DTO 映射、ThreadLocal 缓存、把 SQL 拆成 12 条并行查询。最后优化到 900ms,我很得意。

半年后接手的人离职了,我回去维护这段代码,发现自己都看不懂了。一个需求变更(加两个字段)花了三天,因为字段映射散落在四个地方。

后来我们把这个模块重写了一遍,用最朴素的 MyBatis + 合理索引,查询 1.4 秒。比 900ms 慢,但代码量从 2800 行降到 600 行,加字段只要改一处。那次之后我定了条规矩:性能优化的收益要能覆盖它带来的复杂度成本

坑三:技术选型跟着热点走

这个坑我踩得最久。2020 年上了 Service Mesh(Istio),当时团队只有 8 个人、14 个服务。结果是我们花了两个月学习和调试,服务间延迟增加了 3~8ms,而收益(细粒度流量治理)在那种规模下基本用不上。一年后下掉了。

类似的还有:过早引入 Kafka 替代 RabbitMQ、为了「云原生」把状态硬拆到 Redis。每一次都是「技术很先进,但我们不需要」。现在的判断方法很简单:先写清楚要解决的三个具体问题,再看技术能不能解决。说不出具体问题,就是不需要。

近两年:AI 这一波,我的学习方式变了

2024 年 AI 开始进入工作,我一开始是抗拒的——觉得这东西写的代码质量不行,还老出错。

转折点是那年年底,我试着用它读一个不熟悉的开源项目的源码,让它梳理调用链然后自己去验证。原本两天的活半天就摸清了主干,从那以后我开始把 AI 用进工作流。

但有个体会很重要:AI 的放大器效应很明显。你原有的能力强,它让你更快;判断力弱,它让你更快地写出错误的东西。团队有个实习生用 AI 生成了分布式锁实现,代码看起来很完整,但用的是 Redis SETNX 加锁、DEL 释放,没校验 value——典型错误。他自己完全没看出来,因为「代码跑通了」。

我现在的学习方法

试过很多方法,留下来的就这几条:

  • 带着问题学,不按知识点学。我不会为了「学虚拟线程」去看虚拟线程,而是先有个具体问题,再看它能不能解决。这样记得住,也知道边界在哪。
  • 学到的东西两周内必须用一次。不用的知识一个月就忘干净。
  • 读源码,但要有目标。漫无目的地读 Spring 源码是我 2019 年浪费时间最多的事。现在先有问题再去看,两小时能搞定。
  • 每年做一次技术栈盘点。列出现在用的所有技术,问自己:这个解决了什么问题?有没有更简单的方案?去年用这个方法下掉了两个中间件。

给三到五年经验的同学

这个阶段最容易陷入「什么都会一点,但说不清自己擅长什么」的困境。我的建议是找一件事做到团队里没人比你更懂。

我当时的切入点是 JVM 调优。起因是 2021 年线上出了一次 Full GC 故障,没人会排查,我硬着头皮啃了两周。之后团队里所有 GC 相关的问题都找我,这个「标签」带来的机会比我想象的多。不需要是什么高深领域,我们团队有人是「最懂 MySQL 索引的」,都很值钱。

另外一个建议:尽早接触线上。我见过工作四年没处理过生产故障的人,也见过工作两年已经能独立值班的。差距不在编码能力,在于有没有被真实问题锤过。

小结

八年下来,我觉得成长不是线性的,是几次认知跃迁:从「怎么用」到「为什么用」,从「设计正常流程」到「穷举异常流程」,从「追求技术先进性」到「追求投入产出比」。每一次跃迁都伴随着一次比较惨的失败——异步扣减那次、设计文档被打回那次、Service Mesh 白干一年那次。

现在这个 AI 快速变化的阶段,我心里其实挺踏实的。技术在变,但「把复杂问题拆清楚、把异常想周全、为结果负责」这几件事没变过。

参考