
1. 从“能跑就行”到“敢让人看”工程师成长的四个隐形台阶“我的工程师之路给需要的同学”——这个标题看着朴素甚至有点老派但恰恰是这种不带修饰的表述反而让我觉得有东西可聊。网上讲工程师成长的内容太多了要么是“三个月从入门到精通”的速成神话要么是“年薪百万的架构师教你xxx”的焦虑贩卖。但真正走过这条路的人都知道工程师的成长不是一条平滑上升的直线而是一段一段的台阶每一段都有不同的坑每一段需要的思维方式也完全不同。我写这篇东西不是要给你灌什么鸡汤也不是要列一个“必读书单”或者“必学技术栈”。我想做的是把这条路上几个关键的转折点拆开来讲清楚——你现在站在哪里下一步该往哪个方向使劲以及为什么很多人卡在某个阶段好几年都上不去。如果你刚入行不久或者正在从“能干活”往“能扛事”的阶段过渡那这篇内容应该能帮你少走一些弯路。先给一个整体的框架。我把工程师的成长大致分成四个阶段每个阶段的核心矛盾不一样阶段典型特征核心矛盾突破关键第一阶段能跑就行代码能运行就交差完成任务 vs 理解任务建立“验证”意识第二阶段能扛需求独立负责模块开发写代码 vs 做设计学会拆解和抽象第三阶段能定方案主导技术选型和架构技术最优 vs 业务最优建立成本意识第四阶段能带方向影响团队技术决策做事 vs 让别人能做事从个人能力到组织能力这四个阶段不是严格按年限划分的。我见过工作两年就进入第三阶段的人也见过工作八年还停留在第一阶段的人。区别不在于智商也不在于学了多牛的技术而在于每个阶段该转变的思维方式有没有及时转过来。下面我一个阶段一个阶段地拆。2. 第一阶段代码能跑就交差然后呢2.1 “能跑”和“跑对”之间隔着一条河刚入行的前半年到一年大部分人的状态是接到一个任务打开编辑器噼里啪啦写一通本地跑一下没报错提交。完事。这个阶段的关键词就是“能跑就行”。我当年也是这样。记得有一次写一个数据处理的脚本需求是把一批订单按地区汇总然后输出报表。我三下五除二写完了本地跑了一遍数据出来了看着挺对就交了。结果上线之后业务方反馈说某个地区的数字对不上。我回去查了半天发现是那个地区的订单里有一种特殊状态的数据我没过滤掉。本地测试的时候恰好没有这种状态的数据所以没暴露出来。这件事让我第一次意识到一个问题代码能跑和代码跑对是两码事。“能跑”只说明语法没问题、逻辑没崩溃但“跑对”要求你理解数据的全貌、理解边界条件、理解异常情况。这个阶段最典型的坑就是只测自己想到的情况不测自己没想到的情况。怎么破我的经验是养成一个习惯——每次写完代码不要急着提交先问自己三个问题如果输入是空的会怎样如果输入的数据格式和我预期的不一样会怎样如果某个依赖的服务挂了或者返回慢了会怎样这三个问题不需要你每次都写完整的测试用例去覆盖但至少要在脑子里过一遍看看代码会不会直接崩掉或者产生错误的结果。很多时候你只要多想这一步就能避免大部分低级事故。2.2 日志不是写给机器看的是写给未来的自己看的第一阶段还有一个很容易被忽视的点日志和错误处理。很多新人写代码错误处理就是一句try...catch然后print(出错了)日志就是console.log(到这里了)。这种代码在本地开发的时候没问题一旦上了生产环境出了问题你根本不知道发生了什么。我踩过的一个经典坑早期写一个定时任务跑失败了没有任何记录第二天发现数据没更新但完全不知道是哪里挂的。后来我强制自己养成一个习惯——每一个可能失败的操作都要记录“什么操作、什么参数、什么错误”。比如try: result process_order(order_id, user_id) except Exception as e: logger.error(fprocess_order failed | order_id{order_id} | user_id{user_id} | error{str(e)}) raise这样出问题的时候你至少知道是哪个订单、哪个用户、什么错误。别小看这个习惯它能帮你省下大量排查时间。提示日志的级别要区分清楚。DEBUG 用于开发调试INFO 用于关键流程节点WARN 用于可恢复的异常ERROR 用于需要人工介入的故障。不要所有信息都用 INFO 或者都用 ERROR否则日志要么淹没在噪音里要么漏掉关键信息。2.3 从“我写完了”到“我验证过了”第一阶段到第二阶段的转折点就是验证意识的建立。什么叫验证意识就是你不再把“代码提交”当作任务的终点而是把“确认代码在真实环境下按预期工作”当作终点。具体来说你需要做到写完代码后自己先按真实场景跑一遍而不是只跑一个最简单的 case如果条件允许写几个自动化测试用例覆盖核心逻辑和边界条件上线后主动观察一段时间确认没有异常日志和错误报警如果出了问题先回滚再排查不要在生产环境上直接改代码这几点看起来简单但我见过太多工作三五年的人还做不到。他们提交完代码就等着别人来发现问题出了问题第一反应是“我本地是好的”。这种心态不转变永远停留在第一阶段。3. 第二阶段独立扛需求从“写代码”到“做设计”3.1 需求拆解别急着写代码先画图当你能够独立负责一个模块的开发不再需要别人手把手教你每一步怎么做的时候你就进入了第二阶段。这个阶段最大的变化是你开始需要自己做设计决策了。以前是别人告诉你“写一个函数输入 A 输出 B”你只管实现。现在变成“我们需要一个订单导出功能”剩下的你自己想。很多人这个时候会直接打开编辑器开始写写到一半发现不对劲又推翻重来。这就是典型的“没想清楚就动手”。我的经验是任何超过半天工作量的需求动手之前先画图。画什么图不是那种正式的 UML 图就是简单的框图和流程图。比如订单导出这个需求你至少要画清楚数据从哪来数据库接口文件经过哪些处理步骤过滤聚合格式化输出到哪去文件消息队列另一个接口每一步的输入输出是什么画完图之后你再看一遍很多设计上的问题在图上就能发现。比如数据量太大的时候会不会内存溢出、某个步骤失败了要不要重试、输出格式变了会不会影响下游。这些问题在图上改一笔的成本比在代码里改要低得多。3.2 抽象能力什么时候该抽什么时候不该抽第二阶段另一个核心能力是抽象。你开始发现有些代码在多个地方重复出现于是你想把它抽成一个公共函数或者公共类。这个方向是对的但很多人抽过头了。我见过一个典型的反面案例有人把所有的数据库操作都抽成了一个“万能方法”参数是一个 SQL 字符串和一个参数列表。结果就是任何人想查一个数据都要拼 SQL 字符串完全失去了类型检查和代码提示的好处。这种抽象不但没有降低复杂度反而增加了出错的风险。我的判断标准很简单如果两段代码长得像但改一个地方的时候另一个地方不一定需要跟着改那就不要抽。只有当你发现“改一个地方必须同时改另一个地方否则就会出 bug”的时候才说明它们本质上是同一段逻辑这时候抽出来才有意义。举个例子两个接口都需要校验用户权限而且校验逻辑完全一样那就可以抽成一个公共的权限校验函数。但如果两个接口只是碰巧都用了if user.is_active这个判断但一个是因为要发通知一个是因为要扣款那就不应该抽——因为它们变化的原因不一样。3.3 代码评审不只是让别人挑毛病第二阶段还有一个很重要的实践代码评审。很多团队都有代码评审的流程但大部分流于形式就是点个“同意”完事。我觉得代码评审最大的价值不是抓 bug而是知识共享和设计对齐。你写了一个模块另一个人来看你的代码他可能会问“为什么这里用队列不用直接调用”你解释一遍他理解了你的设计意图下次他遇到类似场景就知道可以这样做。反过来他可能会指出“你这个地方如果并发上来会不会有问题”你一想确实没考虑于是补上。这个过程比任何文档都有效。我自己的习惯是提交评审之前先自己看一遍 diff把明显的错误和调试代码清理掉。然后在评审描述里写清楚“这个改动解决了什么问题、核心思路是什么、有哪些地方我不太确定”。这样评审的人知道该重点看哪里效率会高很多。注意不要在代码评审里争论风格问题。缩进用两个空格还是四个空格、大括号换不换行这些应该由团队的代码格式化工具统一解决不应该占用评审的精力。评审应该关注的是逻辑正确性、边界处理、设计合理性这些真正重要的事情。4. 第三阶段主导技术方案学会在约束下做决策4.1 技术选型没有最好的只有最合适的到了第三阶段你开始需要做技术选型了。比如团队要做一个新的服务用哪个语言、哪个框架、哪个数据库、哪个消息队列这些决策需要你来拍板或者主导。这个阶段最容易犯的错误是唯技术论——什么技术新就用什么什么技术火就用什么。我见过一个团队为了做一个日活几千的小工具上来就搞微服务、上 Kubernetes、接消息队列结果光是运维成本就压得团队喘不过气来。技术选型的核心不是“哪个技术最好”而是“在当前的约束下哪个技术最合适”。约束包括什么团队能力团队里有没有人熟悉这个技术如果没人懂学习成本能不能承受时间窗口项目多久要上线如果时间紧选一个团队已经熟悉的技术比选一个更先进但需要学习的技术更明智。运维成本这个技术需要多少额外的运维投入有没有现成的监控和告警方案生态成熟度遇到问题的时候能不能快速找到解决方案社区活跃不活跃退出成本如果以后要换掉这个技术迁移成本高不高我一般的做法是列出两到三个候选方案然后针对每个方案回答上面这几个问题做成一个对比表格。不用很正式但写下来之后决策会清晰很多。维度方案 A方案 B方案 C团队熟悉度高中低学习成本低中高运维复杂度低中高社区活跃度高高中迁移成本低中高这样一对比很多时候答案就出来了。4.2 架构设计先解决当前问题再考虑未来扩展架构设计是第三阶段的核心工作。但很多人做架构设计的时候容易陷入“过度设计”的陷阱——为了未来可能永远不会发生的扩展需求把系统搞得极其复杂。我的原则是先解决当前的问题同时为未来留好扩展点但不要提前实现扩展。什么意思比如你现在要做一个订单服务预计未来可能会拆分成独立的微服务。那你现在就应该把订单相关的逻辑放在一个独立的模块里接口定义清晰但不需要现在就把它拆成一个独立的服务。等真正需要拆的时候因为模块边界已经清晰了拆起来会很快。再比如你现在用单库就能撑住那就不要提前分库分表。但你要在代码层面把数据访问层抽象好确保以后要分库分表的时候不需要改业务逻辑代码。这就是“留好扩展点但不提前实现”。架构设计的另一个关键是权衡。任何架构决策都是在多个维度之间做取舍一致性 vs 可用性、开发效率 vs 运行效率、灵活性 vs 简单性。没有哪个选择是绝对正确的关键是你知道自己在取舍什么并且能够向团队解释清楚为什么这样取舍。4.3 技术债务不是所有债都要马上还第三阶段你还会面对一个现实问题技术债务。之前的代码有设计缺陷、有性能问题、有安全隐患但业务需求一个接一个没时间重构。怎么办我的经验是把技术债务当成投资来管理而不是当成道德问题来处理。不是所有的技术债务都需要马上还有些债务可以一直背着只要它不造成实际问题。关键是你要知道哪些债务是危险的哪些是可以暂时忽略的。我会把技术债务分成三类致命债务随时可能引发线上故障的比如没有错误处理、没有限流、关键路径没有监控。这类必须尽快解决。高息债务每次改相关代码都要额外花时间的比如糟糕的抽象、混乱的模块依赖。这类应该排期解决。低息债务暂时不影响开发效率和系统稳定的比如代码风格不统一、注释过时。这类可以等有空的时候顺手处理。提示每次做需求的时候如果发现需要改动某个有技术债务的模块可以顺便把相关的债务还掉一部分。这叫“童子军原则”——离开营地的时候比来的时候干净一点。但不要为了还债而还债不要专门停下来做一个“重构 sprint”那样业务方会疯掉的。5. 第四阶段从“自己能做事”到“让别人能做事”5.1 技术影响力不是靠头衔是靠输出到了第四阶段你的价值不再仅仅体现在你写了多少代码而是体现在你影响了多少人、提升了多少团队效率。这个阶段的核心能力是技术影响力。技术影响力怎么建立不是靠 title不是靠资历而是靠持续的输出。输出什么技术方案你主导设计的方案被多个团队采用工具和框架你写的工具帮团队节省了大量时间经验分享你的技术分享让其他人少走了弯路代码评审你的评审意见帮助别人提升了代码质量新人培养你带出来的人能够独当一面这些输出的共同点是它们让别人的工作变得更好。这就是第四阶段和前三阶段的本质区别——前三阶段你关注的是“我怎么把事情做好”第四阶段你关注的是“我怎么让一群人把事情做好”。5.2 技术规划从“做什么”到“不做什么”第四阶段你还需要参与技术规划。技术规划和项目规划不一样项目规划关注的是“这个季度做哪些需求”技术规划关注的是“未来半年到一年我们的技术方向是什么”。做技术规划最难的不是决定做什么而是决定不做什么。技术世界变化太快每天都有新东西出来如果什么都想追最后什么都追不上。你需要根据业务方向、团队能力、投入产出比来判断哪些技术值得投入哪些技术暂时观望。我的经验是技术规划要跟业务规划对齐。业务明年要重点打哪个方向技术就提前在那个方向做储备。业务暂时不关注的领域技术就不要过度投入。技术是为业务服务的不是为了技术而技术。5.3 团队建设招人、育人、留人第四阶段还有一个绕不开的话题团队建设。你开始需要招人、带人、评估人。这些事情和你写代码是完全不同的技能。招人的核心不是找“最牛的人”而是找“最合适的人”。什么叫合适技术能力匹配岗位要求、价值观和团队契合、有成长潜力。我见过很多团队为了招一个“大牛”而打破薪资结构结果大牛来了之后和团队格格不入最后不欢而散。育人的核心是给机会、给反馈、给支持。给机会就是让新人独立负责一些有挑战的事情不要什么都自己扛着。给反馈就是定期和团队成员沟通告诉他们哪里做得好、哪里可以改进。给支持就是当他们遇到困难的时候你能够提供帮助而不是只会说“你自己想办法”。留人的核心是让团队成员看到成长。工程师离职最常见的原因不是薪资而是觉得“在这里学不到东西了”。如果你能让团队成员持续成长他们自然愿意留下来。6. 那些没人告诉你但迟早会踩的坑6.1 技术不是越新越好但也不能一直用旧的我见过两种极端的人。一种是“追新族”什么技术新就用什么项目里永远在用 beta 版本的东西。另一种是“守旧派”觉得什么新技术都是花架子自己熟悉的那套就是最好的。这两种都不对。技术选型要看场景。对于核心业务系统稳定性是第一位的应该选择成熟稳定的技术。对于边缘业务或者内部工具可以适当尝试新技术积累经验。关键是你要知道自己在做什么选择以及为什么这样选择。6.2 沟通能力不是“软技能”是硬技能很多工程师觉得沟通能力是虚的代码写得好才是真的。但到了第三、第四阶段你会发现沟通能力的重要性不亚于技术能力。你需要向产品经理解释为什么这个需求技术上不可行需要向老板解释为什么这个项目需要这么多时间需要向团队解释为什么选择这个方案而不是那个方案。沟通的核心不是“能说会道”而是把复杂的事情说清楚。我自己的经验是跟不同的人沟通要用不同的语言。跟产品经理沟通用业务语言跟老板沟通用成本和收益的语言跟工程师沟通用技术语言。但不管用什么语言核心都是“结论先行、逻辑清晰、有理有据”。6.3 身体是革命的本钱别不当回事这条听起来像废话但我还是要说。工程师这个职业久坐、熬夜、盯着屏幕对身体消耗很大。我见过太多人年轻的时候拼命加班三十岁之后各种毛病都出来了。我的建议很简单能站着就别坐着能走楼梯就别坐电梯能早睡就别熬夜。定期体检该休息就休息。项目再紧急也不差你多睡那几个小时。身体垮了什么技术理想都是空谈。6.4 持续学习不是“什么都学”而是“有方向地学”技术更新太快很多人焦虑得不行什么新东西都想学结果什么都学不深。我的经验是围绕你的核心方向学同时保持对周边技术的了解。比如你是做后端的那你的核心方向就是后端架构、数据库、分布式系统这些。你需要深入学。但同时你也应该了解前端的基本原理、运维的基本流程、产品的基本逻辑。这些不需要精通但需要知道它们是怎么回事这样你和别人协作的时候才不会鸡同鸭讲。学习的方式也很重要。看书、看文档、看视频都可以但最有效的学习方式是动手做。学一个新框架最好的方式是用它写一个小项目。学一个新概念最好的方式是把它讲给别人听。输出是最好的输入。7. 给不同阶段同学的具体建议7.1 如果你还在第一阶段每次提交代码前自己先按真实场景验证一遍养成写日志和错误处理的习惯不要只写print遇到问题先自己查查不到再问但问的时候要带上你已经尝试过的方案不要怕犯错但同样的错误不要犯第二次7.2 如果你正在第二阶段动手之前先画图想清楚再写抽象之前先想清楚“变化的原因是不是同一个”认真对待代码评审既看别人的代码也让别人看你的代码开始关注代码的可读性和可维护性不只是功能实现7.3 如果你已经进入第三阶段做技术选型的时候把约束条件列清楚不要唯技术论架构设计先解决当前问题留好扩展点但不要提前实现技术债务分类管理致命的先还高息的排期还低息的顺手还开始培养自己的技术影响力多做分享、多写文档7.4 如果你在第四阶段你的价值不再是你自己做了多少而是你让团队做了多少技术规划要跟业务对齐知道什么该做更知道什么不该做招人找合适的育人给机会给反馈留人让团队看到成长别忘了保持技术手感完全脱离一线会让你失去判断力8. 最后聊几句实在的工程师这条路说长也长说短也短。长的是从入门到资深需要持续投入好多年。短的是每个阶段的窗口期其实就那么几年错过了再补回来要花更大的力气。我自己的体会是每个阶段的核心任务不是学更多技术而是完成思维方式的转变。从“完成任务”到“理解任务”从“写代码”到“做设计”从“技术最优”到“业务最优”从“自己能做事”到“让别人能做事”。每一次转变都不容易但每一次转变都会让你看到一个更大的世界。如果你现在正卡在某个阶段觉得怎么努力都上不去我的建议是先停下来看看是不是思维方式需要调整而不是技术需要补充。很多时候困住你的不是技术深度而是看问题的角度。另外别太焦虑。网上那些“30岁之前必须达到什么级别”的说法看看就好别当真。每个人的节奏不一样有人快有人慢但只要方向对慢一点也能到。重要的是保持学习、保持输出、保持对技术的热情。这个行业变化很快但有些东西是不变的对质量的追求、对问题的好奇心、对用户的负责、对团队的担当。把这些不变的东西守住变化的东西自然能跟上。希望这些内容对你有用。如果你正在某个阶段挣扎或者对某个点有疑问欢迎交流。工程师这条路不好走但走过去了风景还是不错的。