Categories
程式開發

我只是個1x程序員,這是我五年總結出的經驗法則


作為一名1x開發人員,我在亞馬遜五年的工作中總結了20條經驗法則,希望能夠在有限的自由時間內自我提升為1.1X開發人員。這些經驗法則涉及生產力和學習、編程語言、技術、測試、DevOps、安全、設計和項目管理等領域。希望對大家有所啟發。

本文最初發佈於Mickey Wiki,InfoQ中文站經原作者授權翻譯並分享。

序言

我不是一個10x開發人員。自從有了撥號上網以後,我就沒有再建過網站。我在大學畢業幾年之後才開始學習編程,因為我在政府和政治領域的職業生涯已經走到了瓶頸。

我寫了五年代碼了,這段時間都在亞馬遜。在這期間,我還在養育三個孩子,我剛開始工作時,他們分別是0歲、0歲和2歲。所以我不是那種在晚上和周末還在努力加班的人。我很顧家。

大約一年前,我做了自己的第一個開源項目。這是我的第一個副業項目,它是一個會議網站。

我從來沒有系統地從頭到尾讀過一本關於軟件工程的書。

總之,我是一個1x開發人員。我為了體面的生活付出了足夠的努力。我沒有太多有普遍價值的東西要說,也沒有太多時間去提升。

作為一個1x開發人員,我使用的是大量的傳統智慧。關於軟件工程,我沒有太多有趣或新鮮的東西可說。

總的來說,我還沒有找到方法去從工作中抽出大量時間,或者去做一些更大的副業項目,或者去大量地閱讀,又或者是去取得巨大的成就。我只是能抽點小空(來做這些事情)

但我也有勃勃雄心。我想成為一個1.1x的開發人員。我正在想辦法做到。

我的自助提升理論

這篇文章發表的時候,我正好有些比較自由的時間,因為covid-19病毒帶來的隔離政策,我能休上幾天假,但實際上卻哪裡也不能去,因為此時孩子們也正在放假。

因此,我打算通過以下方式來自我提升軟件工程方面的知識:

  1. 把我對一些軟件工程主題的無知想法寫下來。

  2. 向比我聰明的人分享這些想法,並請他們狠狠地噴我。

  3. 基於他們的反饋進行修正。

  4. 試著想一個方法對有幫助的信息進行查找排序,以去閱讀軟件工程的有關知識,或者在新項目上進行反思,將想法合併到#1中。

規 則

言歸正傳,下面是我作為1x開發人員的經驗法則。

規則1:有規則總是好的

據我觀察,人類在本質上是個模式尋求者,不斷在尋找一種不理性的、前後矛盾的、專制的模式。也就是說,一般來說,大多數人會暗自傾向於以一種取悅領導者的方式設定他們的目標,周圍其他人在做什麼他就做什麼,以及遵循一些現有的模式。在一個複雜的世界中,無論是保持理性還是保持一致性都是非常困難的。因此,“做領導讓你做的”或“做同事正在做的”可以信手拈來,又簡單又快捷。

這種策略在很多情況下都能起到不錯的效果,並有助於營造一種“團隊團結”的感覺。但是,當你們的目標涉及外部,要完成一個團隊外部的目標時,那麼有些事就比“團隊團結”更重要了,理性和前後一致地做事是非常有價值的。

我認為經驗法則(或者如果想說得高大上一點,可以稱它們為原則)可以幫我們提供一些“護欄”、一些“結構”、一些“腳手架”,使大家走出遵從模式的默認心態。它們能幫助我們在一定程度加強邏輯上的一致性。當優先級和價值觀發生大量地碰撞時,它們有助於使交流抓住重點。當你試圖弄清楚,如何面對無數的選擇做出決定時,它們可以幫助你提出一個更清楚明確、更深思熟慮的簡便方法。

我就職於亞馬遜,它以擁有一套普遍適用的原則而著稱,在招聘、做艱難決擇、權衡利弊時都會用到這些原則。我認為有了它們,會使公司更好。不是因為它們有什麼能人異士,而是因為遵循原則總比倒退到唯領導是從要好。

思考很難,做決定很難。有一些精心思考的規則可以幫助我們更好地指導決策。

儘管如此,下面的經驗法則其實與亞馬遜的原則並不相似。它們是我通常一想到某個主題時,腦海中就會浮現出的一些經驗體會。

生產力和學習

規則2:我所學到的大部分知識離開它的即時語境就沒有用了

我有時會聽到有人說,智商測試唯一衡量的是“你有多擅長做智商測試”。我贊成這種看法,也贊成大多數知識都有高度相關性這一普遍看法。大學以來,我做過七份不同的“實際工作”,每一份都有不同職位。在亞馬遜,我做過兩種完全不同的產品和崗位。

