有个现象,做了若干年之后回头看特别明显:起点差不多的人,三五年后差距就拉开了。有些人三年能独当一面,带着团队做核心系统。有些人干了七八年,还在接需求写接口,稍微复杂一点的任务交不到他手上。
差距来自哪?技术天赋有一点影响,但说实话不大。编程不是数学竞赛,不需要你智商超群。学历也不是决定性因素,我见过不少学历一般但成长飞快的人,也见过名校出来但几年下来原地踏步的。
观察了这么多年,我发现真正起作用的是三个层面的东西:你这个人本身的特质,你思考问题的方式,以及你选择走什么样的路。这三个层面有递进关系,前一层是后一层的基础。特质不对,思维方式很难建立起来;思维方式没养成,行动再勤快也容易跑偏。

下面一层一层聊。
先说人本身的特质
技术可以学,方法可以练,但有几个性格和态度上的特质,不具备的话,后面的都很难走远。
对编程要有真正的兴趣
这一条放在最前面,因为它是一切的前提。
编程这个职业可以干很多年,前提是你得真喜欢。不是那种刚入行时的新鲜感,而是写了好几年之后,遇到一个有意思的技术问题,你还是会忍不住想深挖下去。有这种状态的人,不需要别人推着走,他自己就会定期回头想想:这一年我进步了多少,哪些地方做得还不错,哪些地方还差得远。这种反思不是刻意为之,是自然而然的事。你打算在这行长期干下去,自然就会关心自己干得好不好。
反过来,一个对编程没什么热情的人,很容易陷入一种循环:接到需求就做,做完交差,等着下一个来。年复一年,技术没什么长进,工作也没什么成就感。
也有人说不清自己是真喜欢还是只是习惯了。有个自测标准:你周末有没有主动打开编辑器写过跟工作无关的东西?不是为了面试,不是为了完成什么任务,纯粹因为好奇。如果你最近一两年从来没有过这种冲动,那至少说明当前的状态离「真兴趣」有距离。不是说没兴趣就做不了这行,只是成长的动力会弱很多,后面那些需要持续投入的事情,坚持起来会比较难。
谦虚、细心、责任心
这三个放在一起聊,因为它们共同指向一件事:你对工作的认真程度。
谦虚这件事,不从「美德」的角度说,从实际后果说。不谦虚的人,代码审查给他提意见,他的第一反应是辩解。线上出了问题,第一反应是甩锅。觉得自己写的代码不会出错,测试走个过场就提交了。这种状态的后果有三个:跟技术成长绝缘,因为听不进别人的建议就没法改进;破坏团队协作气氛,时间一长没人愿意跟他做代码审查了;容易酿成大故障,因为对自己的代码盲目自信,上线前不做充分验证。
细心在编程领域不是加分项,是底线。一个if条件写反了,一个金额计算用了浮点数没做精度处理,一个SQL的where条件漏了一个字段导致全表更新。这些都不是什么高深的技术问题,就是不够细心。在有并发流量的系统里,一行错误的代码上了生产环境,一分钟可能就是几十万的损失。就算现在很多代码是AI辅助生成的,最终的审核把关还是得人来做。粗心大意的人,写出来的代码让整个团队跟着担风险。
责任心的判断标准只有一个:这个人做事需不需要别人盯。责任心不是绩效考核表上的一个打分项,是体现在你做事需不需要别人盯上的。 责任心强的人拿到一个项目,会先把需求完整梳理一遍,不清楚的地方主动找产品对齐。自己列项目计划和关键节点,不是等别人来排期。写完代码会做详细的自测,覆盖各种分支条件,不是扔给测试就不管了。遇到风险会立刻上报,遇到困难先自己尝试解决,解决不了找人帮忙,而不是一声不吭地卡在那里。上线之后还会观察日志,确认模块运转正常。这些表现不需要多强的技术能力,纯粹是态度问题。
这三个特质说起来都是老生常谈。但观察了十几年,做得好的人几乎无一例外都具备这些。它们不性感,也不像学了某个新技术那样有即时反馈,但长期来看,差距就在这里。
对代码要有敬畏心
敬畏心的意思是,你不会随手就写代码。拿到需求不是先敲键盘,而是先停下来想一想:这个东西该怎么设计,接口该怎么定义,数据结构用什么合适,异常情况怎么处理。用一种慢的心态去思考和决策,而不是赶着把功能堆出来。
见过两类人写代码。一类人接到需求,花半天时间想清楚方案,然后用一两天写出来,代码结构清晰,边界情况考虑到位,后续维护成本很低。另一类人接到需求,半小时就开始写,三个小时就提交了,看着效率很高,但后面改bug、处理各种边界问题的时间,加起来远超前面那个人。
有敬畏心的人,对得起自己写的每一行代码,也对得起要读这些代码的同事。 赶工交差的代码和认真设计过的代码,表面上功能都能跑,但在可维护性、可扩展性上的差距是很大的。你现在偷的懒,全都会变成以后的坑,要么你自己填,要么你的同事填。
敬畏心还会驱动你去追问更深层的东西。你不会满足于「会用就行」,你会想知道它为什么是这样的。这个追问的习惯,就是下一层要聊的东西。
比技术栈更重要的思维方式
有了前面那些基本的特质,至少不会走偏。但光有态度还不够,决定你能走多远的,是你思考问题的方式。
会用和真懂是两码事
很多人用一个技术用了好几年,对它的运行机制几乎不了解。框架配好了能跑,就不再深究为什么这么配。日常开发确实够用,直到出了问题。
一个只停留在「会用」层面的人,遇到框架行为不符合预期时,倾向于换个写法试试,或者搜一个现成方案贴上去。一个理解底层原理的人,会去看日志、查源码、搞清楚到底发生了什么,然后做出准确的判断。两种人平时的产出可能差不多,但在关键场景下的表现完全不同。技术选型要做决策的时候、线上故障要定位根因的时候、架构需要调整的时候,需要的是对技术的理解,不是操作的熟练度。
会用一个东西,说明你能完成任务。理解一个东西,说明你能做出判断。完成任务和做出判断,是两种不同层级的价值。
知道一个框架怎么用,和知道它为什么这样设计、底层走的什么机制,完全是两码事。前者是技能,后者才是知识。技能会过时,Spring Boot今天是2.x,明天就是3.x,API变了你就得重新学。但如果你理解了它背后的自动装配原理、条件注入的设计思想,版本再怎么迭代,你都能很快上手,因为核心的设计理念没有变。
举个例子。线上服务响应变慢,一般人能想到的是加缓存、扩容、优化SQL。这些手段没错,但如果不理解慢的根因,操作可能是无效的。理解了线程模型,知道连接池的工作原理,看得懂GC日志,能分析慢查询的执行计划,才能精准定位到问题出在哪一层。这种能力不是靠搜索引擎和反复试错积攒出来的,是靠平时一点一点积累底层认知得来的。

