Skip to content

第七十章 打杂

PPT写了十二页,比沈渡说的多了两页。

林知行盯着屏幕,把最后两页删掉。第十页是"需要支持",他原本想加一页"后续展望",但沈渡说过高管的注意力窗口是七分钟。多两页就多八十秒,八十秒够人走神三次。

他保存文档,关掉电脑。工位区已经空了大半,只剩几个加班的人对着屏幕发呆。程浩的座位也空了,桌上那份需求文档还摊着,封面朝上,"教育AI产品需求分析-2024Q3"几个字在顶灯下泛着光。

林知行收拾东西,背上背包。拉链头还是坏的,他用力拽了一下,没拽动,干脆不拉了,用手捏着开口走出办公楼。

第二天一早,他刚坐下,工位隔板上贴了一张纸。

纸是A4打印的,抬头写着"人员分配通知"。下面列了几个名字和对应的项目组。林知行找到了自己的名字:

林知行(外包)→ 教育AI产品组-周睿团队

旁边的程浩:

程浩(正式)→ 教育AI产品组-周睿团队

同一个团队,括号里的字不一样。

他把纸揭下来,折好放进口袋。

九点半,周睿来了。

林知行第一次见到周睿本人。四十二岁,中等身材,头发梳得很整齐,发际线比沈渡高。穿深蓝色Polo衫,胸前挂着蓝色工牌,工牌绳是公司发的那种,但他换了一根皮质的,显得更讲究。

周睿走过开放工位区的时候,沿途的人都跟他打招呼。"周总早。""周总监。"他一一点头,笑容很稳,不多不少,是那种练过的客气。

他走到林知行工位前,停下来。

"小林?"

林知行站起来。"周总监好。"

"坐坐坐,别站着。"周睿摆摆手,自己拉了把椅子坐在旁边。椅子的轮子卡了一下,他用力推了推,没推动,就那么歪着坐了。

"沈总跟我提过你,"周睿说,"说你做事认真,思路清楚。"

林知行没接话。沈渡跟周睿提过他,但提的是什么,他不知道。

"新人嘛,先熟悉熟悉环境。"周睿的语气很和缓,像在跟晚辈聊天,"我们组的工作节奏比较快,你先跟着做点基础的事情,把流程跑通。有什么不懂的,随时问。"

他从口袋里摸出一张纸,展开,上面手写了三行字:

  1. 整理历史文档(2021-2023年项目文档归档)
  2. 跑数据清洗脚本(现有数据质量问题修复)
  3. 写测试用例(核心模块回归测试)

"这三个事情不急,但要细心。"周睿说,"文档归档是基础工作,很多老文档散落在各处,找起来很麻烦。你整理好了,后面的人就方便了。"

林知行接过纸,看了看。三个任务,全是打杂。

"有问题吗?"周睿问。

"没有。"林知行说。

"好。"周睿站起来,拍了拍他的肩膀。手掌的力道不大,但停留的时间比必要的长了一点。"好好干。"

他转身走了。走了两步,又回头:"对了,程浩在你旁边,有事可以找他。他下周开始做需求分析,你们可以多交流。"

林知行点头。

周睿走远了。他走路的姿势很稳,背挺得很直,是那种在公司待久了的人才有的姿态——不是自信,是习惯。

林知行坐下,看着手里的纸。

三个任务,全是打杂。

他知道这是惯例。新人入职,不管学历高低,前两周都是整理文档、跑脚本、写测试。这些事情不重要,但必须有人做。外包员工做这些,正式员工做需求分析、方案设计、代码开发。分工明确,没有意外。

但程浩下周就开始做需求分析了。

程浩是同批入职的,985硕士,正式编制。第一周做数据清洗,第二周就转需求分析。林知行也是第一周做数据清洗,第二周继续做文档整理、跑脚本、写测试。

差别不在能力,在括号里的字。

林知行把纸折好,放进口袋。他打开电脑,开始干活。


第一个任务是整理历史文档。

公司的文档系统叫Confluence,里面存了三年的项目文档。林知行要做的,是把散落在各处的文档按项目、按年份、按类型归档。

听起来简单,做起来是另一回事。

文档格式不统一。有的是Word,有的是PDF,有的是Markdown,有的直接写在Confluence页面里。命名规则也不一样,有的用日期开头,有的用项目名开头,有的干脆叫"文档1""文档2""文档3"。

林知行写了个脚本,把所有文档按创建时间、修改时间、作者、关键词分类。脚本跑了两个小时,输出了一份清单:三年内共创建了1,247份文档,其中326份没有标题,89份是空文档,17份是测试文档。

他把空文档和测试文档筛掉,剩下800多份有效文档。然后他开始一份份看,判断归属、打标签、移动到正确的目录。

这个过程枯燥,但有用。

他看到了产品的历史。2021年立项,当时叫"智能教育助手",功能很简单,就是给学生推荐题目。2022年改名"教育AI产品",加了教师端功能,开始接入学校数据。2023年大改版,加了AI答疑、智能批改、学情分析,架构从单体变成了微服务。

