(此文來(lái)自樂(lè)字節(jié))
身為程序員,我們往往都了解大神級(jí)程序員的故事。比如很小就開(kāi)始編程,在 11 歲時(shí)就創(chuàng)建了第一家能盈利的網(wǎng)站,16 歲上大學(xué)、17 歲成立公司、23 歲成為億萬(wàn)富翁。
我們喜歡這些故事,喜歡這些英雄。他們以高產(chǎn)的編程項(xiàng)目和引領(lǐng)潮流的方式激勵(lì)著我們。從解決復(fù)雜的 NP 問(wèn)題到籌集數(shù)百萬(wàn)的 A 輪融資,他們似乎從來(lái)不會(huì)失誤。
不過(guò),事實(shí)是這樣的:每一個(gè)開(kāi)發(fā)者,甚至是樂(lè)字節(jié)這些超牛逼的大神級(jí)開(kāi)發(fā)者,都會(huì)把事情搞砸,然后克服挫折。
不同之處只在于規(guī)模:如果我們搞砸了,數(shù)據(jù)庫(kù)記錄就會(huì)被破壞;如果他們搞砸了,可能就是一個(gè)價(jià)值數(shù)十億美元的錯(cuò)誤。為什么我們總是如此害怕錯(cuò)誤?犯錯(cuò)是件好事,沒(méi)有什么比失敗更好的老師了。
但是,它也帶來(lái)了某種恥辱,沒(méi)有人愿意討論錯(cuò)誤,因?yàn)闆](méi)有人愿意被看作是天才堆中的蠢貨。
但這樣的壓制是有后果的。當(dāng)開(kāi)發(fā)者犯錯(cuò)時(shí),經(jīng)常會(huì)被認(rèn)為是個(gè)人的失敗然后被指責(zé)?!癕ike 忘記更新發(fā)布文檔”或者“Bill 選錯(cuò)了分支”,這樣做其實(shí)適得其反。
失敗通常是系統(tǒng)性的,是發(fā)現(xiàn)和糾正業(yè)務(wù)缺陷的好機(jī)會(huì)。沒(méi)有比失敗更好的老師了,我們不應(yīng)該害怕談?wù)撌 ?/p>
本著這種精神,我坦白地指出作為一名初出茅廬的軟件開(kāi)發(fā)者,我所犯下的三個(gè)最嚴(yán)重的失誤。接著,我將繼續(xù)解釋,我是如何從每一次的失敗中成長(zhǎng)起來(lái)的,并且我感謝這每一次的失敗。
1
刪除了上千個(gè)網(wǎng)址
當(dāng)我在一家大型金融機(jī)構(gòu)工作時(shí),我開(kāi)發(fā)了一套清理 F5 網(wǎng)絡(luò)層中未使用路由的系統(tǒng)。在阻塞之前,F(xiàn)5 路由池只能支持大約 5000 個(gè) URL。系統(tǒng)會(huì)自動(dòng)監(jiān)控這些 URL 流量,通知未使用的資源的擁有者,并清理掉它們,這樣 F5 系統(tǒng)就不會(huì)崩潰,不間斷的人工手動(dòng)操作也能被解放出來(lái)。
該系統(tǒng)一直運(yùn)行良好,但是,在某個(gè)星期天,我醒來(lái)后看到一封電子郵件,它說(shuō)前一晚有 1000 條路由被刪除了,用戶抱怨說(shuō)這些都是活動(dòng) / 實(shí)時(shí) URL!
大家的周末就這樣被毀掉了,我們的團(tuán)隊(duì)立刻行動(dòng)起來(lái)。原來(lái),一個(gè)舊的 .yaml 配置文件與應(yīng)用容器部署在一起,它刪除了 1 周內(nèi)而不是 1 個(gè)月內(nèi)的非活動(dòng)路由。慶幸的是,我設(shè)置了故障保護(hù)以防止刪除生產(chǎn)資源,但是問(wèn)題仍然很嚴(yán)重,如果我的程序確實(shí)刪除了活動(dòng)的資源,全公司范圍內(nèi)高使用率的應(yīng)用程序可能會(huì)因此中斷。
而結(jié)果發(fā)現(xiàn),大多數(shù)資源若在一個(gè)星期內(nèi)不活躍,那么一個(gè)月內(nèi)仍然如此。換句話說(shuō),重要的應(yīng)用不會(huì)在一個(gè)星期內(nèi)都不活躍。因此,最終的損失是可控的:在被刪除的 1000 個(gè) URL 中,只有幾個(gè)遭遇了投訴。
但對(duì)我和我的經(jīng)理來(lái)說(shuō),這也是巨大的指責(zé)和壓力,特別是在損失還不清楚的早期階段。所以我們建立了一個(gè)“作戰(zhàn)室”,把整個(gè)團(tuán)隊(duì)的資源轉(zhuǎn)移到手工重建這些丟失的資源上。
為什么會(huì)這樣?
一開(kāi)始,我認(rèn)為這都是我的錯(cuò)。但是,事后看來(lái),這也是一種系統(tǒng)性失敗。第一,現(xiàn)有的 F5 路由管理系統(tǒng)不能滿足業(yè)務(wù)需求,而且沒(méi)有明確的備份 / 回滾策略,這是個(gè)大問(wèn)題。
另外,由于不必要的復(fù)雜部署過(guò)程,舊配置文件還掛在那里。這太官僚化了,很容易出問(wèn)題。最終,這項(xiàng)關(guān)鍵任務(wù)交給了我一個(gè)人(也就是說(shuō),沒(méi)有代碼審查 / 團(tuán)隊(duì)參與),并且 deadline 很寬松,這簡(jiǎn)直是災(zāi)難的“配方”。
我們從未將這事看得有多重要。現(xiàn)在,隨著經(jīng)驗(yàn)的積累再回顧過(guò)去,可以看出這一結(jié)果似乎是不可避免的。
我是如何成長(zhǎng)的?
我很感激那些站出來(lái)把我們從這場(chǎng)混亂中解救出來(lái)的同事們。
而我的經(jīng)理和最資深的開(kāi)發(fā)者告訴我,他們對(duì)我這個(gè)工程師失去了信心,不讓我繼續(xù)參與重要項(xiàng)目時(shí),我感到前所未有的職業(yè)壓力。
換句話說(shuō),他們不相信我做了如此愚蠢的事,也不相信我可以繼續(xù)從事這個(gè)項(xiàng)目或者其他重要項(xiàng)目(他們最終撤回了)。
雖然很尷尬,但我承認(rèn)我還是為此哭了。
后來(lái)一位隊(duì)友帶我去喝啤酒,當(dāng)我把談話內(nèi)容轉(zhuǎn)述給他后,他說(shuō)這很不公平,并且告訴我他和其他隊(duì)友都非常欣賞我。
這一周我一直被壓得喘不過(guò)氣來(lái),聽(tīng)到有人這么說(shuō)的時(shí)候,我終于忍不住了。另外主管還帶我去吃午餐,幫我度過(guò)難關(guān)。所有這些都讓我記憶猶新。
它使我了解到,盡管代碼有良好的控制,但基礎(chǔ)設(shè)施和數(shù)據(jù)卻常常沒(méi)有得到良好的把控。通過(guò) DBMate 和 Terraform 等數(shù)據(jù)庫(kù)遷移工具管理系統(tǒng)中的這些組件,并將其與應(yīng)用程序代碼的重要性同等對(duì)待,這一點(diǎn)非常關(guān)鍵。
對(duì)于生產(chǎn)環(huán)境,限制訪問(wèn)也是至關(guān)重要的。
例如,我甚至不會(huì)在 IDE 上保留一個(gè)本地主分支,而是傾向于鎖定團(tuán)隊(duì)范圍內(nèi)對(duì)非特性分支的所有直接推送。
默認(rèn)情況下,數(shù)據(jù)庫(kù)和云賬戶應(yīng)該是只讀的,應(yīng)該有明確的備份和恢復(fù)策略。
例如,在我接下來(lái)的工作中,一個(gè)開(kāi)發(fā)者意外地刪除了 prod S3 存儲(chǔ)桶中的文件。要不是我在一周前就設(shè)置好 S3 的版本控制策略(默認(rèn)是關(guān)閉的 —— 亞馬遜太坑爹了!),我們可能會(huì)永久丟失。
最后,我上了最后一課,也是最重要的一課,那就是同理心。
最近我的一位隊(duì)友也遇到了類似的情況:他將錯(cuò)誤的代碼投入生產(chǎn),而我們不得不手工修改一些數(shù)據(jù)。
他對(duì)自己的所作所為感到內(nèi)疚。借此機(jī)會(huì),我明確地解釋,這是因?yàn)槲覀兊牟渴饠?shù)據(jù)遷移流程還不夠完善,這是我們團(tuán)隊(duì)的失敗,而不是他的失敗,都是注定要發(fā)生的。
與此同時(shí),我還要提醒他,他所創(chuàng)造的偉大的功能,對(duì)我們和公司來(lái)說(shuō)是多么重要。其錯(cuò)誤只是提醒我們重新檢查我們的工具 / 流程,這也是促使他對(duì)解決方案做出貢獻(xiàn)。錯(cuò)誤就是機(jī)會(huì)。
2
將代碼通過(guò)電子郵件發(fā)到公司外部
在離職之前,我把代碼通過(guò)電子郵件發(fā)給了自己。在對(duì) Spring 庫(kù)進(jìn)行了近一年的研究后,我創(chuàng)造了一些非常好的測(cè)試模式。我不想忘記這些好的想法,并打算在 Medium 博客上撰寫關(guān)于這些想法的系列文章。
約一個(gè)月后,在我新入職的第一天,我收到了令我臉色煞白的短信?!案鐐儯覀儓F(tuán)隊(duì)出事了。有人把代碼通過(guò)電子郵件發(fā)到了公司外部,這涉及到法律問(wèn)題。你知道是誰(shuí)干了這事嗎?”
我立刻打電話給以前的經(jīng)理,沒(méi)有人接。打電話給我的同事,無(wú)人接聽(tīng)。法律部門已經(jīng)介入,讓他們與我斷絕聯(lián)系。這真是太可怕了。新經(jīng)理覺(jué)得不對(duì)勁,就問(wèn)起我這件事。他過(guò)去是個(gè)律師,所以他讓我請(qǐng)律師以防萬(wàn)一。我急切地給妻子的家庭律師打電話,討論了各種情況。由于牽涉到的是實(shí)用程序代碼,因此他們不太可能會(huì)“找我麻煩”,但可能性還是存在的。
那天妻子來(lái)接我時(shí),心情很好。她問(wèn)我第一天過(guò)得怎么樣,我回答說(shuō):“我想我搞砸了”,她臉色也變了。當(dāng)我說(shuō)完這件事的經(jīng)過(guò)后,她像吃了定心丸一樣,告訴我,雖然真的很蠢,但是我們能挺過(guò)去。接下來(lái)的一個(gè)星期,我一直生活在迷霧中,直到我前公司的法務(wù)團(tuán)隊(duì)找到我,告訴我,如果我簽署立即刪除那段代碼的協(xié)議,他們就不會(huì)起訴我。
為什么會(huì)這樣?
舊有觀念把我束縛住了,就這么簡(jiǎn)單。盡管它看起來(lái)像一個(gè)邪惡的陰謀,但一個(gè)簡(jiǎn)單的事實(shí)是,我對(duì)我創(chuàng)建的模式和實(shí)用程序感到非常自豪,我認(rèn)為如果我失去了它們,我就會(huì)失去一些作為開(kāi)發(fā)者的東西。
我有一些宏偉的想法,那就是這樣可以產(chǎn)生一些有趣的博文,不知何故,我滿腦子只想這件事,利益超過(guò)了風(fēng)險(xiǎn)。
時(shí)至今日,我依然為這次事件給我的前隊(duì)友帶來(lái)的影響感到難過(guò)。這個(gè)錯(cuò)誤百分之百是我造成的,但是他們肯定要處理掉這些后果。團(tuán)隊(duì)的聲譽(yù)可能會(huì)受損,而處理審核問(wèn)題則會(huì)給大家?guī)?lái)很大的麻煩。這有損于我的職業(yè)聲譽(yù),并令人遺憾地中斷了許多關(guān)系。
我是如何成長(zhǎng)的?
最重要的是,此后我對(duì)公司郵件和內(nèi)部交流變得非常謹(jǐn)慎。
由于在 Slack 私信中的談話不當(dāng),在我新工作不到一周的時(shí)間里,就有幾個(gè)員工被解雇了。這是一件相當(dāng)混亂的事情:他們都被解雇了,而我們其他人最終也不得不參加關(guān)于工作場(chǎng)所騷擾的強(qiáng)制性人力資源培訓(xùn)。
雖然你們公司的技術(shù)人員很不稱職,但是你要永遠(yuǎn)相信他們對(duì)你的私信是完全可視的。
還有一點(diǎn)很重要,就是妻子和父母是如何在我身邊支持我的。
面對(duì)這樣的局面,我感到很沮喪,頭腦一片空白,是他們的冷靜和理解使我回到現(xiàn)實(shí)。
那時(shí)候,我處在生存危機(jī)的邊緣:我怎么能有博士學(xué)位,同時(shí)又那么粗心大意,還那么愚蠢呢?這樣會(huì)不會(huì)毀掉自己的未來(lái)?如果沒(méi)有家人的支持,我可能會(huì)走火入魔,使整個(gè)局面更加糟糕。
他們的建議和指導(dǎo)讓我請(qǐng)來(lái)了律師,使我的處境不再那么糟糕。
YAGNI(you ain't gonna need it,你不需要它),它不僅僅是軟件的一個(gè)原則。
這段代碼真的要再看一遍嗎?
即便這會(huì)帶來(lái)多篇博文,也值得去冒險(xiǎn)嗎?
肯定不行。如果你已經(jīng)離開(kāi)了一份工作,或者為了重新開(kāi)始生活,那就離開(kāi)吧。
不要帶走任何東西,別往后看,只往前看。
PS:自學(xué)視頻阿里P8強(qiáng)烈推薦的8個(gè)Java項(xiàng)目實(shí)戰(zhàn)大合集B站:BV1J64y1R7UN