误泄露公司代码、疫情期间被裁,一个“菜鸟”程序员的生存日记
身为程序员,我们往往都了解大神级程序员的故事。比如很小就开始编程,在 11 岁时就创建了第一家能盈利的网站,16 岁上大学、17 岁成立公司、23 岁成为亿万富翁。我们喜欢这些故事,喜欢这些英雄。他们以高产的编程项目和引领潮流的方式激励着我们。从解决复杂的 NP 问题到筹集数百万的 A 轮融资,他们似乎从来不会失误。
不过,事实是这样的:每一个开发者,甚至是这些超牛逼的大神级开发者,都会把事情搞砸,然后克服挫折。不同之处只在于规模:如果我们搞砸了,数据库记录就会被破坏;如果他们搞砸了,可能就是一个价值数十亿美元的错误。为什么我们总是如此害怕错误?犯错是件好事,没有什么比失败更好的老师了。但是,它也带来了某种耻辱,没有人愿意讨论错误,因为没有人愿意被看作是天才堆中的蠢货。
但这样的压制是有后果的。当开发者犯错时,经常会被认为是个人的失败然后被指责。“Mike 忘记更新发布文档”或者“Bill 选错了分支”,这样做其实适得其反。失败通常是系统性的,是发现和纠正业务缺陷的好机会。没有比失败更好的老师了,我们不应该害怕谈论失败。本着这种精神,我坦白地指出作为一名初出茅庐的软件开发者,我所犯下的三个最严重的失误。接着,我将继续解释,我是如何从每一次的失败中成长起来的,并且我感谢这每一次的失败。
当我在一家大型金融机构工作时,我开发了一套清理 F5 网络层中未使用路由的系统。在阻塞之前,F5 路由池只能支持大约 5000 个 URL。系统会自动监控这些 URL 流量,通知未使用的资源的拥有者,并清理掉它们,这样 F5 系统就不会崩溃,不间断的人工手动操作也能被解放出来。
该系统一直运行良好,但是,在某个星期天,我醒来后看到一封电子邮件,它说前一晚有 1000 条路由被删除了,用户抱怨说这些都是活动 / 实时 URL!
大家的周末就这样被毁掉了,我们的团队立刻行动起来。原来,一个旧的 .yaml 配置文件与应用容器部署在一起,它删除了 1 周内而不是 1 个月内的非活动路由。庆幸的是,我设置了故障保护以防止删除生产资源,但是问题仍然很严重,如果我的程序确实删除了活动的资源,全公司范围内高使用率的应用程序可能会因此中断。
而结果发现,大多数资源若在一个星期内不活跃,那么一个月内仍然如此。换句话说,重要的应用不会在一个星期内都不活跃。因此,最终的损失是可控的:在被删除的 1000 个 URL 中,只有几个遭遇了投诉。但对我和我的经理来说,这也是巨大的指责和压力,特别是在损失还不清楚的早期阶段。所以我们建立了一个“作战室”,把整个团队的资源转移到手工重建这些丢失的资源上。
一开始,我认为这都是我的错。但是,事后看来,这也是一种系统性失败。第一,现有的 F5 路由管理系统不能满足业务需求,而且没有明确的备份 / 回滚策略,这是个大问题。另外,由于不必要的复杂部署过程,旧配置文件还挂在那里。这太官僚化了,很容易出问题。最终,这项关键任务交给了我一个人(也就是说,没有代码审查 / 团队参与),并且 deadline 很宽松,这简直是灾难的“配方”。我们从未将这事看得有多重要。现在,随着经验的积累再回顾过去,可以看出这一结果似乎是不可避免的。
我很感激那些站出来把我们从这场混乱中解救出来的同事们。而我的经理和最资深的开发者告诉我,他们对我这个工程师失去了信心,不让我继续参与重要项目时,我感到前所未有的职业压力。换句话说,他们不相信我做了如此愚蠢的事,也不相信我可以继续从事这个项目或者其他重要项目(他们最终撤回了)。
虽然很尴尬,但我承认我还是为此哭了。后来一位队友带我去喝啤酒,当我把谈话内容转述给他后,他说这很不公平,并且告诉我他和其他队友都非常欣赏我。这一周我一直被压得喘不过气来,听到有人这么说的时候,我终于忍不住了。另外主管还带我去吃午餐,帮我度过难关。所有这些都让我记忆犹新。
它使我了解到,尽管代码有良好的控制,但基础设施和数据却常常没有得到良好的把控。通过 DBMate 和 Terraform 等数据库迁移工具管理系统中的这些组件,并将其与应用程序代码的重要性同等对待,这一点非常关键。
对于生产环境,限制访问也是至关重要的。例如,我甚至不会在 IDE 上保留一个本地主分支,而是倾向于锁定团队范围内对非特性分支的所有直接推送。默认情况下,数据库和云账户应该是只读的,应该有明确的备份和恢复策略。例如,在我接下来的工作中,一个开发者意外地删除了 prod S3 存储桶中的文件。要不是我在一周前就设置好 S3 的版本控制策略(默认是关闭的 —— 亚马逊太坑爹了!),我们可能会永久丢失。
最后,我上了最后一课,也是最重要的一课,那就是同理心。最近我的一位队友也遇到了类似的情况:他将错误的代码投入生产,而我们不得不手工修改一些数据。他对自己的所作所为感到内疚。借此机会,我明确地解释,这是因为我们的部署数据迁移流程还不够完善,这是我们团队的失败,而不是他的失败,都是注定要发生的。与此同时,我还要提醒他,他所创造的伟大的功能,对我们和公司来说是多么重要。其错误只是提醒我们重新检查我们的工具 / 流程,这也是促使他对解决方案做出贡献。错误就是机会。
在离职之前,我把代码通过电子邮件发给了自己。在对 Spring 库进行了近一年的研究后,我创造了一些非常好的测试模式。我不想忘记这些好的想法,并打算在 Medium 博客上撰写关于这些想法的系列文章。
约一个月后,在我新入职的第一天,我收到了令我脸色煞白的短信。“哥们,我们团队出事了。有人把代码通过电子邮件发到了公司外部,这涉及到法律问题。你知道是谁干了这事吗?”
我立刻打电话给以前的经理,没有人接。打电话给我的同事,无人接听。法律部门已经介入,让他们与我断绝联系。这真是太可怕了。新经理觉得不对劲,就问起我这件事。他过去是个律师,所以他让我请律师以防万一。我急切地给妻子的家庭律师打电话,讨论了各种情况。由于牵涉到的是实用程序代码,因此他们不太可能会“找我麻烦”,但可能性还是存在的。
那天妻子来接我时,心情很好。她问我第一天过得怎么样,我回答说:“我想我搞砸了”,她脸色也变了。当我说完这件事的经过后,她像吃了定心丸一样,告诉我,虽然真的很蠢,但是我们能挺过去。接下来的一个星期,我一直生活在迷雾中,直到我前公司的法务团队找到我,告诉我,如果我签署立即删除那段代码的协议,他们就不会起诉我。
旧有观念把我束缚住了,就这么简单。尽管它看起来像一个邪恶的阴谋,但一个简单的事实是,我对我创建的模式和实用程序感到非常自豪,我认为如果我失去了它们,我就会失去一些作为开发者的东西。我有一些宏伟的想法,那就是这样可以产生一些有趣的博文,不知何故,我满脑子只想这件事,利益超过了风险。
时至今日,我依然为这次事件给我的前队友带来的影响感到难过。这个错误百分之百是我造成的,但是他们肯定要处理掉这些后果。团队的声誉可能会受损,而处理审核问题则会给大家带来很大的麻烦。这有损于我的职业声誉,并令人遗憾地中断了许多关系。
最重要的是,此后我对公司邮件和内部交流变得非常谨慎。由于在 Slack 私信中的谈话不当,在我新工作不到一周的时间里,就有几个员工被解雇了。这是一件相当混乱的事情:他们都被解雇了,而我们其他人最终也不得不参加关于工作场所骚扰的强制性人力资源培训。虽然你们公司的技术人员很不称职,但是你要永远相信他们对你的私信是完全可视的。
还有一点很重要,就是妻子和父母是如何在我身边支持我的。面对这样的局面,我感到很沮丧,头脑一片空白,是他们的冷静和理解使我回到现实。那时候,我处在生存危机的边缘:我怎么能有博士学位,同时又那么粗心大意,还那么愚蠢呢?这样会不会毁掉自己的未来?如果没有家人的支持,我可能会走火入魔,使整个局面更加糟糕。他们的建议和指导让我请来了律师,使我的处境不再那么糟糕。
YAGNI(you ain't gonna need it,你不需要它),它不仅仅是软件的一个原则。这段代码真的要再看一遍吗?即便这会带来多篇博文,也值得去冒险吗?肯定不行。如果你已经离开了一份工作,或者为了重新开始生活,那就离开吧。不要带走任何东西,别往后看,只往前看。
2019 年,我在一家比较成功的初创公司工作,致力于使路面的维护流程现代化。地方政府是我们的主要收入来源,我们还有风投的支持。这两个来源都在 2020 年 3 月突然消失殆尽。我们的公司成功地在新冠肺炎疫情爆发中度过了几个月,迅速转向应对客户需求的变化,并通过小企业救济基金获得了部分资金。
然而到了 7 月,我们显然需要收缩。CEO 亲自在 11 点半时在 Slack 上给我发了私信,让我在 12 点打个电话,这让我有种不祥之感。到 12 点 15 分的时候,我就被炒鱿鱼了。套用一句话:“Adam,我们让你走,立刻生效。我们认为你做得很好;但是,由于目前的环境,我们打算裁员”。当天,我是 15 个被无情解雇的人之一,没有任何警告,没有离职费,甚至没有 5 分钟的时间向我的团队道别(通话时 Slack 账户被禁用)。
半年前,我和妻子刚刚搬进我们的第一所房子,如果没有稳定的收入,我们的财务状况无法维持很长时间。
接下来的几个月很残酷,我哪儿也找不到工作。同病相怜的质量工程师充斥着市场。见鬼,我没有办法得到失业补偿,这让我很沮丧,于是我写了一整篇博客文章。
新冠肺炎疫情的爆发,直接导致了裁员和就业市场的低迷。但是这是一个惨痛的教训:我被解雇了,因为我不是必不可少的。企业没有我,生意也能顺利进行。他们保留的工程师技术实力很强,但更重要的是,他们在核心业务系统上工作。让他们走,可能会导致业务彻底崩溃。这就是我最大的错误。
作为一个新员工,他们将我安排在很酷的绿地项目(指的是一项不被先前工作限制的项目)上。我在 Jupyter 中从事机器学习管道和数据分析工作。但是我们的核心系统是普通的 Flask 应用。没有人真的把我推到这个系统里,所以我保持距离。当它们出现错误时,我没有解决它们。我没有在他们慢下来时支持他们,也没有人叫我这么做,所以我就没有这样做。我做的是很酷的新东西,事关公司的未来!但事实证明,这些系统,以及构建并支持它们的工程师,对公司来说,比我的价值更大。回想起来,现在已经很清晰了。反思 CEO 不得不做出的艰难决定,他还是做出了正确的让我走人的决定。
7 月至 9 月是艰难的,我在一个又一个的工作机会中被淘汰。尤其是我几乎可以在一家影音公司找到我梦寐以求的工作,但是在最后一步被拒绝了(连续两年),这让我很沮丧。最后,我接受了一份无聊的 Java 工作。我意识到,无聊的软件有直接的需求和专门的使用者,类似“这个按键不可用”之类的事情很容易解决,不需要博士学位也不需要多年的规划。
干一些无聊的事情也能让你变得更重要。从建立基础设施到处理硬功能,我自愿做了很多核心工作。尽管我的目标不是成为系统本身的一部分(也就是说,我仍然希望实现自我控制),但这将使我更难离开。
同时,我也不再担心面试和失业问题。我们只能尽力而为,努力做到最好,其他的我们都无法控制。你没得到这份工作,或许是因为另一个人在某项技术上更有经验,或许他们已经给出去了 Offer。又或者,你不像下一个候选人那样好。丢掉你的自负,坦然接受所有的理由,恐惧就会消失。意识到自己可能不是、也永远不会成为一名大神级的开发者,也没什么关系。
最终我学到的最后一点就是不断地寻求反馈。我做得怎么样?为什么我要做 X 工作?X 对公司成功至关重要吗?如果不重要,那是什么呢?别太执着于自己的工作。有时候,我们害怕反馈,因为它会挫伤我们的自尊心,但是接受反馈就是快速前进的道路。此外,如果你是拒绝给求职者反馈信息的众多公司之一,那你应该为此感到羞耻。
这一切表明,失败和障碍不仅是不可避免的,而且是必然的。个人的失败很少是个人的过错。失败是一个机会——了解自己和身边人的机会。你老板是想拆你的台,还是拉你上来?朋友和家人是否支持你?这是一个多么好的时机,让我们暂停、反思并修正方向。