每次改版都有技术决策文档。林知行一份份看过去,发现一个规律:每次改版,旧模块的文档都会"丢失"。不是真的丢失,是没人更新,过时了,后来的人就不再看。

三年下来,产品里积累了大量"技术债"——那些为了快速上线而做的妥协、为了兼容旧功能而加的补丁、为了绕过bug而写的临时方案。

这些技术债藏在代码里,藏在文档里,藏在那些没人维护的角落里。

林知行开始记笔记。

他打开一个新文档,标题是"教育AI产品技术债梳理"。每发现一个技术债,他就记下来:问题描述、影响范围、根因分析、建议修复方案。

第一个技术债:数据采集模块的接口设计。

2022年立项时,数据采集模块用的是同步接口,每次请求都阻塞,等待数据源返回。后来数据源增加到五个,同步接口成了瓶颈,响应时间从200毫秒涨到了2秒。

有人提了个方案:改成异步接口,用消息队列做缓冲。方案通过了,但实施的时候,为了兼容旧代码,没有完全改成异步,而是在同步接口外面包了一层异步适配器。

结果是:新旧两套接口并存,代码复杂度翻倍,维护成本上升。更糟的是,两套接口的行为不一致——同步接口返回的是实时数据,异步接口返回的是缓存数据,有时候两者的结果会冲突。

林知行在文档里写了根因:架构设计时没有考虑扩展性,改版时为了兼容旧系统做了妥协,导致技术债累积。

第二个技术债:教师评估模块的算法设计。

这个模块给教师打分,基于学生的成绩、出勤率、教学反馈三个维度。算法是2022年设计的,用的是简单的加权平均。

问题是:三个维度的权重是硬编码的,不能动态调整。而且数据源的质量不一样——成绩数据最准,出勤率数据有缺失,教学反馈数据有噪声。

硬编码的权重意味着:如果某个维度的数据质量变差,整个评分都会被拉低,但算法不知道。

林知行在文档里写了根因:算法设计时没有考虑数据质量问题,权重分配缺乏灵活性。

第三个技术债:推荐模块的解释功能。

这是他最熟悉的方向。推荐模块给学生推荐题目,但不解释为什么推荐这些题目。学生看到一堆题目,不知道是根据什么逻辑推荐的,信任度很低。

2023年有人提了个方案:加一个解释层,给每条推荐加一句说明。方案通过了,但实施的时候,只做了一半——解释是硬编码的模板,不是根据实际数据生成的。

结果是:解释看起来像是套话,用户很快就忽略了。

林知行在文档里写了根因:解释功能的需求没有被真正理解,实现方式偷工减料,导致功能形同虚设。

他写了两天,整理了十二个技术债,每个都有问题描述、影响范围、根因分析、建议修复方案。文档加起来三千多字。

周三晚上,他把文档发给了沈渡。

发的时候,他犹豫了一下。文档里有些内容直接指向周睿负责的模块——数据采集模块是周睿主导设计的,教师评估模块也是周睿团队做的。

但他还是发了。因为沈渡是技术VP,他需要知道产品的技术债情况。而且沈渡教过他:周报要写"做了什么"和"为什么这么做"。这份文档就是他的"做了什么"——整理历史文档的过程中,顺便梳理了技术债。

发完文档,他继续做第二个任务:跑数据清洗脚本。


数据清洗脚本是现成的,但数据质量问题很多。

林知行跑了三天脚本,修了四百多条数据。有些是格式错误——日期字段存成了字符串,数字字段多了空格;有些是逻辑错误——学生的成绩比满分还高,教师的出勤率超过了100%;有些是缺失值——某个字段是空的,但下游模块依赖这个字段,导致报错。

他一边跑脚本,一边记笔记。数据质量问题的背后,是数据采集模块的设计缺陷。很多问题本可以在采集阶段避免,但采集模块没有校验逻辑,脏数据直接入库。

他把这些发现也加进了技术债文档。

周四下午,沈渡回了消息。

消息很短,只有一句话:

"你开始看到问题了。"

林知行看着这句话,等了几秒。沈渡没有继续发。

他又等了几秒。

沈渡又发了一条:

"但注意——你的分析里有三处直接指出了周睿负责模块的设计缺陷。如果这篇文档被周睿看到,后果自负。"

林知行盯着屏幕,手指停在键盘上。

他知道沈渡说的是哪三处。数据采集模块的异步适配器问题、教师评估模块的硬编码权重问题、推荐模块的解释功能半吊子实现——这三个技术债,都指向周睿负责的模块。

他在写的时候注意到了,但没有刻意回避。因为技术债就是技术债,不因为是谁负责的就不存在。

但沈渡的提醒让他意识到一件事:在大厂里,指出问题是危险的。尤其是指出领导的问题。

他打开文档,看了看共享权限。

