实习笔记写到第11篇,正好卡在实习期的中段。前几周还在熟悉环境、读代码、跟着导师修小Bug,这两周开始独立接手一个完整的功能模块,从需求评审到上线观察全程跟下来,感触确实和之前完全不同。
这篇笔记不打算写成流水账,而是把这几周里真正花过时间、踩过坑、翻过车的东西整理出来:包括独立负责一个功能模块的完整流程,代码评审里哪些问题被反复拎出来说,还有跨部门协作时那些没人明说但很重要的工作习惯。如果你是正在实习或者刚入行的开发者,这篇应该能帮你少走点弯路。
1. 这一个月在做什么:从“跟着跑”到“带着问题跑”
1.1 实习初期的真实状态
刚进公司的前两周,大部分时间其实花在“看懂系统”上。代码仓库体量不算小,模块之间依赖关系复杂,光是把核心链路捋清楚就花了不少时间。我当时的做法是:先把项目文档粗读一遍,再顺着一个最简单的请求链路把代码从头读到尾——从接口入口、参数校验、业务逻辑到数据落库,完整走通一条线。
这种方式比漫无目的地刷代码有效得多。一条完整链路走完,你对整个项目的结构、分层方式、命名规范、异常处理习惯就都有了一个具体的认知。之后再去看别的模块,会发现大部分代码都遵循类似的路数,读起来快很多。
有个小技巧值得分享:在读代码的过程中,把每一个让自己疑惑的地方记录下来,比如“这里为什么要用异步消息?”“这个状态字段为什么是三态的?”然后带着这些问题去问导师或同事。好问题本身就是学习效率的放大器,比闷头读一天代码有用得多。
1.2 任务复杂度开始升级
进入第四周之后,手里的任务明显不一样了。之前是修小Bug、补单测、调整日志格式这类边界清晰的小任务,而这次是独立负责一个完整的功能模块——从需求分析、接口设计、数据表设计到开发自测,再到联调和提测。这意味着我要自己去拆解需求、做技术选型、定实现方案,然后找导师确认。
这种转变最关键的一点是:不再有人帮你把任务拆好,你只需要执行。你需要自己判断“这个功能涉及哪些系统”“数据从哪里来、到哪里去”“异常情况下应该怎么处理”“有没有兼容老数据的问题”。这些之前觉得离自己很远的问题,突然全部变成了自己的责任。
1.3 代码量变少,思考量变多
一个很直观的感受是:这个月写的代码总量反而没有前几周多,但花在思考上的时间大幅增加。一个接口的入参和出参怎么设计,字段叫什么名字,状态机怎么流转,错误码怎么定,这些看似简单的问题,每一个都能牵出一堆细节。
比如设计一个状态字段,不是简单定义一个整型就行,你得考虑:状态变化有没有非法迁移?并发情况下状态会不会被重复更新?历史数据里有没有脏数据需要兼容?状态变化之后需要不需要发消息通知下游?这些问题想清楚了,写代码反而是最快的一步。
我现在的习惯是:动手写代码之前,先把方案写成一页纸的文档,包含需求背景、技术方案、改动列表、风险评估、测试计划,然后拿着这个文档去找导师过一遍。一次清晰的方案评审,能避免后期大量的返工。
2. 独立负责一个功能模块的全过程复盘
2.1 接到任务后的第一件事:把需求翻译成技术方案
这个模块的功能本身不算复杂:在现有业务流中新增一种数据处理类型,涉及一个新的配置项、一条新的处理链路、以及一份结果回执。但在动手之前,我花了大半天时间梳理现状——现有代码里哪里可以扩展、哪里需要新增、哪些规则是硬编码不能动的。
这一步非常重要。很多时候我们面对一个需求,第一反应是“在哪里加一个if分支”,但成熟的开发者会先问:“这个系统原本的设计意图是什么?我的改动是顺着原设计走,还是绕过了原设计?”顺着原设计走,代码会被自然吸收;绕过原设计,短期看跑得通,长期就是技术债。
我最终定下的方案是:通过配置文件引入新类型,处理链路走统一抽象接口,不污染原有主流程。这样既有扩展性,又不影响存量逻辑。方案给导师看的时候,他提了两个问题:“新增类型之后,旧的校验逻辑还适用吗?”“配置变更后,线上存量数据需要做迁移吗?”这两个问题我确实在方案里没考虑全,又补了一轮设计。
2.2 开发期最容易翻车的三个细节
代码写起来之后,真正花时间的往往不是主流程,而是那些“看起来不起眼,出问题却很致命”的细节。
第一个是参数校验。接口接收外部传入的参数,第一道防线就是参数合法性校验。类型不在枚举范围内、字段格式不对、关键参数缺失,这些如果不在入口拦下来,就会一路穿透到业务层,产生各种诡异现象。这就像小区门禁,访客不登记就放进来,出了事情根本查不到是谁。
第二个是异常处理。很多时候我们写了try-catch就是为了“不让程序挂掉”,但catch了异常之后什么都不做,或者只是打一行日志,这种处理方式比不处理更危险。错误被吞掉之后,排查问题的时候根本无从下手。我这次专门把每一个异常出口都过了一遍:什么异常需要抛出,什么异常需要兜底,什么异常需要告警,什么异常只需要记录。
第三个是日志打点。日志不是越多越好,而是要在正确的位置打。核心业务步骤必须有入参和出参日志;分支判断最好记录一下走了哪条分支;异常必须带完整上下文。否则线上出了问题,日志找不到关键信息,就只能靠猜。
2.3 灰度逻辑与联调注意事项
这个模块从开发到上线,整个过程让我最受教的环节是灰度方案的设计。我最初的设想非常简单:测试环境验证通过,直接发布到生产。但导师提示我:这个功能涉及外部数据推送,一旦出问题影响面不可控,必须先灰度。
最终执行的灰度路径是:单机灰度 → 小流量白名单 → 按比例放量 → 全量。每一步结束都要盯监控数据,看核心指标有没有异常波动,确认没问题再进入下一步。这个节奏看起来慢,其实是给线上留了足够的刹车距离。
联调环节也有不少经验要记。与外部系统联调时,最稳妥的方式是先通过配置开关保持原逻辑不变,新逻辑只在特定测试数据上生效,这样既不会影响正常用户,又能完成联调验证。联调完成后,再逐步打开新逻辑,观察数据是否符合预期。真正上了线也不能掉以轻心,至少要持续观察一段时间的数据表现,确保没有输出异常之后,才可以把开关放量到100%。
3. 代码评审与质量门禁:实习生最容易忽略的事
3.1 一次代码评审,被拎出来的几个问题
代码写完后提交评审,这是整个实习期间“含金量”最高的环节之一。因为别人看你的代码,视角和自己完全不同。我自己觉得写得挺清楚的实现,在评审里依然被指出了不少问题。
第一个问题是命名不够准确。我定义了一个变量叫flag,意图是表示“是否启用新处理逻辑”。评审意见说:flag这个词太模糊了,三天之后再看这段代码,没人能想起来它具体代表什么。最终改成了enableNewProcess,语义清晰很多。命名是代码可读性最重要的组成部分,不能偷懒。
第二个问题是事务边界过大。我把一个事务方法里塞了很多操作,包括更新数据、发消息、调外部接口。评审意见说:事务里绝对不能做远程调用,否则事务会把连接资源占住很久,而且外部调用失败会导致整个事务回滚,引发更严重的问题。这个我确实没有考虑过,属于典型的经验盲区。
第三个问题是空值处理不统一。有些地方用了Optional,有些地方直接判断null,风格不一致。评审要求全项目统一风格,这看起来是小事,但对长期维护来说影响很大——每个人用不同风格写代码,时间一长就是一片混乱。
3.2 自己写完比评审更重要的事:自测清单
被评审出问题之后,我反思了一下:这些问题为什么自己没有先发现?最大的原因是对代码质量的标准理解不够。修好Bug只是最低要求,代码要能经得起评审,还得过几个自测维度:
- 正常链路过一遍:功能是否实现,结果是否正确
- 异常链路过一遍:参数错误、数据不存在、依赖服务超时,分别怎么表现
- 边界条件过一遍:空值、超长、重复提交、并发冲突,是否处理了
- 兼容性过一遍:存量数据、旧版本客户端、老配置项,是否兼容
自测不是走过场,而是要在合入代码之前尽可能地模拟真实场景。一个有用的方法是“破坏性测试”:把自己当作用户,故意做各种不正当的操作,看看系统是否表现正常。这个过程往往能发现测试用例覆盖不到的问题。
3.3 环境与构建:本地过得去,未必线上能跑
除了代码本身的评审,环境一致性也是实习期间踩坑比较多的地方。最典型的就是:“本地明明没问题,怎么一到测试环境就挂了?”
我遇到的情况是这样:本地连的数据库里有一条测试数据,恰好符合新逻辑的前置条件,所以跑起来一切正常。但测试环境里没有这条数据,导致新逻辑根本不会触发,结果看起来就是“功能没生效”。这个问题排查了挺久,最后发现是数据环境不一致导致的。
所以现在养成了一个习惯:凡是依赖特定数据条件的功能,先在测试环境准备好前置数据,再验证逻辑分支是否按预期触发。同时所有配置项和依赖版本都以代码仓库里的声明为准,而不是以本地环境为准。
另一个经常被忽视的问题是构建。以前觉得只要代码能编译能跑就行,后来才意识到构建产物和依赖版本才是线上真正运行的东西。本地依赖版本和仓库声明版本不一致,跑出来的结果就会有偏差。所以每次提交之前,我都会清理本地缓存重新构建一遍,确保构建依赖与仓库声明完全一致。
4. 踩过的坑与问题排查实录
4.1 常见问题速查表
| 症状 | 可能原因 | 排查方法 |
|---|---|---|
| 本地正常,测试环境异常 | 环境数据不一致、配置项不同 | 对比数据库数据和配置差异 |
| 偶发超时,重启后恢复 | 线程池被占满、连接池耗尽 | 查线程池和连接池监控,结合日志看调用链耗时 |
| 数据重复插入 | 接口被重试、缺少幂等处理 | 检查上游调用次数,确认入口是否做去重 |
| 日志里出现乱码 | 字符集不一致 | 检查应用编码与数据库/配置文件编码是否统一 |
| 功能开关打开后无效果 | 配置缓存未刷新、分支逻辑未生效 | 检查配置中心和本地缓存刷新机制 |
这张表是这段时间排查问题的经验总结,但更要紧的是培养一种意识:遇到异常先不要猜,先去日志里找证据。没有依据的猜测,大概率会把排查方向带偏。
4.2 一个耗时最长的Bug复盘
这期间印象最深的一个Bug,现象很简单:某个接口偶发返回超时,一天出现几次,不规律,重启应用后就好一段时间,过段时间又复发。
最初怀疑是数据库慢查询,查了一圈发现慢日志里没有明显异常。又怀疑是下游服务响应慢,跟踪了调用链发现下游耗时也正常。来回折腾了好几天,最后在一个偶然的机会下看到了线程池监控——核心线程数一直很高,队列在持续堆积。这才意识到问题出在线程池参数配置上。
原来这个服务的线程池核心线程数设置偏小,而任务处理中有部分操作会阻塞等待外部响应。一旦流量出现短时峰值,任务就会排队,前端表现出来就是接口超时。重启后线程池清空,症状暂时消失,之后又随着流量累积逐步显现。根本解法是调整线程池参数、缩小单任务阻塞时间,并增加线程池运行指标的监控告警。
这个过程最大的教训是:遇到偶发问题,第一反应应该是去查线程池、连接池、队列这类“中间蓄水池”的指标,而不是盯着业务日志死磕。蓄水池满了,业务才表现出异常;只盯业务表象,永远定位不到根因。
4.3 从表象到底层:排错的基本思路
排查问题是一个典型的逆向推理过程。我的习惯是:
- 先在监控面板上找到“异常指标第一次出现的时间点”
- 结合日志找到那个时刻附近发生的异常事件
- 确认影响范围是全量还是某类条件命中
- 复现问题时保持场景条件一致,避免二次污染
排查问题最忌讳一上来就凭借感觉修改代码。有人遇到Bug第一反应是“加一行日志试试”,然后反复发布验证,这样浪费大量时间且很难真正解决。更好的方式是先通过日志和监控还原完整的异常现场,确认触发条件的完整性之后,再着手修改。一次定位、一次修复,效率最高。
5. 跨部门协作与沟通:技术之外的必修课
5.1 跨部门沟通的基本姿势
这个模块涉及和外部服务进行数据对接,需要和不只一个同事协同配合。一开始我的沟通方式很“学生气”:有疑问就问,想到什么说什么,没想清楚就在群里直接发。结果发现这样效率很低,对方常常要来回确认才能明白我要表达什么。
后来总结出一个适合自己的沟通模板:先说背景和目的,再说具体的诉求和需要对方配合什么,然后给出时间节点,最后附上相关文档或代码链接。这样一段消息发过去,对方可以直接给出有效回复,不用反复追问细节。
跨部门沟通还有一个容易被忽略的点:对方也有自己的排期和任务优先级。不是说你提了需求,对方就理所应当立刻响应。提前沟通、预留时间余量、主动同步进度,这些都是职场里基本的协作素养。
5.2 如何向导师汇报进度
实习生在汇报进度这件事上,最容易踩的坑是:报喜不报忧,或者卡住了不好意思说,等到快deadline才摊牌。这两种都很被动。
我的经验是:每周固定时间同步一次整体进度,平时如果遇到阻塞超过半天解决不了,就及时找导师求助。汇报的时候按这个结构来——当前进展、遇到的问题、下一步计划、需要什么支持。不要只说状态,要说事实和诉求。
一个我自己踩过的坑是:有一次遇到问题,觉得“再试一下就能自己搞定”,结果卡了一天半,最后导师只花了半个小时就定位了原因。事后复盘,这个效率损失完全是沟通不及时造成的。实习阶段最大的优势就是你还有“新人保护期”,不懂就问不丢人,耽误进度才丢人。
5.3 关于“被否定”的心态调整
做技术的人多少都有点心气,方案被驳回的时候第一反应往往是“哪里不行?”甚至有点不服气,这是很正常的心态。但真的把别人的意见逐条听完之后,你会发现大部分反对意见本质上都不是针对你个人,而是对着代码质量和技术风险在提问题。
有一次我设计的方案被导师连续驳回了两轮,原因分别是事务范围过大和数据迁移遗漏。当时确实有点沮丧,但改完之后回头再看,这两条意见刚好堵住了后期最可能出故障的地方。如果当初坚持自己的想法,后面线上的风险大概率会变成由我来买单的事故。
所以我现在的心态调整方式是:把评审意见当成“免费的风险提示”,被驳回一次就少踩一个坑。把这种思路想清楚之后,心态就稳多了。
另外还有一个小得多的经验:同一次评审里提出的多条意见,修改完之后文字性地列出“意见清单”和“处理方式”再回给评审人,这会让对方觉得被尊重,也方便确认是否处理到位。不要只在聊天记录里说“都改了”,主动把修改记录整理清晰,是对协作效率有意义的小习惯。
6. 写在最后:实习进入中后段的个人体会
第11篇笔记写到这里,正好是一个承上启下的节点。回顾这几个月,最大的变化不是手头任务变复杂了多少,而是看问题的方式转变了:从“这个功能怎么做”到“这个功能值不值得做、做了有什么风险、出问题怎么快速恢复”,这是学生思维到职业思维的第一个台阶。
下一个阶段,我还想继续提升两个方向:一是对线上系统运行的敏感度,包括监控指标、日志分析、容量预估这些只有在真实环境里才能学到的东西;二是技术方案文档的写作能力,能把设计思路用文字清楚表达出来,本身就是一种重要的工程能力。
实习这段时间给我最大的一个感受是:学校里教的是一套体系的逻辑,职场里跑的是另一套体系的逻辑,两者之间需要大量实践去衔接。多写笔记、多复盘、多暴露问题,是连接这两套逻辑最快的办法。希望这份笔记能对也在实习路上的你有点帮助。