2018 年的時(shí)候,我開始在彭博社(Bloomberg)工作。從那之后,事情發(fā)生了很大變化。我不再是公司里最初級(jí)的成員了,而且我還指導(dǎo)過幾個(gè)工程師,這真是太棒了。這有助于我觀察自己與其他人的差別,吸收他們的最佳實(shí)踐,并發(fā)現(xiàn)我不知不覺中已經(jīng)做得很好的事。
每年的工作回顧是一個(gè)很好的方式來提煉我學(xué)到的經(jīng)驗(yàn)教訓(xùn)。它們對(duì)于模式匹配也很有價(jià)值。只有我從特定模式觀察時(shí),才會(huì)發(fā)現(xiàn)問題。然后我就 開始有意識(shí)地跟蹤這些模式。
今年的宏觀主題是擴(kuò)大眼界并挑戰(zhàn)邊界。它還涉及到聚焦視野,以及向去年的章節(jié)中增加細(xì)微差別。如果你 預(yù)先讀過我去年的評(píng)論 就更有意思了:你就可以區(qū)別出我的成長。
這些回顧都從一個(gè)問題開始:我如何進(jìn)一步成長?
進(jìn)入第二年的時(shí)候,我已經(jīng)準(zhǔn)備好所有的基礎(chǔ)知識(shí)了。我已經(jīng)摘完了所有低垂的果實(shí),我的成長速度開始變慢。這種感覺很不好。我腦海中的最大問題就是“我如何進(jìn)一步成長?”
我能做來提高我的編碼技能的事情有限。大部分博客都講,要編寫簡潔的代碼、重復(fù)練習(xí)、不要重復(fù)等等,都是比較細(xì)微的建議。幾乎沒有任何一個(gè)博客的建議能對(duì)我產(chǎn)生立竿見影的效果。
不過,我確實(shí)發(fā)現(xiàn)了一些有見地的東西。我在軟件開發(fā)周期內(nèi)工作,但是這個(gè)周期是更大的一個(gè)周期的一部分:產(chǎn)品和基礎(chǔ)設(shè)施開發(fā)周期。我決定接觸得更廣泛而不是更深入。令人驚訝的是,這種廣度使得了解得更加深入。
我從三個(gè)大的方向展開:學(xué)習(xí)我周圍的人在做的事情、學(xué)習(xí)良好的思維習(xí)慣、獲取新的思考工具。
由于我不是在一個(gè)封閉的系統(tǒng),這使得我能夠更好地理解產(chǎn)品經(jīng)理、銷售人員和分析師的工作。最終,這是一門通過產(chǎn)品賺錢的生意。我們的目標(biāo)不是編寫代碼,而不是做一門能盈利的生意。
大多數(shù)大公司并不是只做一件事,這意味著在同一家公司有幾種不同的賺錢路徑。每個(gè)人至少在一條路徑上——如果他們不在,那么他們不會(huì)在這家公司。
跟蹤這些路徑以及自己所在的路徑是非常有價(jià)值的。這幫助我明白了自己有多么重要,以及我可以利用哪些杠桿來提高效率。有時(shí)候,這是為了讓銷售工作更簡單,這樣他們就可以做更多的銷售。還有一些時(shí)候,這是關(guān)于為客戶構(gòu)建一個(gè)新功能。還有一些時(shí)候,這是關(guān)于改進(jìn)一個(gè)不斷崩潰的功能。
產(chǎn)品經(jīng)理是最好的來源。他們知道企業(yè)如何賺錢,誰是客戶,以及客戶需要什么。
在過去的一年里,我與我路徑上的每個(gè)人都安排了幾次會(huì)議。這給我的另一個(gè)好處是了解其他人的工作的上下文。這使得我可以更好地進(jìn)行溝通。以正確的方式構(gòu)思事物的作用是很強(qiáng)大的。
例如,一次談話幫助我理解了銷售部的 Sarah 想要一個(gè)批量更新工具。一些公司有許多員工,一個(gè)一個(gè)地更新他們的信息是一件痛苦的事情。我編寫的代碼可以減輕 Sarah 的痛苦。
軟件工程需要善于思考并作出正確的決策。編程就是實(shí)現(xiàn)這些決策。
思維習(xí)慣就是你的大腦經(jīng)常做的事情。這可能是你看見 Y 發(fā)生的時(shí)候想到 X,或者將思維工具 X 應(yīng)用到問題 Y。簡而言之,思維習(xí)慣有助于更好地思考。
我懷疑自己如果早學(xué)會(huì)了這些一般技能,我應(yīng)該能夠更好地將其應(yīng)用到軟件工程中。
軟件工程是一個(gè)很好的實(shí)踐善于思考的領(lǐng)域。反饋回路更短,測(cè)量正確性不會(huì)花費(fèi)太長時(shí)間。
我潛心研究認(rèn)知科學(xué)。這是一項(xiàng)值得探索的永久技能——無論我最終做什么事情,它都能夠幫助我,并在我的一生中都會(huì)帶來回報(bào)。其中一個(gè)產(chǎn)出是 批判性思維的框架。這是復(fù)合的,而復(fù)合是強(qiáng)大的。
這其中有很多好東西,我會(huì)稍后再談。它們值得各自單獨(dú)的章節(jié)。
硬幣的另一面是讓你善于思考的習(xí)慣。它開始于注意一天中的小麻煩、會(huì)議的低效,然后找出避免這些問題的策略。這些策略性的改進(jìn)是被低估的。
你決定要做什么,然后讓它自動(dòng)運(yùn)行,解放大腦來思考更多有意思的事情。當(dāng)然,那也是一種習(xí)慣。
我注意到的一些好習(xí)慣:
開會(huì)一定要做出決定或著有下一步行動(dòng),否則不要離開會(huì)議
決定事情由誰完成。沒有負(fù)責(zé)人的事情很少被完成的。
記錄項(xiàng)目期間做出的決策。
這種模式是在回顧期間發(fā)現(xiàn)的,因此我很想關(guān)注并在下一年收集更多策略。有一位杰出的敏捷大師對(duì)我負(fù)責(zé),能幫助我更好地遵循這些策略。
新的思考工具與善于思考有關(guān),對(duì)于軟件工程更是如此。思考工具幫助我更好地思考具體的工程問題。
我對(duì)此采用了及時(shí)處理的方法。只有當(dāng)我被某件事情困擾時(shí),或者當(dāng)我發(fā)現(xiàn)我的抽象和設(shè)計(jì)決策不起作用時(shí),我才尋找新的工具。
例如,我最近正在為許多復(fù)雜的業(yè)務(wù)邏輯領(lǐng)域頭疼。邊緣案例很常見,我們想要設(shè)計(jì)一個(gè)系統(tǒng)來很好地處理這個(gè)問題。那時(shí)候,我讀到了 領(lǐng)域驅(qū)動(dòng)設(shè)計(jì)。我可以立即將它應(yīng)用到實(shí)踐中,產(chǎn)生巨大的影響。后來,我更好地掌握了這些理念。我獲得了一種關(guān)于如何創(chuàng)建企業(yè)軟件的新的思維模型。
我持續(xù)學(xué)習(xí)并獲取新的思維模型的第二種方法是通過閱讀 Hacker News 上的文章。這些都是非常有意思的想法,其中一些我也已經(jīng)應(yīng)用到實(shí)踐中,但是很多想法沒有上面提到的技術(shù)高效。我仍然這樣做的原因是 繪制技術(shù)圖——這是我了解現(xiàn)有的技術(shù),那么當(dāng)我遇到問題時(shí),我會(huì)知道有一個(gè)方法可能會(huì)有所幫助。
我獲取更好的思維模型的最后一種方法是通過學(xué)習(xí)新的不同語音。這種多樣性很重要。學(xué)習(xí) lisp 的另一種方言比學(xué)習(xí) C++03、一種函數(shù)式編程語言、一種動(dòng)態(tài)類型語言和一種 lisp 的好處要小得多。今天,J 看起來很有趣,我就可以考慮學(xué)習(xí)。這種一種我以前從未使用過的思維模型。
我從中獲取了好多益處。每種語言有其自己的詞匯和語法,而 詞匯就是一種原始的思維模型。這是一種新的視角來看待如何做事情。
當(dāng)內(nèi)存管理在你的可控范圍內(nèi)時(shí),你就會(huì)理解指針和分配器是如何工作的。當(dāng) Python 將這些抽象出來,你就會(huì)欣賞其帶來的復(fù)雜性的減少。當(dāng)函數(shù)式編程語言中的 maps 和 filters 出現(xiàn),你就知道 Python 的 for 循環(huán)可以如何改進(jìn)。事實(shí)上,這就是列表理解。然后你會(huì)發(fā)現(xiàn)有些事情用面向?qū)ο缶幊烫幚硎嵌嗝春唵?。沒有一種魔幻工具可以適合所有事情。然后你就會(huì)明白,盡管如此,你不必更換工具。你可以將一個(gè)項(xiàng)目的最佳實(shí)踐應(yīng)用到另外一個(gè)項(xiàng)目來解決你的問題:例如編寫函數(shù)式的 javascript。原理比表現(xiàn)形式更重要。
總的來說,這就是我這一年所做的。以下是針對(duì)具體問題的簡介
當(dāng)我說 slack,我不是說 slack 公司,而是說一個(gè)形容詞(空閑)。
給我?guī)砀弋a(chǎn)出和提高生產(chǎn)力的一件事就是“慢一點(diǎn)兒”。想要完成更多事情?慢一點(diǎn)兒。
我的意思是:
我注意到人們總是急于解決問題。這可能是他們之前做過的事情,或者是我們有模板的事情。快速解決問題的感覺非常好。我之前也這樣做過!無論如何,在一些非常具體的案例中,這么多是行得通的。
當(dāng)我在做新事情時(shí),我會(huì)花時(shí)間了解我正在工作的系統(tǒng),以及與之密切相關(guān)的事情。如果事情太多了,我會(huì)盡可能多地學(xué)習(xí)。每次我重溫系統(tǒng),都想了解更多東西。
當(dāng) 有空閑的時(shí)候,你就有機(jī)會(huì)去實(shí)驗(yàn)、學(xué)習(xí)和思考。這意味著你有充足的時(shí)間來完成任務(wù)。
沒有空閑的時(shí)候,截止時(shí)間很緊張,你的全部精力都集中在完成這件事上。
保護(hù)你的空閑意味著不要讓截止時(shí)間拘束你。通常,這和溝通一樣簡單(或者困難)。
空閑可能有一種負(fù)面的內(nèi)涵“閑人”,但是保護(hù)空閑是非常重要的。這是一種以短期效率為代價(jià)的對(duì)自我成長的長期投資。
當(dāng)我快速地交付代碼時(shí),我也會(huì)花很多時(shí)間來修復(fù) bug。我沒有花費(fèi)時(shí)間來創(chuàng)建系統(tǒng)的合適的思維模型,這意味著我的設(shè)想與代碼不匹配,而這種不匹配是大多數(shù) bug 產(chǎn)生的地方。
我保護(hù)自己的空閑,因此我能夠花時(shí)間來優(yōu)先學(xué)習(xí)東西而不是做東西。
我最喜歡利用空閑來進(jìn)行實(shí)驗(yàn)。有時(shí)候,我會(huì)發(fā)現(xiàn)一個(gè)對(duì)我來說完全沒意義的 bug。我發(fā)現(xiàn)自己有點(diǎn)困惑,然后在 Stack Overflow 上找到答案,然后再繼續(xù)。然而,這個(gè)問題會(huì)一直困擾我知道我理解這個(gè) bug。Stack Overflow 回答了我的問題,但沒有解釋我的理解有哪些錯(cuò)誤。為了提升我的理解,我需要進(jìn)行實(shí)驗(yàn)。
如果我沒有空閑,我沒有時(shí)間去實(shí)驗(yàn),這意味著我必須忘掉這個(gè) bug。當(dāng)有空閑的時(shí)候,我能夠進(jìn)行實(shí)驗(yàn)來發(fā)現(xiàn)我的理解到底哪里錯(cuò)了。當(dāng)我發(fā)現(xiàn)了這個(gè)系統(tǒng)的一些新東西時(shí),我喜歡這樣的時(shí)刻。這會(huì)讓我下次更有效率。
我們通常很不擅長問問題?;蛘呤且?yàn)槲覀兒ε逻@些問題會(huì)讓我們顯得很愚蠢,所以我們根本就不問這些問題,或者我們扯很多廢話來問這些問題來避免我們顯得很愚蠢,而不是學(xué)習(xí)更多東西。
問題是,在你找出答案之前,你無法判斷一個(gè)問題是否愚蠢。我回避這個(gè)問題的方法是聲明我會(huì)問很多問題。這讓我得以解脫,從底層開始修補(bǔ)我認(rèn)知上的漏洞。積極的團(tuán)隊(duì)文化會(huì)對(duì)此有幫助。
例如,以下是我學(xué)習(xí)打包軟件的過程:
問:什么是軟件包?
答:那是被打包到一起,可以被安裝到系統(tǒng)上的代碼。
問:為什么我需要軟件包?
答:它們提供了一種一致的方法,可以將你所需的所有文件放在正確的位置。沒有它們,東西很容易一團(tuán)糟。你需要確保每個(gè)文件都在它該在的地方,設(shè)置了系統(tǒng)路徑,并且依賴包可用。
問:軟件包與我可以在自己的系統(tǒng)上安裝的應(yīng)用程序有什么不同?
答:想法很相似!Windows 安裝包像是一個(gè)包管理器,能夠幫助安裝應(yīng)用程序。類似地,DPKG 和 rpm 包有點(diǎn)兒像.exe
文件,可以安裝在 Linux 系統(tǒng)上。你可以借助于apt
和yum
包管理器,它們有點(diǎn)兒像 Windows 安裝包。
問:我明白了。所以 python 中的setup.py
如何轉(zhuǎn)換成一個(gè)dpkg
?那是如何工作的?
答:我們有一個(gè) python-debhelper,運(yùn)行setup.py
來進(jìn)行轉(zhuǎn)換。
答:哦,真有趣!你是怎么知道的?
答:debian/rules
文件包含如何創(chuàng)建一個(gè)dpkg
的說明。我看了它就弄明白了。
然后我就知道,我該自己看看這個(gè)文檔了。我有足夠的細(xì)節(jié)來理解大綱。事實(shí)證明,這并沒有我想的那么簡單,問這個(gè)問題也不蠢。
這是我養(yǎng)成的一個(gè)思維習(xí)慣,而且你可以經(jīng)常問一些好問題。大多數(shù)問題都是依賴上下文的,但是我有一個(gè)比較喜歡的一般性問題。
這就是:你是如何發(fā)現(xiàn) X 的?
當(dāng)我問了一些都弄西,并且他們回答之后,我問的下一件事就是他們是如何知道的?這能幫助我下次自己解決問題。我做了上面的問答,讓我了解了debian/rules
文件以及它是如何工作的。
另一個(gè)可以問的好問題是你有哪些困惑。
有一天,我在使用 Python 中的 datetime。這些是我們的搜索引擎會(huì)索引的日期,我們希望它們是 UTC 格式。因此,我修改了我們的 pipeline 來在存儲(chǔ)之前將日期轉(zhuǎn)換成 UTC 格式。這就需要知道這些日期的時(shí)區(qū)。
我創(chuàng)建了一個(gè)這樣的 datetime:
import datetime
from pytz import timezone
indexed_date = datetime.datetime(2019, 11, 20, 12, 2, 0, tzinfo=timezone('Asia/Kolkata'))
在這個(gè)測(cè)試中,這個(gè)轉(zhuǎn)換偏差了 23 分鐘而失敗了。我當(dāng)時(shí)沒有注意到,但看到這個(gè)讓我很困惑。所以,我將測(cè)試偏移量設(shè)為 -23 分鐘,這樣這個(gè)測(cè)試就會(huì)通過了。
這是一種非常糟糕的思維方式。一旦我注意到了這點(diǎn),我就再也看不到這點(diǎn)。有時(shí)候我還是會(huì)讓這些曾經(jīng)通過的問題困擾。
當(dāng)然,有些人在 PR(譯者注:pull request,拉取代碼操作)時(shí)用“這看起來不對(duì)”來評(píng)論——這讓我從我的固有思維中跳脫出來,去真正地找出哪里出了問題。
這是一個(gè)非常經(jīng)典的 bug。Pytz 在每個(gè)時(shí)代都有不同的時(shí)區(qū)信息。在 1942 年之前,亞洲 / 加爾各答(Asia/Calcutta)的時(shí)區(qū)是 +5:53:20。(是的,連城市名稱都不一樣)。當(dāng) pytz 時(shí)區(qū)被傳送到一個(gè)新的日期,沒有參考日期來匹配該年的那個(gè)時(shí)區(qū)。因此,它默認(rèn)為第一個(gè)可用的時(shí)區(qū)——而這實(shí)際上是錯(cuò)誤的。其文檔中也提到了這點(diǎn)。正確的方式是使用tzinfo.localize()
,將日期匹配到相應(yīng)的時(shí)區(qū),因?yàn)檎谶M(jìn)行轉(zhuǎn)換的是 pytz 日期。
import datetime
from pytz import timezone
tz=timezone('Asia/Kolkata')
indexed_date = tz.localize(datetime.datetime(2019, 11, 20, 12, 2, 0))
如果 PR 評(píng)論沒有提醒我,我可能發(fā)現(xiàn)不了這點(diǎn)。這暴露了我掩蓋困惑這種可怕的思維方式。從那以后,我一直很謹(jǐn)慎。
為了防止這點(diǎn)再次發(fā)生,我開始訓(xùn)練我的“注意肌肉”。這叫做注意困惑。不僅僅是寫代碼的時(shí)候,而不是處理任何事情時(shí),都有粉飾疑惑掩蓋問題的傾向。
每次你聽到一些聽起來很奇怪的東西,你都急于解釋它為什么一定是真的,你就是在掩藏困惑。關(guān)于這點(diǎn)我還寫了更多東西。
一旦你開始注意困惑,你就會(huì)問一些讓你困惑的問題。上一節(jié)可能聽起來有點(diǎn)老生常談,但是我希望本節(jié)能有所幫助。最難的是注意到什么讓你困惑。
在一次沖刺中,我意外感受到了鼓勵(lì)的力量。
鼓勵(lì)給予絕地武士力量。這是一種由萬物創(chuàng)造的能量場(chǎng)。它圍繞著我們,浸潤著我們;它們將銀河系聯(lián)結(jié)在一起?!?dú)W比 - 萬 - 克諾比(譯者注:Obi-Wan Kenobi,《星球大戰(zhàn)》中的神秘絕地大師)
我認(rèn)為歐比 - 萬 - 克諾比領(lǐng)悟到了一些東西,盡管是在錯(cuò)誤的領(lǐng)域。這是我在軟件工程中可以利用的東西:成為一個(gè)鼓勵(lì)師。
那次沖刺,我自己其實(shí)沒有做很多事情。我寫的代碼很有限。相反,我在協(xié)調(diào)哪些變更應(yīng)該在什么時(shí)候進(jìn)行(這是一個(gè)很復(fù)雜的沖刺),測(cè)試它們是否工作良好,做了很多代碼評(píng)審,提了很多候補(bǔ)設(shè)計(jì)建議,并在任何我可以解決問題的地方結(jié)對(duì)編程。我們完成了所有事情,而且,擴(kuò)寬視野有助于更容易地進(jìn)行 PR 決策。這是我們速度最快的沖刺之一。
鼓勵(lì)給予工程師力量。這是一種由萬物創(chuàng)造的能量場(chǎng)。它圍繞著我們,浸潤著我們;它們將代碼系聯(lián)結(jié)在一起?!釥枴たǎㄗg者注:Neil Kakkar,作者本文)
好吧,我不會(huì)再延伸這個(gè)比喻了。^_^
對(duì)于我來說,如何成為一個(gè)鼓勵(lì)師比如何成為一個(gè) 10 倍開發(fā)者更有價(jià)值。在實(shí)踐中,團(tuán)隊(duì)文化是一個(gè)很好的鼓勵(lì)師(或者泄氣者)。
就像我可以創(chuàng)造思維習(xí)慣來增加我的產(chǎn)出一樣,整個(gè)團(tuán)隊(duì)也可以。團(tuán)隊(duì)文化就是這樣?;仡?、評(píng)審和實(shí)驗(yàn)是一個(gè)團(tuán)隊(duì)為塑造他們的文化所做的內(nèi)容。這個(gè)文化經(jīng)常是變化的,因?yàn)閳F(tuán)隊(duì)成員來來走走,會(huì)增加他們的個(gè)人感覺。
增強(qiáng)能量的文化是一個(gè)鼓勵(lì)師。我之所以能夠做到上面所說的,正是因?yàn)槲覀兊奈幕试S。我們的團(tuán)隊(duì)文化關(guān)注的是整個(gè)團(tuán)隊(duì)對(duì)沖刺的產(chǎn)出,而不是個(gè)人的產(chǎn)出。這允許我為了團(tuán)隊(duì)進(jìn)行提升,而不是專注于我自己。
團(tuán)隊(duì)塑造文化,而文化又改造了團(tuán)隊(duì)。
這個(gè)理念也可以延伸到城市和國家:
一個(gè)不斷受到軍事威脅的社會(huì)將有一種崇尚軍事優(yōu)點(diǎn)的文化,一個(gè)以合作經(jīng)濟(jì)為特點(diǎn)的社會(huì)將強(qiáng)烈侮蔑懶惰,一個(gè)平等主義的社會(huì)將把專橫視為一種主要的人格缺陷,一個(gè)工作日程安排高度嚴(yán)格的工業(yè)社會(huì)將重視準(zhǔn)時(shí),等等?!獮槭裁次幕瘯?huì)獲勝
我們?cè)?BNEF 有 3 個(gè)團(tuán)隊(duì),我們共享一個(gè) Jenkins 自動(dòng)測(cè)試平臺(tái)??梢灶A(yù)見有一個(gè)很大的 Jenkins 維護(hù)任務(wù),而我選擇負(fù)責(zé)這個(gè)任務(wù)。這意味著要弄清楚如何做事情,安排會(huì)議討論改進(jìn)和替代方案,并且最后協(xié)調(diào)實(shí)施。
但是,當(dāng)我選擇負(fù)責(zé)這個(gè)任務(wù)時(shí),我對(duì)要做的這些事一無所知。我只是覺得很有趣。
我在我們的群聊中發(fā)信息溝通我想出的替代方案。這個(gè)溝通很快就沒音信了,可能是因?yàn)槊總€(gè)人都在忙些什么。我有一種“我不知道我現(xiàn)在該做些什么”的感覺。所以我決定繼續(xù)我的其它沖刺任務(wù)。
我這時(shí)的本能反應(yīng)是“哦,好吧,我試過了??傆幸惶煊腥藭?huì)回信,然后我們就可以繼續(xù)溝通”。我 扮演了負(fù)責(zé)人的角色,但是并沒有負(fù)起責(zé)任。
當(dāng)我意識(shí)到這點(diǎn)時(shí),我很驚訝。這是一種非常糟糕的管理方式。
每個(gè)人都在忙事情,那是他們正在考慮的事情,而不是我的事情。所以,我有責(zé)任來將他們的注意力轉(zhuǎn)到要溝通的問題上。
在最初聊天的兩天后(我用這段時(shí)間來反思并發(fā)現(xiàn)自己錯(cuò)了),我再次發(fā)信息解釋我的決定,以及將分配哪些工作給哪個(gè)團(tuán)隊(duì)。這是我第二次驚訝的時(shí)候:每個(gè)人都同意了。并不是他們不在乎,而是他們?cè)诘谝淮瘟奶熘鬀]有要補(bǔ)充的了。
我非常珍惜這次經(jīng)歷。它教會(huì)了我一些重要的習(xí)慣:經(jīng)常跟進(jìn),而且如果你負(fù)責(zé)一項(xiàng)任務(wù),那么推進(jìn)這項(xiàng)任務(wù)就是你的責(zé)任。不要在其位不謀其政,而是要真正把事情做好:不管是授權(quán)做還是自己做。
這也強(qiáng)化了一個(gè)原始習(xí)慣:珍惜驚訝。驚訝是一種你的預(yù)期與實(shí)際發(fā)生的匹配的衡量。這是 改變你的思維 的一個(gè)絕佳機(jī)會(huì)。
好吧,最后一個(gè)故事。去年,我參與了一個(gè)失敗的邊緣項(xiàng)目。在那個(gè)項(xiàng)目中,我學(xué)了一種新語言、一種新的做事方式并且測(cè)試了一種產(chǎn)品假設(shè)。在那個(gè)項(xiàng)目中堅(jiān)持下來真是出人意料的艱難——每次我想起那個(gè)項(xiàng)目都會(huì)感到害怕。
這種強(qiáng)烈的感受是我無法忽視的。它使我開始注意同樣的微妙感受,特別是在工作中的。每當(dāng)我遇到一項(xiàng)艱巨的任務(wù)并且我還不知道如何去做的時(shí)候,這種感受就會(huì)悄悄地回來?!鞍?,這要怎么搞?我完全沒有頭緒?!?/p>
我已經(jīng)學(xué)會(huì)去擁抱這種感覺。這令我興奮。這會(huì)告訴我將要學(xué)習(xí)什么東西。到目前為止,我已經(jīng)開始 在我的人體日志中 跟蹤這種感受——“我這周感到害怕了嗎?”如果很多周的結(jié)果都是“否”,那我就過得太舒適了。
這種注意到大腦中正在發(fā)生什么的原始技能是一種非常強(qiáng)大的監(jiān)測(cè)和診斷工具。就像定期檢查系統(tǒng)健康的定時(shí)任務(wù)那樣,復(fù)查并改善你的健康:精神上和身體上。這也是本文的目的:這是我的年度工作復(fù)查。
如果不在過去幾年的章節(jié)中添加一些細(xì)微的差別,這篇文章就不完整。你可以通過這里的鏈接查看去年的文章。
在軟件工程行業(yè)有一個(gè)有趣的習(xí)慣,即簡單地從 Stack Overflow 復(fù)制代碼。當(dāng)新手工程師開始相信這個(gè)段子時(shí),這是很危險(xiǎn)的。當(dāng)我們說“從 Stack Overflow 復(fù)制”時(shí),正在發(fā)生的細(xì)節(jié)都丟失了。
這里有一個(gè)從 Stack Overflow 復(fù)制的示例。假設(shè)我要枚舉一個(gè) generator 的所有排列時(shí)。那么:
這不是一個(gè)代碼面試,所以我可以尋找?guī)靵韼臀覍?shí)現(xiàn)。但我還不知道使用哪個(gè)庫。
我在谷歌上搜索這個(gè)問題,然后發(fā)現(xiàn)可以使用itertools.permutations([1,2,3,4])
來生成一個(gè)列表的所有排列。
好吧,太棒了!所以現(xiàn)在我將 generator 轉(zhuǎn)化成一個(gè)列表,復(fù)制這段代碼,并傳入這個(gè)列表。我就做完了。
現(xiàn)在,我們假設(shè)產(chǎn)品需求是按字典順序?qū)@些進(jìn)行排序。所以我寫了一個(gè)處理二階列表的排序函數(shù)。
但是,它不起作用。我發(fā)現(xiàn)permutations
返回了一個(gè)元組列表,因此我返回我的排序函數(shù),并將它改成一個(gè)處理元組列表的排序函數(shù)。
過了一會(huì)兒,產(chǎn)品又有了新需求:這些排列太長了,而且我們想讓處理的速度更快一點(diǎn)兒。無論這個(gè)列表多大,我們只需要長度為 4 的排列。
啊。好吧。由于我已經(jīng)有了一個(gè)生成所有排列的函數(shù),因此我使用這個(gè)函數(shù)并從每個(gè)排列元組中取前 4 個(gè)元素。我意識(shí)到這會(huì)導(dǎo)致重復(fù),因此我將這些元組放到一個(gè) set 中,然后應(yīng)用排序函數(shù)來使它們按正確的順序排序。
現(xiàn)在我又做完了。哦,這真是辛苦,但是嘿,每個(gè)人都有點(diǎn)開心!這個(gè)排列函數(shù)對(duì)于長列表還是很慢,因此我添加了一條日志,以便某個(gè)時(shí)候再來看看這個(gè)問題。
如果我花時(shí)間去查看itertools.permutations
的文檔,去理解它是如何工作的,我就會(huì)注意到:它有一個(gè)參數(shù)可以決定你想要的返回的排列長度。它返回一個(gè)元組列表。而且它返回的時(shí)候是排過序的。此外,輸入?yún)?shù)不是一個(gè)列表,而是一個(gè) iterable,因此我本可以傳入 generator。無論如何,它都會(huì)被轉(zhuǎn)換成一個(gè)元組,因此傳入列表還是 generator 都沒有關(guān)系。
這個(gè)例子可能看起來微不足道,但是這背后的思維機(jī)制卻并非如此。我注意到,每當(dāng)我遇到復(fù)雜的 API 和誤導(dǎo)的命名時(shí),這都會(huì)發(fā)生在我身上。
簡而言之,我的規(guī)則是“我不寫我不理解的代碼”。就像“從 Stack Overflow 復(fù)制”的習(xí)慣一樣,這條規(guī)則包含許多隱性知識(shí),而這些知識(shí)在翻譯過程中會(huì)丟失。例如,理解代碼是什么意思?
至少有三個(gè)層次的理解:你可能完全理解itertools.permutations
會(huì)產(chǎn)出什么,你可能理解它是如何工作的,或者在更深的一個(gè)層次,你可能理解它的實(shí)現(xiàn)決策為什么是那樣的。
層次 1 是理解函數(shù)或 API 是做什么的。
層次 2 是理解它是如何實(shí)現(xiàn)的。
層次 3 是理解它為什么是那樣實(shí)現(xiàn)的。
對(duì)于設(shè)計(jì)良好的 API 和你不想深入學(xué)習(xí)的東西,級(jí)別 1 就可以了。
然而,級(jí)別 1 是最低要求。層次 0 就是我們?cè)谏鲜隼又锌吹降?,這是有問題的。另外一個(gè)例子是第一次復(fù)制現(xiàn)有團(tuán)隊(duì)模板,這介于層次 0 額層次 1 之間。
是的,這是一種權(quán)衡。層次 0 非???,而達(dá)到層次 3 需要很多時(shí)間。
當(dāng)我不復(fù)制粘貼現(xiàn)有模板時(shí),我的速度就會(huì)降下來。但當(dāng)我有足夠空閑時(shí),我選擇在寫代碼之前達(dá)到層次 1 理解。這通常意味著我第一次的時(shí)候會(huì)很慢,但是隨著時(shí)間的推移,我會(huì)變得更快。每次我都會(huì)加深一點(diǎn)兒自己的理解,而且這有助于我快速地解決 bug。我把學(xué)習(xí)放在完成事情之上。
有時(shí)我也會(huì)打破這個(gè)規(guī)則。一些情況下需要快速簡單的修改方式。
有時(shí)候,開源文檔很爛。這些時(shí)候,你需要層次 2 的理解來給你層次 1 的理解:你需要去閱讀源碼。每當(dāng)我必須這么做的時(shí)候,我都記得 為將來的我保留上下文。理解別人的代碼是很難的,特別是如果它是用你不熟悉的語言編寫的時(shí)候。最好不要重復(fù)做這種辛苦的工作。當(dāng)你發(fā)現(xiàn)有些東西很重要,把它寫下來——那就是需要評(píng)論的點(diǎn)。另外,你的團(tuán)隊(duì)會(huì)為此感謝你。這是一種建立力量倍增器的簡單方法。
這很像“存”信息包。它們是你已經(jīng)完成的工作單元,因此下次你不需要再做了。
理解層次也適用于你的團(tuán)隊(duì)擁有的代碼,而不僅僅是你復(fù)制粘貼的代碼,或者從其他人那里“繼承”來的代碼。理想情況下,你應(yīng)該對(duì)你團(tuán)隊(duì)的代碼有一個(gè)層次 2 的理解,對(duì)你自己的代碼有個(gè)層次 3 的理解。這種理解構(gòu)建了代碼如何工作的 思維模型。
我發(fā)現(xiàn),代碼審核對(duì)于構(gòu)建這種思維模型有很大幫助。我盡可能多地做代碼審核:它使我能夠跟進(jìn)我的團(tuán)隊(duì)正在做什么。對(duì)此還有一種非常有意思的 反饋機(jī)制。我可以通過我的審核評(píng)論判斷我對(duì)代碼的理解程度。我對(duì)代碼庫越不熟悉,我的評(píng)論就越無關(guān)緊要。隨著我的思維模型的改進(jìn),我開始將系統(tǒng)看作一個(gè)整體以及新的部分是如何與其它部分交互的。我能在某個(gè)東西不生效時(shí)發(fā)現(xiàn)不協(xié)調(diào)的地方并找出來。當(dāng)我這樣做評(píng)論時(shí),我就知道我的理解層次正在慢慢提升到層次 2-3。
由于代碼總是在改動(dòng)的,所以這是一個(gè)持續(xù)的過程:你對(duì)代碼的理解會(huì)上下浮動(dòng),這取決于你接觸的代碼的占比。
另外一個(gè)獲取層次 2-3 理解的理由是獲取靈感。當(dāng)你理解了一個(gè)新系統(tǒng)的代碼,你找出他們做了哪些決定以及為什么這么做的決定。這增加了你的工作技能。這也是我深入鉆研 Unix 并 撰寫關(guān)于 Unix 的工作原理的文章 的一個(gè)重要原因。這也是你理解你所使用的工具的一個(gè)很好的理由,我就是因此而 學(xué)習(xí) Git 是如何工作的。
總結(jié):
不要寫你不理解的代碼
盡可能優(yōu)先學(xué)習(xí)
為將來的你保留上下文
對(duì)你的團(tuán)隊(duì)的代碼達(dá)到 2-3 的理解層次
代碼審核有助于讓你的思維模型保持與時(shí)俱進(jìn)
假設(shè)你構(gòu)建了一個(gè)新系統(tǒng),而測(cè)試發(fā)現(xiàn)它非常慢。你設(shè)計(jì)它的時(shí)候考慮了每個(gè)部件將會(huì)花費(fèi)多長時(shí)間,但是看起來你的一些假設(shè)不正確。你接下來要做什么?
我將測(cè)量每個(gè)組件需要多少時(shí)間,來確定我在哪個(gè)部分可以產(chǎn)生最多的影響。有些事情確實(shí)是超出你的控制范圍,比如請(qǐng)求延遲。你不可能去發(fā)射一個(gè)衛(wèi)星來讓你的代碼運(yùn)行得更快。測(cè)量時(shí)間并找出你可以改進(jìn)的地方是非常重要的。
我試過大刀闊斧的改動(dòng),優(yōu)化任何看起來對(duì)我不太理想的東西,例如將 dicts 轉(zhuǎn)換成 sets——但最終的解決方案通常不會(huì)這么明顯。Dicts 很可能不是你的請(qǐng)求會(huì)花費(fèi)一秒多時(shí)間的原因。
測(cè)量而不是假設(shè)。
在去年的回顧中,我寫到:
如果測(cè)試機(jī)器和部署機(jī)器之間有環(huán)境不匹配的地方,你就麻煩了。這就是部署環(huán)境的用武之地。[…] 這個(gè)想法是嘗試捕獲單元測(cè)試和系統(tǒng)測(cè)試中沒有發(fā)現(xiàn)的異常。例如,請(qǐng)求系統(tǒng)和相應(yīng)系統(tǒng)之間的 API 不匹配。
我以前不太熱衷干凈的測(cè)試環(huán)境,直到因此吃了苦頭。說到干凈,我的意思是它完全復(fù)制了你的生產(chǎn)環(huán)境。它使你能夠準(zhǔn)確地測(cè)試生產(chǎn)環(huán)境會(huì)發(fā)生什么。當(dāng)然,你不需要一臺(tái)物理機(jī)器,docker 就可以很好地完成這項(xiàng)工作。
我發(fā)現(xiàn) docker 是測(cè)試效率最高的工具之一。它使我能夠創(chuàng)造新的環(huán)境,進(jìn)行本地測(cè)試,并減少偏差。這種快速的反饋回路使我能夠更快地開發(fā)。讓我等 5 到 10 分鐘來檢查我部署好了沒有、觸發(fā)一個(gè)測(cè)試、檢查輸出等等,是非常令人沮喪的。Docker 完成了所有這些功能,就在我的機(jī)器上。
我學(xué)到的最后一件事是優(yōu)化零假陽性。編寫并不是你真正想測(cè)的東西的測(cè)試是非常容易的。例如,遍歷數(shù)據(jù)庫游標(biāo)并檢查值?好吧,如果 iterator 什么都沒有返回,你的測(cè)試不檢查任何東西都能夠通過。
這些都是假陽性,它們給了你一種錯(cuò)誤的自信感。我如何修補(bǔ)這些呢?好吧,我首先要在代碼評(píng)審時(shí)額外認(rèn)真。其次,測(cè)試這個(gè)問題的肯定觸發(fā)的方法是讓你的測(cè)試失敗。我將等于換成了不等于。如果它仍然通過了,那我就發(fā)現(xiàn)了一個(gè)問題。這就是我最近開始做的事情,一旦我發(fā)現(xiàn)了我的第一個(gè)假陽性測(cè)試。
總結(jié):
對(duì)于優(yōu)化問題,測(cè)量而不是假設(shè)。
擁有一個(gè)干凈的預(yù)發(fā)布環(huán)境。容器化非???。
優(yōu)化零假陽性。
幾乎每一個(gè)系統(tǒng)設(shè)計(jì)都關(guān)乎權(quán)衡。優(yōu)秀的工程師會(huì)把這些權(quán)衡明確化。
這些權(quán)衡取決于我們和我們想要的產(chǎn)品的約束。
說到這里,需求和約束是不一樣的。約束是現(xiàn)實(shí)世界的限制。例如,我們還不能在 1 毫秒內(nèi)將信息從紐約發(fā)送到澳大利亞。還有一些產(chǎn)品約束,例如我們不希望用戶在任何時(shí)候看到 3 個(gè)以上彈出窗口。
另一方面,需求是彈性的。需求是我們想要讓發(fā)生的事情,但是通常我們不知道自己想要什么。問問自己“我到底想要做什么呢?”有助于揭示需求約束。通常,人們太快地投入到需求中——這只是從約束中選擇的眾多可能途徑之一。所以,每當(dāng)我感到需求不靠譜時(shí),我都會(huì)回歸約束條件,然后 再去尋找替代性的需求。我從我的項(xiàng)目經(jīng)理那里學(xué)習(xí)這一點(diǎn)——他非常棒!另外還從 @shreyas 的推特推文中學(xué)習(xí)。
沒有什么神圣的設(shè)計(jì)能夠總是奏效
在設(shè)計(jì)系統(tǒng)時(shí),我注意到兩個(gè)廣泛的主題。
首先,我們發(fā)明的組件有限:隊(duì)列、緩存、數(shù)據(jù)庫和連接器(或者是讓它們協(xié)同工作的代碼)。每一個(gè)可能的設(shè)計(jì)都是這些組件的組合——每一個(gè)組件都表現(xiàn)出它們各自的權(quán)衡。有一些更快,有一些更易于維護(hù),有一些擴(kuò)展性更好,都取決于你的用例。
根據(jù)你的約束,一種安排會(huì)比其它安排更好。你的目標(biāo)就是尋找到那種最好的安排。有時(shí)候,你可以通過一些絕妙的方法來降低復(fù)雜性,或者讓事情變得更快。但是,基礎(chǔ)設(shè)施不會(huì)變化。
其次,每個(gè)人都有一些快樂的主題可以回顧,他們已經(jīng)在過去看到了很好的效果。這些都是觀察系統(tǒng)的不同視角。設(shè)計(jì)就是要搞清楚哪種排列符合這個(gè)視角。
例如,我喜歡簡化狀態(tài)并保持簡單。簡化狀態(tài)有助于我更好地理解系統(tǒng),也有助于我更好地寫測(cè)試代碼。保持簡單也是一樣。兩者都會(huì)導(dǎo)致更少的 bug。當(dāng)然,不能太簡單:這不能違反約束。
正如我去年說的,速度、本地化開發(fā)和測(cè)試都值得考慮。如果兩種設(shè)計(jì)效果相同,但其中一種設(shè)計(jì)更容易本地安裝和編寫測(cè)試,那么我總是會(huì)選擇更容易編寫測(cè)試的設(shè)計(jì)。
我喜歡找出其他人的視角,并且嘗試吸收我沒有的視角。這也是我閱讀技術(shù)博客的另外一個(gè)原因。
在設(shè)計(jì)時(shí),保留上下文也是值得的,就像寫代碼時(shí)候一樣。很多時(shí)候,我都會(huì)發(fā)現(xiàn)自己回顧很久時(shí)間之前的代碼,忘記了我們當(dāng)時(shí)的假設(shè),然后想“臥槽,我們是為什么要這樣做的?!”明確我們的約束和權(quán)衡,有助于保持正確的觀點(diǎn),并有助于判斷你是否做出了正確的決定。
最后,在設(shè)計(jì)取代現(xiàn)有系統(tǒng)的系統(tǒng)時(shí),我發(fā)現(xiàn)討論遷移路徑非常重要:我們將如何管理從舊系統(tǒng)遷移到新系統(tǒng)?
如果你曾經(jīng)注意到一個(gè)系統(tǒng),一半的東西運(yùn)行在新代碼上,另一半運(yùn)行在舊代碼上,那就是一條有缺陷的遷移路徑。不考慮遷移路徑會(huì)導(dǎo)致技術(shù)債務(wù)高筑:你現(xiàn)在不得不同時(shí)管理和維護(hù)新系統(tǒng)和老系統(tǒng)。有時(shí),這是因?yàn)閮?yōu)先級(jí)切換,而你還停留在中間狀態(tài)。無論哪種情況,這些異常都不會(huì)長久。
好的遷移路徑可能會(huì)花費(fèi)比較長的時(shí)間,考慮到它們留在系統(tǒng)內(nèi)的狀態(tài)的話。如果優(yōu)先級(jí)改變,我們是否會(huì)陷入到什么都不能做的狀態(tài)?或者我們的遷移是增量的嗎,即使改變優(yōu)先級(jí)也能保持穩(wěn)定運(yùn)行?當(dāng)然,增量遷移并不總是正確的解決方案。有時(shí)候,徹底地遷移會(huì)更容易一些。其中重要的一點(diǎn)是溝通好:我們不能處理這種遷移的優(yōu)先級(jí)變更。
總結(jié):
每個(gè)系統(tǒng)設(shè)計(jì)都關(guān)乎權(quán)衡。
每個(gè)設(shè)計(jì)都有有限的技術(shù)組件。
人們進(jìn)行設(shè)計(jì)時(shí)都有明確的視角,就像思維模型。
在設(shè)計(jì)時(shí)保留上下文:寫下你的約束和權(quán)衡。
當(dāng)取代老系統(tǒng)時(shí),有一個(gè)明確的遷移路徑。
根據(jù)上述主題,收集需求實(shí)際上就是收集約束。正如我們上面所見的,需求有時(shí)是將約束轉(zhuǎn)變成技術(shù)需求,這并不總是正確的前進(jìn)方向。
在我的團(tuán)隊(duì)文化中,團(tuán)隊(duì)和項(xiàng)目經(jīng)理之間有充足的信任,我們可以隨意挑戰(zhàn)彼此的意見。直接問問題就好了。
問題清單在這里很有效。這里鏈接有一些我經(jīng)常問的一些問題。
最后一節(jié)將深入討論一些問題,一些我曾經(jīng)做錯(cuò)的事情,以及對(duì)所有做對(duì)的事情的總結(jié)。
盡可能多地做代碼審查。你錯(cuò)過的越多,你對(duì)代碼的心理模型就越錯(cuò)誤,你設(shè)計(jì)新東西時(shí)需要花費(fèi)的時(shí)間就越多。
斟詞酌句:第二個(gè)問題一般就是問“你是怎么發(fā)現(xiàn) X 的?”,而 X 就是你第一個(gè)問題的答案。
第一個(gè)審核我的 PR 的人是我自己。而且總是這樣。我很喜歡這樣做。這是我從寫作中學(xué)到的:第一階段寫明主旨要點(diǎn),第二階段進(jìn)行段落編輯。這和寫代碼很像。代碼審核就是編輯階段,而且對(duì)我的代碼進(jìn)行代碼審核也會(huì)讓我更好地編寫代碼,發(fā)現(xiàn)不一致的地方,并知道其他人是如何進(jìn)行代碼審核的。
就像在電子游戲中,你可以獲得一些力量。這些有助于你在現(xiàn)實(shí)世界獲得力量。就像在電子游戲中,你需要進(jìn)行任務(wù)才能獲得這些力量。
下面是我發(fā)現(xiàn)的一些可能需要通過的任務(wù)。
當(dāng)文檔不全時(shí)閱讀源代碼
任務(wù):閱讀開源代碼。
為你正在查看的代碼快速構(gòu)建思維模型
任務(wù):閱讀開源代碼。
擁抱恐懼
任務(wù):構(gòu)建一個(gè)輔助項(xiàng)目。
足夠自信,敢于表現(xiàn)無知
任務(wù):克服成長之路上的第一個(gè)常見問題。
定義自己的屬于。讓人們明確知道我在談?wù)撌裁?。就像我?guī)字芮霸凇禝dea Muse》文章中提到的:“大多數(shù)時(shí)候,大部分人都不知道自己在談?wù)撌裁础!?/p>
任務(wù):???
就像工程師喜歡包含常見問題的文檔一樣,我認(rèn)為人們喜歡閱讀關(guān)于成長之路上常見問題的文章——我發(fā)現(xiàn)自己犯的錯(cuò)誤,然后改正了的。
當(dāng)我明白的事情越多,更多的人會(huì)向我問問題。這感覺棒極了!然而,肯定有一些問題我不知道答案。在這種情況下,靠著感覺并且自作聰明是一個(gè)陷阱。這個(gè)陷阱會(huì)阻礙我們學(xué)習(xí)。
如果我說不知道,人們會(huì)停止向我問問題嗎?很可能是這樣的。
而且,他們無論如何都會(huì)找出答案,因?yàn)樗麄円埠苣芨珊吐斆?。如果被這種問題困住是該有多愚蠢?
敢于表達(dá)無知的自信是一種超能力。
我磨練這項(xiàng)技能的一個(gè)好方法是,當(dāng)我沒有什么要補(bǔ)充的時(shí)候,就說“沒什么要補(bǔ)充的”,而不是重復(fù)別人說的話。這讓我感到很強(qiáng)大。我 從查理芒格 那里學(xué)到這個(gè)方法。
有時(shí)候,我會(huì)陷入恐慌和沮喪的狀態(tài)。我不再理性地思考問題,盡可能寫些垃圾來解決問題。添加一個(gè)調(diào)用,添加一個(gè)括號(hào),打印一些隨機(jī)的東西,只是讓事情以某種方式可以運(yùn)行。當(dāng)我修改某個(gè)事情花費(fèi)的時(shí)間超出了預(yù)期時(shí),我就會(huì)開始進(jìn)入這種狀態(tài)。
比如下面這個(gè)具體的例子。我參與對(duì)我們新構(gòu)建的一個(gè)隊(duì)列系統(tǒng)的測(cè)試,我想要模擬饑餓和競爭的隊(duì)列消費(fèi)者。因此,我決定在測(cè)試中生成幾個(gè)線程,都運(yùn)行消費(fèi)者,這些線程將運(yùn)行 5 秒鐘,在隊(duì)列中競爭一條消息。我預(yù)期只有其中一個(gè)線程會(huì)得到這條消息(這是我們實(shí)現(xiàn)的隊(duì)列定義)。而且我預(yù)期這些線程都不會(huì)崩潰。
在這個(gè)測(cè)試中,我給每個(gè)線程設(shè)定的join
超時(shí)時(shí)間是 5 秒。這些測(cè)試不起作用。我嘗試手動(dòng)模擬,一切都會(huì)順利運(yùn)行。但是使用線程,有時(shí)候測(cè)試會(huì)失敗。我想不通其中的問題。我嘗試了所有我能做的隨機(jī)的事情。在一個(gè)絕望的時(shí)刻,我重新安排了測(cè)試的順序。我這樣做的時(shí)候感到很有趣,這怎么可能有幫助呢?結(jié)果,第一個(gè)測(cè)試又通過了,而另一個(gè)之前通過的測(cè)試開始失敗。
那時(shí)候,我發(fā)現(xiàn)自己失去了冷靜,在嘗試一些沒有意義的隨機(jī)事件。我冷靜下來,開始調(diào)查線程中在發(fā)生什么。結(jié)果是,join
只會(huì)等待,即使超時(shí)也不會(huì)終止進(jìn)程。terminate()
才是終止進(jìn)程的方法。如果我花時(shí)間仔細(xì)閱讀了文檔,我就不會(huì)覺得那么沮喪了。
這些線程沒有被終止,而且這些遺落的線程會(huì)擾亂接下來的測(cè)試。
通常,這種情況發(fā)生在我比較匆忙的時(shí)候,當(dāng)我沒有保護(hù)我的空閑,結(jié)果就是我沒有將學(xué)習(xí)放在做事情之上。其它時(shí)候,是因?yàn)榇a比較難,沒有觸手可得的解決辦法。
只要我注意到自己這樣做,我就會(huì)自己從中解脫出來。我會(huì)從應(yīng)急性的 bug 修復(fù)轉(zhuǎn)變?yōu)椴呗孕缘?bug 修復(fù)。
把優(yōu)化學(xué)習(xí)放在做太多事情上很容易。例如,為了嘗試一種新技術(shù)而做出錯(cuò)誤的設(shè)計(jì)決定。多虧了我們的團(tuán)隊(duì)文化,我能控制住自己。我們互相質(zhì)疑彼此的決定,并意識(shí)到當(dāng)我們沒有充分的理由來解釋它時(shí),就會(huì)有一種潛在的欲望——我們之后再把它搞明白。
我做這件事的具體方法:當(dāng)找出一個(gè)設(shè)計(jì)的優(yōu)點(diǎn)和缺點(diǎn)后,我會(huì)明確提出“這學(xué)習(xí)起來很酷”,因此這種意愿不會(huì)再被脆弱的理由隱藏。
因?yàn)橐恍┱_的理由而做決定,而不嘗試新的東西
向團(tuán)隊(duì)技術(shù)棧增加一項(xiàng)新的技術(shù)是一個(gè)重大決定,不能輕易決定。
為了擴(kuò)展去年的清單,我還有一些沒有找到答案的問題。我會(huì)在今年繼續(xù)深入思考這些問題。
你如何構(gòu)建一個(gè)促進(jìn) X、Y、Z 的文化?
你如何判斷文化契合度?當(dāng)事情自下而上構(gòu)建時(shí),很難做自上而下的預(yù)測(cè)。
我覺得字斟句酌自己的語句是另外一種超能力。那就是高效溝通 + 溝通正確的事情。我怎么做才能磨練這項(xiàng)能力?
軟件工程中有哪些開放性的問題?
還有一些去年的問題,我還覺得需要進(jìn)一步思考
如何處理代碼文檔和工作流?
進(jìn)一步探索去風(fēng)險(xiǎn)(De-risking)。降低項(xiàng)目風(fēng)險(xiǎn)的所有策略有哪些?
如何降低系統(tǒng)降級(jí)率?
我第一年時(shí)間在盡自己的最大努力吸收我所能獲得知識(shí)。我沒有足夠的知識(shí)來看系統(tǒng),我只能看到部分。今年,我以上帝視角來查看這個(gè)系統(tǒng)。我找出了一些不太理想的部分并著手改進(jìn)。我查看系統(tǒng)的其它部分,吸收他們的最佳實(shí)踐,并對(duì)那些不太適合我的實(shí)踐保持警惕。
隨著時(shí)間的推移,我開始從我做對(duì)的事情上總結(jié)經(jīng)驗(yàn),而在我意識(shí)到之前,其他人就已經(jīng)開始把我看做是一名高級(jí)軟件工程師了。
我愛死工程學(xué)了。
作者介紹
Neil Kakkar 目前在 Bloomberg LP, London 寫代碼。在 Bloomberg 之前,曾在 ShareChat 實(shí)習(xí),這是一個(gè)印度地區(qū)性的內(nèi)容發(fā)現(xiàn)平臺(tái),增長曲線非常快速。在 ShareChat 之前,曾在 Google。喜歡工程學(xué)和心理學(xué),工程學(xué)幫助我更好地與電腦和其它實(shí)物玩耍,而心理學(xué)幫助我更好地與人類玩耍。另外比較喜歡關(guān)于系統(tǒng)的設(shè)計(jì)和推理。幾乎所有東西都可以建模為一個(gè)系統(tǒng)。
原文鏈接:
https://neilkakkar.com/things-I-learned-to-become-a-senior-software-engineer.html
你也「在看」嗎???
聯(lián)系客服