"全组可见。"

他把权限改成了"仅自己可见"。

改完之后,他盯着文档看了很久。文档的标题是"教育AI产品技术债梳理",副标题是他自己加的——"基于2021-2023年历史文档的分析"。

这份文档,他花了两天时间写,梳理了十二个技术债,每个都有根因分析和修复建议。如果公开,对产品的改进会有帮助。

但如果公开,也会得罪人。

他想起沈渡的话:"在公司里,看懂问题和说出来是两件完全不同的事。"

他看懂了技术债。但他不能说出来。

至少不能公开说出来。

他关掉文档,继续做第三个任务:写测试用例。


测试用例是给核心模块写的回归测试。

林知行花了一周时间,写了两百多个测试用例,覆盖了数据采集、教师评估、推荐三个模块的核心功能。写测试用例的过程,让他对产品的技术细节有了更深的理解。

他发现了很多边界case——输入为空怎么处理、并发请求怎么处理、超时怎么处理。有些case,现有代码没有覆盖,一旦触发就会出bug。

他又把这些发现记了下来,但没有写进技术债文档。他写在了一个私人笔记里,标题是"待修复的问题"。

这个笔记,只有他自己能看到。

两周过去了。

林知行完成了周睿分配的三个任务:历史文档整理好了,数据清洗脚本跑完了,测试用例写好了。他还顺便梳理了技术债、发现了边界case,但这些额外的工作,他没有告诉任何人。

周睿在周报里给他写了一句评语:"工作认真,完成度高。"

程浩的需求分析也做完了。他在周会上汇报了分析结果,周睿听完后点了点头,说:"不错,继续深入。"

林知行坐在下面听,没有说话。

他的周报写得很规矩,按照沈渡教的格式:做了什么,为什么这么做。但他没有写技术债梳理,没有写边界case发现。只写了三个任务的完成情况。

周会结束后,他收拾东西准备下班。

走到门口的时候,他路过周睿的办公室。门半开着,里面亮着灯。周睿坐在办公桌后面,手里握着电话。

林知行没有停步,但脚步慢了一点。

他听到了周睿的声音。

"……沈渡塞过来的那个人,大专学历,做外包的……"

声音不大,但在安静的走廊里很清楚。

"……对,先放着,看他能折腾出什么……"

林知行继续走,没有回头。

他的脊背发紧,肩膀绷着,手指攥着背包带。但他走得很稳,步伐没有乱。

走出办公楼,天已经黑了。中关村的霓虹灯招牌亮着,红的、蓝的、绿的,映在玻璃幕墙上。

他站在路边,等红灯。

绿灯亮了,他跟着人群过马路。

走到马路对面,他停下来,回头看了一眼办公楼。五楼的灯还亮着,那是周睿办公室的方向。

他转过头,继续走。

背包的拉链头又掉了。他蹲下去捡,手指在路灯下摸索。

找到了。他把拉链头塞进口袋,站起来,继续往青旅的方向走。

路上,他想起周睿说的那句话:"沈渡塞过来的那个人,大专学历,做外包的……先放着,看他能折腾出什么……"

语气不重,甚至带着点随意。像是在聊一个不重要的人,一个可以先放着、不急着处理的人。

林知行走到青旅门口,推开门。前台的小妹在看手机,抬头看了他一眼,又低下去了。

他走到自己的床位,放下背包,躺下来。

天花板上那道裂缝还在,从这头延伸到那头,像一条干涸的河。

他盯着裂缝,脑子里在跑一个算法。

输入:周睿的态度("先放着,看他能折腾出什么"),程浩的待遇(正式编制、需求分析任务),自己的处境(外包身份、边缘工作、灰色工牌)。

输出:?

他算不出来。

因为这个算法的变量太多,而且很多变量是他看不到的——周睿跟沈渡的关系、周睿对激进派的态度、周睿在公司的政治立场、周睿对学历的看法。

这些变量,他一个都不知道。

他闭上眼睛。

明天还要继续做周睿分配的任务。后天也要。大后天也要。

他必须在两个月内做出点什么。

但第一周,他只做了数据清洗。第二周,他做了文档整理、数据清洗、测试用例。

第三周呢?

他不知道。

但他知道,周睿在看他。沈渡也在看他。

而他,只能继续做那些"不重要但必须有人做"的事情。

然后,等一个机会。

他翻了个身,把脸埋进枕头里。

枕头有汗味,是上一个人留下的。

他没在意。

他想起父亲说的那句话:"到了打个电话。"

他还没打。

不是忘了,是不知道说什么。

说他做了两周打杂的活?说他被分配到了一个不待见他的团队?说他的灰色工牌和灰色工位?

他拿出手机,看了看时间。晚上九点半。

父亲应该还没睡。

他打开通讯录,翻到"爸"。

手指悬在拨号键上,停了几秒。

然后他锁了屏幕,把手机塞回枕头底下。

明天再说。

(本章完)