有人会说「工作中大部分时间就是CRUD,哪有机会深挖原理」。这个反驳有道理,但也有个误区。深挖原理不必非得在工作中做。下班后花一个小时读一段源码,周末研究某个框架的设计文档,这种积累不需要等公司给你机会。等到线上出了问题再去临时学,永远来不及。
细节决定了你眼里的系统长什么样
这里说的细节不是代码里变量命名之类的表面功夫,是每一层技术栈里真正在发生什么。
数据从客户端发出来,经过网络到达服务端,在操作系统内核里经历了什么,被Web容器接收后怎么分发到你的业务代码,业务代码里调用了数据库连接池,连接池内部是怎么管理连接的,SQL到了MySQL之后经过了哪些阶段,结果怎么一路返回到你的应用层。这个链路上每一环,你了解得越多,遇到问题时能排查的范围就越大,定位的速度就越快。
有些人排查线上问题又快又准,不是因为运气好,是因为脑子里有足够多的细节。看到一个现象,马上能关联到可能的原因,因为那些底层的运行机制他都了解过。没有这些积累的人,只能一层层猜、一步步试,效率差距非常明显。
你没有理解细节,就无法真正理解全貌。 同一个分布式系统,在不同人的脑子里,它的清晰度是完全不同的。有人看到的是几个方框之间连着箭头,有人看到的是每个方框内部的线程模型、序列化方式、网络协议、故障恢复机制。后者遇到问题时的思路,会比前者开阔得多。
细节了解够了之后,你会发现一件事:你能把复杂的东西用简单的话讲清楚了。很多人觉得自己表达能力差,给别人讲一个技术方案讲不明白,写技术文档写不清楚。大多数时候这不是表达能力的问题,是对那个东西理解得还不够透。当你真正把一个技术点的每个环节都搞明白了,脑子里有清晰的模型,你自然能用通俗的语言讲出来,因为你知道哪些是关键的,哪些是可以省略的,该从哪个角度切入最容易让人理解。
下次如果你发现自己给别人解释一个东西很费劲,不妨先检查一下:是不是自己还有些地方没想透。
经历和经验是两回事
工作年限长不代表经验丰富。
一个人如果每天做的事情都在舒适区里,需求来了按老套路写,线上问题来了按老办法修,三年和十年的差别只是重复的次数多了。经历在增加,经验没有增长。
真正的经验来自于复盘和思考。做完一个项目,回头想想架构上有没有更合理的方案。看到同事用了一种你没想到的解法,研究一下他的思路和你的区别在哪。读到一篇技术文章,对比一下和自己的认知有没有冲突的地方。这些事不需要额外投入大量时间,但能让同样的经历产出完全不同密度的经验。
带团队的时候见过一个工作不到3年的人,排查问题的思路和代码设计的成熟度比一些做了七八年的人还好。后来了解到,他有个习惯:每次遇到问题解决完之后,会花几分钟想想根因是什么,以后怎么避免类似的情况。这个习惯他坚持了两年多。经验的密度,不取决于时间的长度,取决于你从每次经历中提取了多少东西。
有人可能觉得「复盘」说起来容易做起来难,天天赶需求哪有时间。复盘不需要正式坐下来写文档,很多时候就是做完一件事脑子里过一遍:哪些地方做得好、哪些走了弯路、下次遇到类似场景该怎么做。把这个思考变成下意识的反应,花不了多少额外时间。差距就在这个习惯上。
还有一点。简历上能看到的东西,比如技术栈、工作年限、参与过的项目,是筛选的起点,不是终点。真正决定一个人水平上限的,是那些没法写在简历上的东西:拿到需求后怎么拆解问题,碰到陌生技术怎么上手,线上出了故障排查思路是什么。这些底层能力比表面的技术栈重要得多,因为技术栈会变,但分析问题的方式、学习新东西的能力,是稳定的。
思维方式到这里聊得差不多了。但有个问题:要从经历中提取高密度的经验,你得有足够复杂度的经历才行。如果做的项目一直是简单的增删改查,哪怕复盘意识再强,可提取的东西也有限。
具体该怎么做
前面聊了特质和思维方式,这两层解决的是方向问题。方向对了不等于能走到,很多人想法是对的,但卡在不知道怎么迈出第一步。这一部分聊具体的做法。
走出增删改查的困境
你现在每天干的活,接一个需求,建张表,写几个接口,前端传数据过来你存进去,要数据的时候你查出来返回去。你觉得没意思,觉得天天在重复,看不到成长。
为什么分到你手上的都是这种活?因为复杂的任务,主管不会交给你。一个需要深入理解业务、需要做方案设计、需要考虑各种边界情况的任务,交给一个只写过简单接口的人,他不敢赌。所以你手上永远是那些不太需要动脑子的活,你做完之后经验还是简单活的经验,下次分配还是类似的简单活。这是一个循环,得主动打破它。
一个真正有复杂度的业务系统,增删改查可能只占整体工作量的百分之二三十,甚至更少。剩下的大头在业务流程的梳理上,在状态流转的设计上,在多个模块之间数据一致性的保障上,在并发场景下的安全控制上,在代码结构如何应对频繁变化的需求上。这些东西,不亲自去做一个完整的复杂项目,根本碰不到。

