最好的 Go 框架就是不用框架?

2023-10-09     InfoQ

原標題:最好的 Go 框架就是不用框架?

作者 | Robert Laszczak

譯者 | 張健欣

策劃 | 褚杏娟

撰寫本文時,我已經領導 Go 團隊好多年了。我從初學者那裡聽到的最常見的問題是:我應該使用什麼框架?

在使用 Go 的過程中最糟糕的事情之一就是遵循其它程式語言的方法。其它語言已經建立了「默認」框架:Java 的默認框架是 Spring,Python 的默認框架是 Django 和 Flask,Ruby 的默認框架是 Rails,C# 的默認框架是 ASP.NET,Node 的默認框架是 Express,PHP 的默認框架是 Symfony 和 Laravel。而 Go 不同:沒有默認框架。

更有趣的是,許多人建議你根本不應該(在 Go 中)使用框架。他們瘋了嗎?

Go 語言的哲學

Go 框架是存在的,但沒有一個 Go 框架提供項其它語言框架那樣的功能集。這點短期內不會改變。你可能認為這是因為 Go 生態系統比較「年輕」。但是還有一個更重要的因素。Go 是圍繞 Unix 哲學構建的:

  • 一個程序只做一件事並把它做好。
  • 程序間協同工作。
  • 編寫程序來處理文本流,因為這是一個通用接口。

這個理念來自 B 程式語言(C 語言的前身)的設計者肯·湯普森(Ken Thompson),他也是 Go 語言的設計者。

在實踐中,Unix 哲學傾向於構建小而美的軟體,而不是大而全的軟體。你可以在你的終端中看到這些例子。例如:cat example.txt | sort | uniq 。cat 從文件中讀取文本,sort 對行進行排序,uniq 刪除重複行。所有命令都是獨立的且只做一件事。這直接來自 Unix 哲學。得益於這樣的設計,你可以獨立開發比較小的自治命令。

在 Go 中,Unix 哲學在標準庫中隨處可見。最好的例子是應用最廣泛的接口:io.Reader 和io.Writer 。最好的庫都遵循這種哲學。

框架的設計違背這種哲學理念。通常,它們試圖在一個框架內涵蓋所有可能的用例。它們不是為了與其它工具一起使用而設計的,而且通常無法復用。這意味著不可能將開發成果轉移到其它不兼容的框架。如果框架的採用率很低(或者就是死了),那所有的努力都白費了。

對你來說,什麼是重要的

每個技術決策都有權衡,你的選擇要對你和你的項目更有意義。

當你在從事一個短期項目(比如用時不到一周且用完即扔的概念驗證項目)時,有些方案是有意義的。在這種情況下,最關鍵的因素是你能多快地完成它。但是如果你在從事一個持續很長時間的項目,並且你要與多人一起協作,那麼這個決定的影響是巨大的。

對於大多數項目,最重要的參數是:

  • 你能以多快的速度啟動項目
  • 從長遠來看,你能以多快的速度開發項目
  • 對於未來的變化,項目的靈活度(這與前兩點緊密相關)。

讓我們開始評估我們的決定。

節省時間

框架最大的好處之一就是節省時間。運行一個命令就可以得到一個功能齊全的項目。框架通常提供一個固定結構的項目,而且如果你不知道如何做,它會有很大幫助。但與大多數其他技術決策一樣,它不是沒有代價的。

隨著時間的推移,當項目增長時,你會很快觸及框架在約定和限制方面的牆壁。框架作者的需求跟你的需求可能有所不同。框架創建者採取的決策可能適用於簡單的 CRUD 應用程式,但無法處理更複雜的場景。如果繼續使用,很容易就為了克服一個框架限制而迅速失去在項目啟動上節省的所有時間。隨著時間的推移,這可能會導致團隊遇到很多挫折。

幾年前,我在一家使用 Go 框架(我會略過框架名稱)的初創公司工作。這家公司正在成長並創建新的服務。隨著時間的推移,當我們想要支持的複雜用例越多時,我們就感到越痛苦。這個框架也是嚴重 Bugs 的來源。不幸的是,擺脫這個框架並不容易。

有一次,一些框架組件變得無法維護,與生態系統的其它部分不可兼容。我們被迫擺脫這個框架,而這個框架已經與整個系統緊密耦合。將其從數十個服務中移除是一個不小的任務,這需要一個跨團隊的計劃、需要多人數月的時間和努力,才能擺脫這個框架。即使這個項目最後成功了,我也不認為整個事情是成功的。如果有人更早做出不同的決定,所有花費的時間可以被利用得更好。整個項目都不是必要的。許多公司對開發團隊缺乏信任也就並不令人奇怪了。

這是一個很好的例子,表明了一個小小的決定會在數年後變成一個代價高昂的需要「救援」的項目。

