聊一聊 Go 中面向包的設計
我是一隻可愛的土撥鼠,專注於分享 Go 職場、招聘和求職,解 Gopher 之憂!歡迎關注我。
歡迎大家加入 Go 招聘交流羣,來這裏找志同道合的小夥伴!跟土撥鼠們一起交流學習。
目錄
-
前言
-
鏈接
-
歷史
-
語言機制
-
包的設計哲學
-
項目結構
-
驗證
-
驗證包的位置
-
驗證依賴項
-
驗證正在實施的策略
-
驗證接受 / 返回數據的方式
-
驗證如何處理錯誤
-
驗證測試
-
驗證 recover 和 panic
前言
文章翻譯自:https://github.com/ardanlabs/gotraining/tree/master/topics/go/design/packaging,屬於由於
gotraining
系列的design/packaging
篇,本人翻譯水平,覺得翻譯不當之處煩請指出。謝謝。
面向包的設計允許開發人員確定一個包在 Go 項目中的位置,並且該包必須遵守設計準則。它定義了什麼是 Go 項目以及 Go 項目是如何構建起來的。最後,它增強了團隊成員之間的溝通交流,促進了整潔的包設計和項目架構。
鏈接
可以參考閱讀下面文章
包設計理念
- Design Philosophy On Packaging[1] - William Kennedy
面向包設計
- Package Oriented Design[2] - William Kennedy
歷史
在 2000 年 Mihai Budiu 對 Brian Kernighan 的採訪中,Brian 被問到以下問題:
“Can you tell us about the worse features of C, from your point of view”?
“從你的角度來看,你能告訴我們 c 語言最糟糕的特性是什麼嗎?”?
以下是 Brian 的回答:
I think that the real problem with C is that it doesn’t give you enough mechanisms for structuring really big programs, for creating "firewalls" within programs so you can keep the various pieces apart. It’s not that you can’t do all of these things, that you can’t simulate object-oriented programming or other methodology you want in C. You can simulate it, but the compiler, the language itself isn’t giving you any help.”
我認爲 c 語言的真正問題在於它沒有提供足夠的機制來構造真正的大型程序,在程序中創建 “防火牆”,這樣就可以將各個部分分開。並不是說你不能做所有這些事情,也不是說你不能在 c 語言中模擬面向對象程序設計或者其他你想要的方法。你可以模擬它,但是編譯器,語言本身不會給你任何幫助。
語言機制
-
直接使用包與我們學習如何用其他語言組織源代碼相沖突
-
在其他語言中,包的設計是一種可以選擇使用或忽略的特性
-
您可以將包的設計看作是在源代碼樹上應用微服務的思想
-
所有包都是 “first class”,唯一的層次結構是在項目的源代碼樹中定義的內容
-
需要有一種方式將包的一部分 “暴露” 給外面
-
兩個軟件包不能相互交叉引入。引入是單向的。
包的設計哲學
-
爲了達到目的,包是需要提供其他使用的,而不是包含
-
包的命名必須帶有描述它所提供的內容的意圖
-
包決不能成爲各種不同問題的傾倒場
-
爲了便於使用,包必須以使用者爲中心來設計封裝
-
包必須是直觀的和簡單的使用
-
包必須尊重它們對資源和性能的影響
-
包必須保護用戶的應用程序不受級聯更改帶來的影響
-
包必須防止對具體類型斷言的需要
-
包必須減少、最小化和簡化其代碼庫
-
爲了便於移植,包的設計必須考慮到可重用性
-
包必須追求最高級別的可移植性
-
包必須減少設置策略,當它是合理的且實用
-
不能成爲單一的依賴點
項目結構
Kit Application
├── CONTRIBUTORS ├── cmd/
├── LICENSE ├── internal/
├── README.md │ └── platform/
├── cfg/ └── vendor/
├── examples/
├── log/
├── pool/
├── tcp/
├── timezone/
├── udp/
└── web/
-
vendor/
vendor
文件夾的比較好的參考文檔可以在 Daniel Theophanes 的 Gopher Academy 文章 Understanding and using the vendor folder[3] 中找到。爲了這篇文章的目的,第三方軟件包的所有源代碼都需要轉移 (或複製) 到vendor
文件夾中。包括將從公司 Kit 項目中使用的包。也會將 Kit 項目中的軟件包視爲第三方軟件包。 -
cmd/
cmd/
這個項目擁有的所有程序都在cmd/
文件夾下。cmd/
下的文件夾總是會爲將要生成的每個程序命名。使用程序文件夾末尾的字母 d 表示它爲守護進程。每個文件夾都有一個包含main
包的相匹配的源代碼文件。 -
internal/
需要由項目中的多個程序導入的
internal/
包屬於internal/
文件夾。使用internal/
這個名稱的一個好處是,項目從編譯器那裏得到了額外的保護。這個項目之外的任何包都不能從internal/
導入包。因此,這些軟件包只屬於這個項目的內部。 -
internal/platform/
基礎的但對於項目來說是特定的它會歸爲
internal/platform/
文件夾。這些包可以爲數據庫、身份驗證甚至序列化處理等提供支持。
驗證
面向包設計的一個重要方面是去驗證包設計的能力。這是可能的,因爲根據包在項目中的位置與包相關聯的準則。有七個驗證步驟可幫助你識別設計問題。
驗證包的位置
-
Kit
-
爲現有不同項目提供基本支持的軟件包
-
日誌、配置或網絡功能
-
cmd/
-
爲正在構建的特定程序提供支持的包
-
啓動,關閉和配置
-
internal/
-
爲項目擁有的不同程序提供支持的包
-
CRUD, 服務或業務邏輯
-
internal/platform/
-
爲項目提供內部基本支持的包
-
數據庫、身份驗證或序列化處理
驗證依賴項
-
All
-
要質疑當前這些軟件包的設計選擇
-
如果合理的話,將包移動到要導入包的源代碼樹中
-
使用 source tree 來顯示依賴關係
-
驗證每個依賴項的成本 / 收益
-
爲了共用現有類型要質疑導入
-
對同一級別其他包的導入問題
-
如果一個包想要導入另一個同級別的包:
-
internal/
-
cmd/
-
不能導入來自這些位置的包:
-
internal/platform/
-
cmd/
-
internal/
-
不能導入來自這些位置的包:
驗證正在實施的策略
-
Kit
、internal/platform/
-
不允許對任何應用程序問題制定策略
-
不允許記錄,但必須解耦對追蹤信息的訪問
-
配置和運行時更改必須解耦
-
檢索指標和遙測值必須解耦
-
cmd/
、internal/
-
允許對任何應用程序問題設置策略
-
允許以本機方式記錄和處理配置
驗證接受 / 返回數據的方式
-
All
-
現有類型可能不再適合使用
-
驗證給定類型的 值 / 指針 語義的一致使用
-
當使用接口類型接受值時,重點必須放在所需的方法上,而不是值本身
-
如果不需要方法,則使用具體類型
-
在合理的情況下,在聲明新類型之前使用現有類型
-
問題類型來源於暴漏給導出 API 中的依賴項
驗證如何處理錯誤
-
All
-
錯誤已被記錄
-
應用程序恢復到了 100% 完整性
-
不再報告當前錯誤
-
處理錯誤意味着:
-
Kit
-
應用程序中不允許 panic
-
不允許包裝錯誤
-
只返回根源錯誤值
-
cmd/
-
允許在應用程序中使用 panic
-
如果未處理,可以用上下文包裝錯誤
-
大多數處理錯誤發生在這裏
-
internal/
-
應用程序中不允許 panic
-
如果未處理,可以用上下文包裝錯誤
-
少數處理錯誤發生在這裏
-
internal/platform/
-
應用程序中不允許 panic
-
不允許包裝錯誤
-
只返回根源錯誤值
驗證測試
-
cmd/
-
允許使用第三方測試包
-
可以有一個用於測試的
test
文件夾 -
與單元測試相比,更要多關注集成測試
-
kit/
,internal/
,internal/platform/
-
在 Go 中堅持 testing 包
-
測試文件屬於包
-
更多地關注單元測試而不是集成測試
驗證 recover 和 panic
-
cmd/
-
可以 recover 任何 panic
-
只有當系統可以恢復到 100% 完整時
-
kit/
,internal/
,internal/platform/
-
goroutine 歸一個包所有
-
可以給應用程序提供一個關於 panic 的事件
-
不能從 panic 中恢復,除非:
參考資料
[1]
Design Philosophy On Packaging: https://www.ardanlabs.com/blog/2017/02/design-philosophy-on-packaging.html
[2]
Package Oriented Design: https://www.ardanlabs.com/blog/2017/02/package-oriented-design.html
[3]
Understanding and using the vendor folder: https://blog.gopheracademy.com/advent-2015/vendor-folder/
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/zPHooITRTLNJDcbH2uPsUw