狗家intern转正之后match到了现在的组,一待就快4年,组员已换了几轮。在此期间,拿了两次Superb并从3一路升到5。由于今年年初TL跑路,组里没有别我更资深的人,同时与manager并肩作战取得了一些办公室政治斗争的胜利,最终被任命为TL。特以此文记录一下这段经历(就当我写了篇升级打怪的小爽文呗)。
L3到L4
入职后不久便被分配到了一个性能优化的项目:有一个定时任务要处理产品所有的membership并找出存在风险的数据加以标记。要处理的数据量并不是特别大,但是每一次要跑个13、14个小时。在运行的过程中,这个定时任务需要去别的数据源(dependency)获取额外的数据来帮助我们自己的数据进行校验。
优化的思路其实很简单了,首先改成多线程,并把运行过程中单个单个发送的读数据请求改成运行前统一的批量获取(batch preloading),再让该任务进程下的多个线程可以共享这些批量获取到的数据(反正只读)。一顿哐啷哐啷打铁之后把运行时间从13小时减少到到了20分钟。把我老板高兴的呀,立刻发了个spot bonus。
凭借若干个类似这样scope较小但执行结果令人满意但小项目,获得了老板及组员一定程度上的信任。很快,一个对我职场发展有极大推动作用的项目A悄然落下。
项目A在组里已经做了好几年并最终停滞,这个项目有一种特殊的魔力,以至于曾经参与过这个项目的组员都已经转组或跳槽。唯一剩下还在做的组员Z,在老板的密切关注下resume了这个项目。. Χ
然后项目开展后不久,我就意识到这个项目有很多的坑:Z很早以前就承诺的design doc迟迟没有写完,Z开展了好几次的会议来“讨论”具体的design,但是来来回回都是high level地介绍这个项目要做什么,而不是从技术层面上谈及应该怎样设计怎样实现。该项目经年累月已积攒的代码从结构上看颇为完善,但是经过了多年多人的编写却从没有end to end的跑通过。每次Z被问到目前的状态离最终launch还有多少GAP,其总是支支吾吾顾左右而言他。
. From 1point 3acres bbs虽然前路不明,但项目A又异常重要,以至于有别的组迫不及待地想要依赖A。于是老板找来了别组的一位外援该Y来帮助我们开发项目A。Y完成了Z迟迟没有完成的design,并且清晰地定义了接下来要做的事情。Z也最终出局走人。
Y对该项目的贡献是巨大的,没有他的帮助这个项目不知要再拖延多少时日。但Y毕竟不是我们组的成员,没多久就被他自己的manager召回。项目A的车轮已经滚动了起来,谁也不愿让其就此终结(没有人想背项目失败的锅)。于是该项目需要一个新的带头人,这个机会落在了我的身上。
我成为这个项目的带头人之后,基本上延续着Y留下的方针路线。但是这个项目几经易手,很多domain knowledge没有得到很好的传承和贯彻。由于长期缺少一个主心骨为这个项目指明方向,很多design上看上去很美好的巧思,没有在代码层面得到落地。这些问题在end to end调通之后逐渐暴露了出来。最严重的问题有二:性能和正确性。
1. 性能方面,该项目最终级的目标是要将API的latency控制在毫秒级别(因为是end user facing)。然而初次调通之后的性能令人大跌眼镜:latency一度超过数十分钟,能够承载的QPS也屈指可数。
此时摆在我前方有两条路:一是自己独立解决,二是求助TL或其他senior一些的组员。如果我选了一但是最终又没能解决,那么我就成为了导致项目延期或失败的“罪人“,肯定影响我的绩效。如果我选了二,大概率是可以解决该问题,但也意味着我将失去了一部分credit(当然,即便失败了责任也不全在我)。
出于对自己的蜜汁自信,我决定搏一搏。最终发现在包括数据获取、据缓存及读取和应用层(处理逻辑)存在多处欠优化的地方。一顿哐啷哐啷地打铁,把延迟从数十分钟降低到了300ms,同时最高可以handle 小几百QPS。.
. check 1point3acres for more.
我把这些优化过程像讲推理故事一般抽丝剥茧地写成了文档:在某某处发现了不寻常的地方,经过某某处理和观察发现了可疑的问题所在,通过某某手段修复之后latency从大几十分钟降到10min。之后在另一处又发现问题,将latency从10min降到60s。反复如此最终降到300ms。差不多就是那种一路打怪升级的爽文。
当我把这个文档以”项目进展汇报“的形势发到了组里,很快获得了skip manager的注意和赞赏。他在文档里留了好几处抒发情绪的comment:”so satisfying”, “I can read docs like this all day”…
后来在过道上碰到他,他还特意口头表扬我说这个工作做得好,非常impressive。我暗中一笑:就这?Easy peasy啦
2. 正确性方面,该项目上线之后要取代现有产品的一个模块。因此其必须保证同样的input跑出来的output和被替代的模块完全一致。因为要被替换的模块已经线上运行了好多年,因此不一样的结果意味着项目A的正确性存在问题。
虽然得益于狗家的代码审核机制,所有源代码都有详尽的unit test。但是这些测试只能保证代码的行为和开发者脑海里预期(或PRD所定义)的行为一致。很可惜该项目没有所谓的PRD,而且当开发者对行为的预期有所偏差的时候,这些测试都成为了摆设。本来这不应该是一个问题,在项目的中早期有很多的验证机会能够修正这些偏差。但是由于人员更迭和项目管理的不力,正确性问题成为了项目上线前的最后一道关卡。
没有办法,继续硬着头皮上。参考国内同行的解决方案,组织了几次”大会战“,收集结果不同的cases并带领全组成员分工debug,最终把正确性问题完全解决,甚至发现了好几处原有component存在的bug。这些”会战“过程乏味且备受老板关注(亚历山大),但也算获得了几个意外收获:
1. 由于不是所有组员都知道该如何debug那些service,我做了详尽的knowledge sharing,手把手当着TL和manager的面展示如何定位问题所在,如何去数据源找到索引数据来交叉验证。无形之中奠定了我在这块domain expert的地位。
2. 对于找到的bug,基本上隔天甚至当天我就已经fix并完成验证。进一步展示了我的独立性和生产力。.google и
凭借这些成果,入职一年之后轻而易举地完成了3到4的升级。
L4到L5
升到4后有可考虑过换组,但是由于疫情,很快搁置了下来。经过若干个不痛不痒的小项目,迎来了最终让我升到5的项目B。
其实我在项目A中的角色已经部分做到了L5的scope。或许是得益于项目A的成功,manager对我已有一定的信任度,外加此时组里已没有其他较senior的成员有bandwidth,于是让我lead这个director非常关注的项目B。
项目B并没有什么技术层面上的难点,但是执行过程中需要和其他及不同角色(PM,UX,QA)打交道。我很快做好design并带领大概七八个组员一起开工。
期间经历了一些办公室政治:直接依赖于我们组service的兄弟组TL X某天毫无征兆地发邮件“指责”我们组进度落后,导致拖累了项目上线。然而项目一开始的时候我们两组就商量好了API,并为之提供了mock data。因此X组根本没有被我们block。此时离计划的上线timeline还有充足的时间,真正在管理项目进度的upper management也根本没有丝毫为项目进度感到担心。
我和老板商量一番后决定正面严正抗议,直指“进度落后”是无稽之谈。PgM和我们两组共同的manager也很快出面说不用担心上线时间,并不存在进度落后这个情况, 并明确要求X不要在传播这一观点。. From 1point 3acres bbs
. .и
后续的事情逐渐表明,这次只是一系列小动作的开始。很快X所在的组的另一位L5成员开始陆续发难,一边插足我们组的设计细节,一边不断表达想要“帮助”我们组做一些事情来让项目进展的更快。简而言之,就是想从我们这抢活,扩大他们组的scope并让部分成员表现leadership进而升职。
他们坚持要在我们并不需要的情况下提供“帮助”,然后顺理成章地拿走本该属于我们组员的credit。这种强盗行径,还真是符合某些西方势力的一贯作风。
随后在两个组共同的manager W面前,我的老板和X的老板开展了激烈的讨论。故事的最后,W让X那边不要踩过界插手我们的业务,并且专门起草了一份文档,来定义两个组各自的scope及合作的形式。
表面上看,这件事有了完美的结局,然而其实埋下了更多潜在的坑。这个文档之中为X组提供了很多的留白,甚至明言他们组可以在我的老板首肯的前提下,让1-2人出于扩展技术领域的目的来做本属于我们组的事情。
.--
W很显然不想做那个恶人来告诉某一边不能怎么样,他倾向于让两个组自己协商来解决,但又特意为X组留了一些可以操作的空间。究其根源,X组本身的职责范围scope有限,但却又招聘了相当数目的人员。至于我们组,由于“历史悠久”并手握足够多的(潜在)项目。从W的角度,确实没有理由让X组的人原地待命眼巴巴地看我们坐拥超出我们组capacity的项目资源。但从我们的角度,本属于我们组员、并能提供足够的impact和difficulty让组员成长晋升的项目资源将被分薄。.google и
无论如何,项目B得以继续推进。该项目让我与若干L5及L6的员工有了直接的合作。他们成为了我4升5的peer reviewer班底。足够大的impact,与多方愉快合作的经历,再加上跨多个quarter的项目管控,最后成功升到L5。
成为TL
长期以来,我们组都缺少L5及以上的工程师。在很短的一段时间内曾有过3位L5,但数量很快降为1位。甚至有段时间一位也没有,全是L3和L4大眼瞪小眼。在项目B接近尾声时,原先的TL(也是唯一的L5)跑路了。老板于是想让我来做TL。但我一开始是拒绝的,一来不想承担TL所要担负的责任(加量不加价),二来觉得自己技术深度广度都远没达到TL该有都水平,三来对需要频繁与人打交道对角色并没有什么兴趣。奈何老板“循循善诱”并将TL与升职挂钩,掰扯了两个月后最终同意。
我做TL的时间很短,与之前相比,工作中出现了几个显著的变化:
. Waral dи,
在狗家做TL听上去很cool,但我觉得自己目前阶段还是不能很好的胜任。
一来技术积累还不够。组里一向缺少资深的工程师提供指导,从3到5基本上都靠自己摸索。并不认为我面对各式各样的技术难题都能给其他较junior的组员提供正确的指导。强行为他人set technical direction弄不好误人误己。
二来我是个内向的人,与人打交道让自己的精力消耗太快。消极怠工的情绪时不时涌上心头,最严重时甚至恨不得一走了之。
除此之外,前面经历过的政治摩擦让我不看好未来大组的生态环境。未来若干年的roadmap在我看来在执行的层面只不过是重复前几年做过的类似的工作,无法带来技术上的挑战和面对未知难题的兴奋感。TL这个角色,我应该不会做很久吧。
总结
回顾这几年的经历,机遇来得确实比实力要重要。因为所在的组缺少senior的工程师,所以才会一再发生本属于L+1级别的事情下放给了L级别的我。当然也得益于,当这些机会落下的时候我很好地接住并完成。代价则是缺少与有经验的工程师共事的机会,无法在职业生涯早期学到足够多的他人智慧。当别人因为我是TL而找上我的时候,我常常发虚