我發現,我從一份工作中學到的東西,有90%對下一份工作完全沒有用處。即使這兩份工作同屬一個職業領域。但也不是全部都沒用,剩下的10%可能是非常重要的10%,比如如何更好地處理電子郵件或如何應對辦公室政治。但是,當我開始下一份工作的時候,我學到的大部分東西都是“用完就沒用了”,即在一個非常特殊的組織下如何以非常特殊的方式來做事。

亞馬遜可能截然不同,因為這裡的開發人員花費大量的時間來掌握在其他地方根本不存在的內部工具和業務概念。我大概被這弄得有點想不通了。我知道其他開發人員具有不同的體驗,他們掌握一種特定的技能,而這些技能實際上可以隨著他們從一份工作遷移到另一份工作。

在教育領域(我曾從事過幾年這方面的工作),有一個真相是,大多數知識是不可遷移的。學習某個領域的知識通常對其他領域沒有幫助。

所以,我常常任性地認為:如果我今天所做的90%的事對未來的工作沒有任何幫助,那麼我應該不在那90%上投入過多的精力(像我以前那樣),例如,去關注些通用的思想、系統、抽象概念和技術,或者出於某種重要原因,我願意為這份工作犧牲那90%的時間,或許,僅僅是因為錢多。

這條規則對我來說可能比較特殊,因為我換過很多工作。對於其他人來說,他們或許能夠將大部分技能從一份工作遷移到另一份工作。

規則3:把“學習時間”花在能產生復利的事情上

複利是一個非常重要的概念,它存在於利率體系中、摩爾定律中,哪裡都有它。它主要是關於良性循環的。因此,在有限的自由時間裡,我想的這條經驗法則是,把重點放在能夠引發良性循環的事情上。

我學會更快地打字是一個完美的開端。在過去兩個月時間裡,我在keybr.com上花了一些時間學習,它可以很系統地教你如何更快地打字。字打得越來越快讓我可以在同樣的時間內寫更多的東西,進行更多的交流,完成更多的事情,因為這一點改變讓我在電腦上做的幾乎所有事情都變快了。

建立持久的人際關係也是一項能產生復利的活動,因為它能讓你接觸到更多的人,他們能幫助你更快地完成工作。

消費媒體(書籍、博客等)並不是一件能產生復利的事情。除非你有某種方法來映射、來消化,將知識融入你的思想。如果這篇文章中有些有價值的東西,除非你做些什麼來“加工”它,否則你僅作為讀者,可能並不會從中受益。

編程語言

這部分內容可能會完美地暴露我的無知。

規則4:何時使用Java或C#

Java是大型企業應用程序的理想選擇,很難想像亞馬遜在任何其他平台上運行。這是因為它擁有最強有力的類庫和社區支持,而靜態類型使處理大公司內部的海量數據模型變得更加容易。

我認為C#是微軟對Java的一種詮釋,如果我需要Java的一些好處,但又身處微軟的生態系統中,那麼我會使用它。

規則5:何時使用Python或Ruby

在我看來,Python和Ruby非常相似,它們都是腳本語言,都是動態類型的,它們似乎是00年代最偉大的東西。當速度比易讀性或調試更重要時,就可以選擇使用它們。其次,Python非常適用於ML/AI應用。

在使用Python時,你應該使用類型提示,這麼做更明智一些。

規則6:何時使用硬核語言

我認為Go、Rust、Haskell、Erlang、Clojure、Kotlin、Scala是更“硬核”的語言。在這些語言中,我只用Kotlin交付過產品代碼。

但是設想一下,如果我正在構建一個延遲和性能比社區或類庫支持更重要的全新的Web服務,那麼我可能會使用Go或Rust。

我在做一些不需要很多業務邏輯的事情時,比如一些非常優雅的東西或數學函數方法,可能會用到Haskell或Erlang。

我不知道我什麼時候會使用Clojure,我想,如果我真的開始了解和喜歡Lisp了,我就會使用它。我知道Clojure是一個編譯為JVM字節碼的函數範型,但我更喜歡使用Kotlin。因為Kotlin能與Java一起使用,而且IntelliJ對它的支持也很不錯。對於Scala也類似,我首先會選擇Kotlin。

規則7:如何使用Javascript

我寫過的最糟糕的代碼就是用Javascript寫的。當時,我正在為亞馬遜做一個移動購物專家,我團隊中的同事對於JS框架的有關內容都知之甚少。我們用的是vanilla JQuery。