項目的可維護性

衡量項目的可維護性是一個有爭議的話題——很難比較兩個項目的可維護性。有些人說框架很棒,他們沒有感到使用框架的痛苦。對其他人來說,框架可能是長期以來最大的噩夢。有些項目比其他項目更具挑戰性,許多人認為與框架較勁只是工作的一部分。這就是為什麼很難客觀地衡量框架對項目可維護性的影響。

幸運的是,我們可以用一點科學知識來理解它。基於科學研究的《Accelerate:The Science of Lean Software and DevOps》一書,聚焦於找出表現最好和表現最差的團隊的特點。對我們來說重要的是,良好性能的最重要的一個因素就是松耦合架構。

我領導的團隊經常問我,「如何知道我們的架構是松耦合的」,最簡單的方法之一是確保應用程式的部件可以輕易替換或刪除。如果你的應用程式的部件很難刪除,那麼你的應用程式就是緊耦合的。這樣的緊耦合會導致牽一髮而動全身,引發多米諾效應。

為什麼松耦合架構如此重要?需要承認,我們都是人,即使經過了最好的調研,我們也會犯錯。當你選擇了錯誤的庫或框架,應該很容易替換而不需要重寫整個項目。如果我們想要節省時間,我們應該考慮從長期來看有什麼幫助,而不僅僅是在項目開始時。

請考慮一個場景,當你想要完全刪除一個框架時,需要重寫大量代碼嗎?它可以在多個服務上獨立運行嗎?如果不行,那麼你需要花些精力將框架和核心邏輯分開。但是,這會犧牲框架一開始時帶來的「省時」。

備選方案?構建服務時不用框架

你可能會覺得,在沒有框架的情況下構建服務需要很長時間,尤其是如果你之前使用其它程式語言。我理解這一點,幾年前當我開始用 Go 寫程序時,我也有相同的感受。但是,不用框架並不意味著你自己需要構建一切東西,有許多經過驗證的庫會提供你需要的功能。

這意味著,你需要在調研上多花一點兒精力。如果你正在閱讀本文,那你就已經在調研了!幾個小時的調研時間在整個項目的生命周期中幾乎不值一提。你這樣做所帶來的靈活性,很快會將你調研所花的時間「掙」回來。

如果你決定不使用框架,應該怎麼辦?一開始最大的障礙可能是如何構建一個服務。最簡單的方法是一開始將所有東西放到一個文件中。你可以簡單地開始,推遲一些決定,然後隨著時間的推移演化你的項目。

如果有示例項目可以作為參考,那麼這會很有幫助。你可以看看我在 GoRemoteFest – github.com/roblaszczak/goremotefest-livecoding 上的演講「讓我們用 Watermill 在 15 分鐘內構建一個事件驅動應用程式」所用的項目。這個示例項目只需要兩個外部庫就可以運行了。

請隨意 copy 這個代碼庫並根據你的需要調整,我確信這個示例不會有你項目所需的全部的庫。我們發布了一篇文章介紹可以用來構建 Go 服務的 Go 庫清單。這些庫我們已經用了幾年了,還解釋了我們為什麼使用這些庫,以及如何識別類似的庫是好還是壞。

文章連結:

https://threedots.tech/post/list-of-recommended-libraries/

當你的項目變得越來越複雜,而且你已經知道了你的庫是如何協同工作的,那麼你就可以開始重構它了。最後,你可能不需要那些看起來很關鍵的框架功能。得益於此,你可以得到一個更簡單的項目並進行更少的調研。

總 結

決定如何構建服務不是你應該走捷徑的地方。從長遠來看,做出錯誤的決定會對你的時間產生非常負面的影響。它會對團隊的速度產生負面影響,更重要的是會影響士氣。

在做出錯誤的決定後,你很快就會陷入沉沒成本謬論的陷阱。與其成為解決自己製造的問題的英雄,我們應該避免製造這些問題。

作者介紹:

Robert Laszczak 是 SlashID 的首席工程師、三點實驗室(Three Dots Labs)的聯合創始人、Watermill 庫的創建者。

原文連結:

The Best Go framework: no framework?(https://threedots.tech/post/best-go-framework/)

聲明:本文為 InfoQ 翻譯,未經許可禁止轉載。

點擊底部閱讀原文訪問 InfoQ 官網,獲取更多精彩內容!

今日好文推薦

下一代 Docker 來了!1小時構建縮至1.5分鐘,還能結合 LangChain、Ollama 等做 AI 應用開發

蘋果中國App Store將不允許未備案應用上架;iPhone 15發熱嚴重,問題源於第三方軟體?Meta又要裁員了 | Q資訊

微軟裁員內幕

Angular 重磅回歸

文章來源: https://twgreatdaily.com/zh-cn/32de8679f329d214adc582d60db111df.html