怎么打破这个循环?分三步走:
第一步,主动跟主管谈。 明确表达你想承担一个完整的、有一定复杂度的业务模块。不是打杂式地写几个接口,而是从需求理解、方案设计、编码实现到最终上线,你自己负责到底。很多人从来不跟主管提这种事,觉得主管应该主动安排。但主管手下那么多人,谁主动谁就有机会,谁不吭声主管就默认你挺满意现状。
第二步,如果直接拿大项目不现实,退一步。 不要大的,给个中等规模的完整模块也行。关键是「完整」。你得自己去想表怎么设计、接口怎么划分、异常情况怎么处理、跟其他模块怎么交互。这个思考的过程本身就是成长,哪怕你想的方案不够好,主管帮你改,你也比之前只管埋头写代码的时候进步了一大截。
第三步,如果连中等的任务主管也不放心给你,跟着高手学。 跟主管说你愿意作为帮手,跟着某个资深的同事一起做一个中大型项目。看他怎么拆解一个大需求,看他怎么做技术选型,看他怎么处理那些你从来没想过的问题。一个有经验的人做项目时的思考过程、踩过的坑、做决策时权衡的因素,在任何书上都学不到。跟着走一遍,很多之前想不明白的事自然就理解了。
这三步是递进关系,能走第一步就走第一步,走不了就退到第二步,再不行就第三步。但无论如何,得迈出去。
有人会说「我们公司就是小公司,压根没有复杂项目」。这种情况确实存在。即使是小公司的简单项目,你也可以主动给自己加更高的标准。同样一个功能,考虑一下并发量大了怎么处理、数据量大了怎么办、这个模块未来可能怎么变化。项目简单不代表你的思考要简单。如果环境实在提供不了成长空间,那就需要考虑换一个环境了,这也是后面要聊的。
选一个技术方向往深处扎
广而浅的技术栈在市场上不稀缺。会用Spring Boot、MyBatis、Redis、Kafka的Java开发者有几十万。但能把JVM调优做到源码级别理解的、能把MySQL的索引优化和MVCC讲清底层机制的、能在高并发场景下做出正确架构决策的,数量就少得多了。稀缺性决定了你在市场上的议价能力。
怎么选方向?看你当前的工作内容和兴趣所在。做Java后端的,可以选JVM和性能优化、MySQL深度优化、分布式中间件、高并发架构设计中的任何一个方向深入。选哪个不是最关键的,关键是选了之后真的扎下去。
深到什么程度算深?三个自测标准:
- 核心组件的源码你读过,并且能讲清它的设计思路和关键实现
- 你能写出有深度的技术分析文章,写的过程就是逼自己想透的过程
- 面试时你能主动引导面试官聊你的长板,而不是被动回答
之前团队里有个人来面试的时候说:我只会Spring。我问了不少Spring的知识点,他都是从源码级别的维度跟我解释的,非常精准。深度理解源码让他的思路很开阔,回答难题的时候又快又准。他后来去了小米,现在已经是架构师了。面试官在意的不是你会多少种技术,而是你对技术有没有真正研究过。一个在某个方向有源码级深度的人,学其他东西也不会慢。
有人担心选错方向。这个顾虑合理,但过度纠结比选错更浪费时间。先选一个开始深入,深到一定程度后你的技术判断力会变强,要调整方向时,转型成本比浅尝辄止的人低得多。你在一个方向上训练出来的阅读源码的能力、分析问题的框架,换到另一个技术领域上照样能用。深入的经验本身是可迁移的。
环境对人的影响比你想的大
在小公司写代码,很多时候标准是「功能能跑就行」。嵌套几个for循环,SQL不建索引直接连表查,只要测试通过了就提交,因为线上压根没几个人用。这种环境待久了,你的标准会不知不觉往下掉。
当你的系统每天要承接百万级请求时,情况完全不同。一行低效的代码,一个没处理好的并发锁,上线可能就是P0级故障。在那种环境下,周围的同事都很严谨,代码审查会很严格。你被几次线上报警吓出冷汗后,自然就会对生产环境产生敬畏心。你会开始主动考虑边界条件、高并发下的数据一致性、服务的降级和兜底方案。
环境不决定你的上限,但会决定你的下限。 一个高标准的环境会强行拉高你的最低要求。在一个代码审查严格的团队待两年,你的编码习惯和思维方式会被重新校准。这种改变不是自己看几本书能获得的,它来自日复一日高标准下的实战和即时反馈。
具体怎么走?如果当前在小公司,积累一定经验后去中厂当跳板。中厂的项目规模和技术要求比小公司上一个台阶,同时门槛相对没有那么高。在中厂积累了项目经验和技术深度之后,再挑战大厂。大厂的技术体系、工程规范、高并发场景,是在中小公司很难接触到的。经历过几个有量级的项目,你的技术视野和代码品味就完全不一样了。
如果暂时去不了更好的环境,那就在现有条件下找替代方案:参与开源项目,认真研读大厂公开的技术方案和源码,在技术社区里跟有经验的人交流。不要坐等好环境来找你。
也有人在大厂待了几年反而没什么成长,因为大厂分工太细,做的事情很窄,每天就维护一个小模块。环境是必要条件,不是充分条件。进了好环境之后,还是要回到前面说的那些:主动争取复杂项目,主动深挖技术。在哪里都不能做一颗舒服的螺丝钉。
对照表:你现在在哪个位置
把前面三个层面的内容浓缩成一张自评表,你可以对照着看看自己在每个维度上处于什么阶段。
| 维度 | 还需提升 | 基本做到 | 做得很好 |
|---|---|---|---|
| 兴趣 | 当成工作做,下班不碰代码 | 偶尔学新技术,但不持续 | 遇到有意思的技术问题会主动深挖 |
| 谦虚 | 不太接受别人的意见 | 能听取建议并改进 | 主动寻求反馈,把代码审查当成学习机会 |
| 细心 | 经常因为粗心导致bug | 大部分情况下考虑周全 | 对边界条件和异常情况有本能的警觉 |
| 责任心 | 需要人催才推进 | 按时完成分配的任务 | 主动梳理需求、列计划、拉评审、自测到位 |
| 敬畏心 | 拿到需求就开始写代码 | 会想一想再动手 | 每次都做方案设计,考虑边界和异常 |
| 知其所以然 | 会用就行,不深究 | 偶尔看源码和原理 | 核心技术栈能讲清底层设计思路 |
| 关注细节 | 只关注业务逻辑层 | 了解部分底层链路 | 数据链路每一层都有认知 |
| 经验密度 | 做完项目就做完了 | 偶尔做复盘 | 每个项目都有总结和沉淀,形成方法论 |
| 项目复杂度 | 只做过简单的增删改查 | 做过中等复杂度的完整模块 | 独立负责过核心复杂系统 |
| 技术深度 | 广而浅,什么都会一点 | 某个方向有一定积累 | 至少一个方向达到源码级理解 |
这张表不是用来打分的,是用来定位的。看看哪些维度你已经做到了,哪些还有提升空间。每个人的成长节奏不一样,不需要焦虑,但需要知道自己在哪里、下一步该往哪个方向用力。
小结
做了这么多年开发,越来越觉得一件事:这篇文章讨论的这些特质和思维方式,去掉「Java」两个字,答案也一样。做Java、做Go、做前端、做数据,底层需要的东西是共通的。谦虚、细心、责任心、对代码的敬畏、对原理的追问、从经历中提取经验的习惯,这些跟具体的编程语言和框架无关。框架换了一波又一波,热点年年不同,但这些东西几十年来没变过。
技术能力的成长不是一条平滑的上升曲线。我的感受是它更像台阶,在一个平台上积累了足够多的东西,某个时刻突然上了一个台阶,看问题的角度和以前完全不一样了。台阶之间的积累期,有时候挺长的,也挺枯燥的。能不能熬过去,靠的就是前面说的那些:对这件事有没有真正的兴趣,和愿不愿意用一种认真的态度去对待你每天写的代码。
决定一个程序员能走多远的,不是他会多少种技术,是他怎么对待每一行代码、怎么思考每一个问题。
希望这篇内容可以帮到你。 最近在知乎出了秒杀专栏,感兴趣的可以订阅一下。至于知识星球的,可以搜:
老码头的技术浮生录
它是一个能实际帮你解决难题的星球。有问题的,找知心的Sam哥。
我的知乎账号:
- SamDeepThinking