一開始還很簡單,但很快我們就有了很多新的前端需求,管理前端狀態簡直就是一場噩夢— 想想看,組件消失了,然後又出來了,我們也不知道為什麼,所以我們把每個變量都輸出到了控制台。

許多人都有過如此糟糕的經歷,我就是其中之一。但我認為這主要是我們自己造成的。幾年後的今天,我的JS指南是:

1、使用Typescript ,這是更明智的選擇。

2、嘗試盡可能將邏輯推給服務器。如果前端不是超級複雜,我將考慮類似於Phoenix的選擇,它實際上是把所有東西都推給了服務器。

3、使用Vue之類的框架,或者在需要前端交互時使用React。

4、不要跳過單元測試。

規則8:何時使用C或C++

我覺得不是你選擇了C,而是它選擇了你。有各種應用程序都必須使用C語言,如操作系統、語言設計、底層編程和硬件應用等。

C++很有趣。它似乎非常適用於機器人、電子遊戲和高頻交易等應用程序,因為在這些應用程序中,沒有“垃圾回收”使其性能更優於Java。

規則9:如果你希望不必重新構建就可以測試服務器上的變更,那麼就使用PHP或Hack吧

出於安全方面的考慮,在亞馬遜禁用PHP,但是至少在2020年有大量Facebook和Slack的後端在使用它的繼承者Hack。

在寫這篇文章之前,我從來沒有考慮過何時使用PHP或Hack。也許是因為這在亞馬遜是一種禁忌吧。我知道Slack和維基百科都在使用它。 Slack的人聲稱它擁有一個真正對開發人員友好的編程環境,例如,你不需要重新啟動本地服務器來查看你改動的內容,而且它有web-native的並發支持。

技 術

規則10:何時使用微服務

當我需要每隔一段時間運行一個相對小且簡單的代碼塊時,我就會使用微服務。

規則11:選擇哪種數據庫技術

當需要執行即時查詢和或需要支持ACID和事務時,請選擇SQL。否則選擇 NoSQL。雖然No​​SQL在事務處理方面越來越好,但PostgreSQL(我熟悉AWS Aurora風格)在可用性、擴展性和持久性方面也越來越好,而這些正是NoSQL的傳統優勢。

測 試

規則12:何時編寫單元測試

在任何時候我都會嘗試編寫單元測試,只要預計缺陷產生影響,無論多麼細微。缺陷的預計影響應該是:缺陷的可能性 × 缺陷的成本。我的做法像是一種逃避,因為我無法精確計算這些值。但是,至少對於我編寫的代碼和通常給出的需求來說,一般出現代價高昂的缺陷的可能性還是非常大的。

但每個代碼塊都應該有一個簡單的單元測試,從而驗證代碼是以可測試的方式編寫的,這真的非常重要。

但我不是那種認為每一行和每條分支都必須覆蓋的人。如果你不相信自己(或他人)能夠很好地計算上面的預計影響方程,那麼可以考慮採用這種策略。

規則13:何時編寫集成測試

我將集成測試定義為調用不屬於自己的代碼的測試,而不是模擬它。

只要我無法信任不屬於我的代碼時,就會試著寫一個集成測試。特別是,如果它可以在我不知道的情況下進行變更時。

規則14:何時編寫端到端測試

我將端到端測試定義為使用我的產品模擬完整的“用戶會話”的測試。用戶可以是一個人,也可以是另一台計算機,它試圖通過與我的代碼進行多次交互來完成某些事情。這些通常是規則12中定義的集成測試的超集。

1、當我不完全理解產品是如何工作的,以及不能對一個變更進行充分的單元測試時,我希望有一種方法可以讓我更有信心認為我沒有破壞任何東西,就像“冒煙測試” 。

2、當我需要一些回歸測試用例來驗證未來重構的功能時。

3、當很難提前預知結果的時候,例如,在做一個複雜的計算時,我想測試一些代碼對它們的影響。

第一種情況應該想辦法避免,但第二種和第三種情況實際上真的沒有辦法。

DevOps

規則15:何時需要一個專門的支持工程師

在亞馬遜,默認是由你們自己支持自己的代碼,因此如果系統中出現嚴重錯誤,你們之中的一位同事將被找來日以繼夜地工作,直到問題得到解決。

它可能很殘酷。但是亞馬遜(例如,我現在的團隊)和其他公司中都有專門的部門,他們聘請了一名站點可靠性工程師(SRE),由他負責在正常工作時間之外在線解決嚴重的生產環境問題。

多年在這方面的經歷讓我開始相信,作為一名程序員,如果實際上還存在下班後要被找來工作的風險,應該始終提倡使用專門的SRE。一個最好的例子是,如果你“繼承”了其他人的代碼,還得對裡面已有的缺陷負責。

