每個開發者都應該知道的10件事
我是一個 Python + Go 開發者,過去幾年一直從事于全球范圍內的應用開發。我和我的團隊每天要應對大約 200 萬的客戶,處理這種規模級別的事務其實是不太容易的,所以,我想分享一下過去幾年我的一些經驗和技巧。
安全問題絕不能是馬后炮
應用的安全問題絕不應該是馬后炮或者降級成為“稍后再考慮的事兒”。我們需要從應用開發的第一天起,就將強有力的安全性考量貫穿到每次討論和開發流程中去,而不是開發到第 300 天才開始考慮。將安全問題放到最后考慮,反而會增加開發的時間,需要回爐重構以適應安全問題。更糟的情況是,你沒有足夠的時間來解決任何漏洞,最終只能交付易受攻擊的代碼。可以去了解下雅虎(Yahoo)這樣的公司,他們是如何做到這一點的。
應用不同,需求也不同。按需為應用做技術選型,而不是迫于行政壓力或市場熱度
每個應用都不盡相同,這一點其實無須贅述。沒有任何一套神圣的準則可以應用于所有應用(當然也包含本條)。當開始開發一個新的應用時,是應用本身及其架構決定了它要使用哪種技術或者基于哪個平臺。在思考“我的應用需要什么?”這個問題之前,就決定使用 gRPC 或者Kubernetes 只會造成一種后果:在你開始動手寫代碼之前,就為以后設置了路障,這也是為什么我們會陷入像 Canonical 這樣公司會為物聯網設備提供 Kubernetes 服務的可笑境地。引用 Jeff Goldblum 的話,“你們的科學家如此醉心于他們能夠干什么,卻不會停下來想一想是否應該這樣做”
你可能不需要微服務
我知道,微服務很迷人。能夠在應用程序中獨立地伸縮各種組件是令人興奮的,這也合理化了基于特定代碼庫的持續工作。但如果誠實地想一想,你可能沒有必要“微服務化”,像諸如此類的原因,“我想將 X 功能和 Y 功能解耦”,“避免壞代碼污染應用的其他部分”,亦或是 “應用程序崩潰時,最小化受影響的半徑”,這些都不是微服務化的借口,反而是壞的開發實踐(保持你現在,需要時再去觸及),code review 標準需要更加嚴格(不滿足要求的代碼暫時不要 merge),缺乏細粒度的安全控制的表現。
你真的需要獨立伸縮應用的不同部分,并且目前有能力解決一個或更多的組件問題(如登錄流程)嗎?
你的應用是運行在基于虛擬服務器的架構上并且想要縮減開支嗎?那么你不應該去探索微服務。
在最好的情況下,你能做到收支相抵。在最壞的情況下,需要啟動額外的實例。假設你有一個包含五個服務的整體應用,然后你將其分解為多個微服務。現在,你有5個應用程序,要么a)為其啟動專用實例,使初始內存占用增加5倍,要么b)使用現有內存占用,只需增加管理它的操作成本。
擁有標準的開發環境
當你與多個開發者協作時,其中一件最有裨益的事情就是在團隊中標準化開發環境。這其實并不意味著非得一起使用基于容器,虛擬化開發環境的“巫術”。當然了,如果你想這么做也可以。但像使用相同版本的開發語言這種簡單的標準,有時就會在團隊中創造奇跡。當同事基于 Go 1.11 版本開發時,你去嘗試基于 Go 1.12 版本去定位 bug 時,你會哭的。在協作中升級版本是有難度的,但如果操作正確升級也可以很順滑。
配置比看起來要困難,按需計劃
與一些熱門網站所說的相反,配置其實要比“把所有東西扔進環境變量”復雜的多。在我看來,配置一個應用程序應該至少有四種方式:
- 代碼中的默認配置
- 本地配置文件
- 命令行標記
- 環境變量
- 遠端配置源(如 Hashicorp 的 Consul)
我將遠端配置當做是可選的,但其他四種是必要的。
開發過程中,將依賴的 27 個配置值扔到環境變量中,僅僅是為了在本地運行應用程序,這一點至少是令人沮喪的。或者你可能需要更好的自動化以及一個 Makefile?可以提供一種方式如一個application.yaml文件來訪問本地配置源,允許你設置默認的 “dev” 配置。另外,代碼中的默認配置意思是你只需要設置需要修改的默認配置。當通過像 systemd 這樣的初始系統運行應用時,命令行標記會非常有用,因為它可以在追蹤進程時,更加容易的看到配置信息。當應用運行在容器中時,環境變量會非常實用,但像秘鑰這種配置不適合放在環境變量中。
絕不要將秘鑰如密碼、認證token、證書等一些你不想泄露出去的東西放到環境變量中,因為這樣很不安全,有可能被宿主機上的任何進程讀到。你應該總是使用秘鑰管理器來管理秘鑰,我個人的選擇是Vault by Hashicorp,你可以選擇最適合你的。
按需使用包管理,而不是僅僅因為能用
我們都知道 “left-pad” 事件,一個只有 11 行代碼的 NPM 包從倉庫中移除,為何給全網造成了影響?我們不要這樣做。有合理的導包需求時,才應該使用 package,如特定供應商的SDK(例如 AWS 的 SDK),是一組非常詳細的標準庫的抽象(這就是為什么大家喜歡用 Python 的 Requests 庫而不使用 urllib),或者導入被廣泛使用的框架如 Go 語言的 Echo HTTP server 或者 Python 語言的 Flask WSGI server。一些方便的庫也可以,比如 JavaScript 的 Lodash,它提供了一些標準庫中沒有的公共功能和附加功能。這些外部依賴應該讓開發更容易,并且不需要手工編寫樣板或集成代碼 -- 這些是包管理的益處,但是,像 left-pad 這種,很容易陷入這種陷阱--“這正好有一個能解決問題的庫,直接用舊行了”。每一個你導入的依賴,都會增加不穩定、不安全或者僅僅不可維護的風險。
每導入一個包,新的依賴項本身的風險就會增加——這也稱為傳遞依賴項。如果你導入一個單獨的包,而這個包又導入了五個包,那么你現在就繼承了這五個依賴項以及它們所帶來的所有風險和危險。我和很多業內人士都認為包不應該引入傳遞依賴關系,但這是不現實的,至少包應該盡可能精簡,如果需要更強大的功能,則為用戶提供顯式擴展它的方法。
我現在遵循的一個簡單原則是,如果導入的庫,我自己可以在 10-15 分鐘實現,就自己實現。否則,如果有可用的外部庫,我就使用外部庫。開發過程中謹記這個規則可以讓你避免導入一些不必要的包。如果你不希望每次都從頭開始編寫新的 HTTP 服務器來提供 API,那么這種方法就足了。
如無必要,無需抽象
一個極易陷入的大陷阱就是“抽象所有”的黑洞。“這個我后面可能會復用”的想法可能會使你誤入一些黑暗和可怕的面向對象歧途,我弄清了其中的個中緣由,DRY 原則已經深入人心且理由充分。但是你花太多時間去抽象反而沒有足夠的時間寫邏輯。只需安心編寫代碼,如果你發現需要實現一個與之前完成的其他工作類似的方法或函數,那么你可以返回并抽象它——但同樣要有節制。我個人傾向于遵循的原則是,如果在抽象之前它是一個簡單的三行函數,那么最好保持不變,然后重復它。如果只是 3 行代碼,也許可以自問,它是否需要變成一個函數?
你應該時不時地“涅槃”你的項目
本條準則是最可怕的,它讓管理者緊張,讓產品經理氣急敗壞,讓開發者憤怒,但是你絕對需要它。
每隔一段時間就從頭開始是一件好事,它允許你代碼中刪除垃圾,實現新的想法,而不需要改造現有的代碼庫,并迫使每個人重新評估項目。
把項目想象成森林,每一行代碼都是綿延數英里的大森林中的一棵巨大松樹。隨著森林的演化,灌木叢、丟棄的松針、松果、枯死的樹枝和其他雜物散布于森林之中。這是你厭惡的東西,你的技術債。它會一直不斷堆積,直到某些巨變發生。對于森林而言,這種變化是以野火的形式出現。大火橫掃森林,燒毀了堆積起來的無用垃圾。樹皮足夠厚的樹會留下來,未成熟或未發育完全的樹會在火災中被燒毀。雖然這看起來是森林的盡頭,但它隱藏了一個巨大的秘密:森林一直在等待這場火。耐心地,年復一年地,森林一直在期待這場大火來凈化自己,并帶來變化。因為當大火在樹冠下肆虐時,下一代的參天大樹正在松果中發芽。當大火蔓延到森林地面時,脆弱的幼樹就會冒出來,與被大火熏黑的幸存者為伴。這也是你的應用程序該有的樣子:有彈性的、在清除過程中,編寫良好的部分幸存下來,而其他部分則為新思想和新代碼讓路——就像鳳凰涅槃一樣。
你不是 Google
除非你是 Google,但如果你真的是 Google,為何你還在讀這篇文章呢?關鍵是你大概率不是 Google,不是 Microsoft,不是 Amazon,不是 Twitter,不是 Facebook。你不需要在全世界 17 個不同的數據中心的 10,000 個裸機服務器上編排 150,000 個容器。你的問題通常不會對世界上每一個人造成很大的影響。我們為什么要討論這個?因為你的規模決定了你的操作平臺。如果你正在運行幾百個容器,那么你真的需要 Kubernetes 嗎?你真的需要自己運行 Kubernetes,還是只是想把它添加到你的簡歷中?HashiCorp Nomad 之類的工具非常適合解決中小型問題:它易配置,幾乎不需要維護,有良好的文檔,并且非常容易就可以把應用程序遷移過去,因為它可以與容器、系統進程和 JVM 應用程序一起工作。如果你真的想使用 Kubernetes,為什么不基于把繁雜細節都抽象好的 Rancher 來管理呢?運行 Kubernetes 這樣的復雜系統(它是為谷歌這樣的公司設計的)所帶來的麻煩和開銷對于一個團隊來說是難以承受的。我甚至會直截了當地說,初創公司應該不惜一切代價避免使用它,除非他們的產品是專門針對 Kubernetes 的。需要注意的是,要使用 Google、Amazon 和 Microsoft 在各自的云產品中提供的托管服務。因為他們管理著所有的丑陋的東西,很多管理費用并不是由你來承擔的。但千萬別讓我抓到你在物聯網設備上使用 Kubernetes,千萬不要。
不要照搬網上陌生人的開發哲學
對于開發風格和要遵循的原則,你應該形成自己的想法。即使是上面的 10 條建議也只是僅供討論,我只是網上的過客。