可以在不同的時區找些人,通過培訓使他們能夠支持你的系統,這件事並不難。關鍵是,要找到給人家的錢。團隊中的工程師們需要共同努力向管理層明確表達這一訴求。

安 全

規則16:如果你把你所有的IT安全委託給信息安全部門,他們會想出非常嚴苛的規則

信息安全是一項棘手的工作。在某種程度上,博弈論說的是對的,他們必然會因為過於謹慎而犯錯。所以我想的這條規則是,你是否至少可以做一些你自己的安全,以避免受到過於嚴格的限制。

一個典型示例​​是亞馬遜內部wiki遷移的災難。早在2015年,亞馬遜的信息安全團隊就禁止在公司內使用PHP了。我們內部的wiki使用的是MediaWiki,而MediaWiki又是用PHP編寫的。

Facebook、WordPress和Slack都在使用PHP,而Facebook正在構建簡化後的Hacklang來取代它,內部的wiki團隊未對這個決定提出任何質疑,只是把這個信息安全指令當成了一條命令來執行。

他們將MediaWiki替換為基於java的替代品XWiki,最終為這個團隊花費了4年多的時間,共計24個開發人員,在這些頁面不斷遷移的過程中,亞馬遜幾乎所有其他團隊都還經受著中斷的困擾,而這些損失並未統計在內。如果他們對PHP的禁令有所抵制,或者對Hack做了更多的研究,可能就能避免這場災難。

設計和白板

規則17:設計會議是尋求建議,而不是請求批准

有很多會議的目的是“得到批准”或“得到投入”。你應該予以避免,只有在萬不得已的情況下才同意這麼做。你希望得到的不是“簽字蓋章”。你希望能夠自己做決定,確定需要與其他人達成什麼程度的協議。

相反,設計會議或交流應該是尋求建議和回答問題的。

項目管理

規則18:估算更多地用於製造壓力,而不是項目規劃

作為在努力交付產品的開發人員和產品經理,我參加過很多估算會議。

大家會說估算是為了規劃,它們的目的是算出某項工作需要多長時間,使每個人都可以按此做計劃。

在我五年的工作經歷中,只記得有一個項目是這樣運作的。那是一個非常簡單的安卓應用程序,沒有外部依賴,沒有什麼技術複雜度,只有一個本地mySQL數據庫和一些視圖。

在這個特別的案例中,因為幾乎沒有未知的東西,所以我們可以做出非常準確的估算。我們可以準確地預測什麼事情在什麼時候會準備就緒,誤差控制在一兩天之內,這對我們有很大的幫助,因為硬性期限定得非常緊張。

在我參與過的項目中,這是唯一一個我們可以精確地量化我們的開發速度,並將其向著里程碑推進的項目。

在所有其他項目中,估算的主要目的是施加壓力,逼著大家去聊“但你說過只需要5天”,這反過來又迫使大家更快、更努力,或者加更長時間的班,以便在未來不去聊這樣的話題。

我本身並不反對壓力。但我認為重點是要認識到,這是做估算的主要目的。

規則19:明確區分硬性期限、軟性期限、內部期限和預計完成日期

硬性期限:如果不能在這個期限前完成,就會對業務造成嚴重的影響。

軟性期限:如果沒有在這個期限前完成,有些人可能會有麻煩。

內部期限:這是一個團隊內部目標,不會影響團隊之外的任何人。

預計完成日期:這是團隊對工作將在什麼時間完成的當前預測。

我見過很多人因為把這些東西搞混而痛苦不堪。無論什麼時候你收到一個期限,都得先問問這是哪一個。當然,通常情況下,內部期限必須保持在正軌上,才能達成硬性期限。但我想告訴大家的是,如果把內部期限當成硬性期限公佈出來,是為了迫使大家多加加班。

另一個需要牢記的是:經常會發生一種情況,當一個工程師給出一個預計完成日期時,其他人卻把它設定成了硬性期限。千萬不要這樣做。

規則20:當有人提敏捷時,推行看板,而不是Scrum

當有人說“我們做敏捷”時,對我來說,這是指每兩週開一次團隊會議。這就是敏捷對於我的全部意義。

有些人可能會弄不清Scrum和看板這兩種敏捷“風格”的區別。在我看來,Scrum意味著“你必須在這兩週內完成某些事情”。看板則意味著“在兩週內做你能做的事情”。如果你不清楚團隊遵循的是Scrum還是看板,你要明確表達,應該推行看板。

考慮到估算的難度(參見規則18),Scrum很容易就變成,你不得不加班去完成那兩週內安排的事情。

延伸閱讀:

https://muldoon.cloud/programming/2020/04/17/programming-rules-thumb.html