上帝視角看 “Go 項(xiàng)目標(biāo)準(zhǔn)布局” 之爭
本文轉(zhuǎn)載自微信公眾號(hào)「腦子進(jìn)煎魚了」,作者陳煎魚。轉(zhuǎn)載本文請(qǐng)聯(lián)系腦子進(jìn)煎魚了公眾號(hào)。
大家好,我是煎魚。
前段時(shí)間 Go 語言社區(qū)有一件事情引爆了熱議,那就是 golang-standards/project-layout 項(xiàng)目的 “Go 項(xiàng)目的標(biāo)準(zhǔn)布局” 之爭。
沒想到,五一假期,認(rèn)真一看,這個(gè) issues 已經(jīng)提出將近一個(gè)月了,仍然在熱議階段,我想,咱們需要好好的聊聊這個(gè)話題。
煎魚帶你了解下的前因后果,再分享我的看法和業(yè)務(wù)真實(shí)情況。
背景
問題發(fā)生地
在 GitHub 上有一個(gè)項(xiàng)目 Spaghetti(github.com/adonovan/spaghetti),是 Go 軟件包的一個(gè)依賴性分析工具。
該項(xiàng)目的目錄結(jié)構(gòu)如下:
看上去并不復(fù)雜,代碼量不多,文件平鋪也不超過一屏,就是一個(gè)布局比較簡單的項(xiàng)目。
有一位老哥提出了一個(gè) PR,明確的期望該項(xiàng)目按照 golang-standards/project-layout 項(xiàng)目給出的 “標(biāo)準(zhǔn)” 布局來調(diào)整。:
我猜測該項(xiàng)目可能是因?yàn)榘?Go、HTML、JS、PNG 和 go.mod 文件等擺在了一起,引起了該同學(xué)的一絲絲糾結(jié),覺得比較亂?
“標(biāo)準(zhǔn)布局“ 長什么樣子
在 golang-standards/project-layout 項(xiàng)目中,其自稱:
項(xiàng)目的組織名也是 "golang-standards",其提供了一個(gè)基本的 Go 項(xiàng)目布局,精簡展示如下:
- project-layout
- ├── api
- ├── cmd
- ├── configs
- ├── docs
- ├── go.mod
- ├── init
- ├── internal
- ├── pkg
- ├── scripts
- ├── vendor
- ├── ...
- /cmd:項(xiàng)目主要的應(yīng)用程序。
- /internal:私有的應(yīng)用程序代碼庫,這些是不希望被其他人導(dǎo)入的代碼。
- 應(yīng)用程序?qū)嶋H的代碼可以放在 /internal/app 目錄(如:internal/app/myapp)。
- 應(yīng)用程序的共享代碼放在 /internal/pkg 目錄(如:internal/pkg/myprivlib)中。
- /pkg:外部應(yīng)用程序可以使用的庫代碼(如:/pkg/mypubliclib)。其他項(xiàng)目將會(huì)導(dǎo)入這些庫來保證項(xiàng)目可以正常運(yùn)行。
- /vendor:應(yīng)用程序的依賴關(guān)系,可通過執(zhí)行 go mod vendor 執(zhí)行得到。
- /configs:配置文件模板或默認(rèn)配置。
- /init:系統(tǒng)初始化(systemd、upstart、sysv)和進(jìn)程管理(runit、supervisord)配置。
- /scripts::用于執(zhí)行各種構(gòu)建,安裝,分析等操作的腳本。
更具體的布局介紹,大家可以參見 project-layout 項(xiàng)目的 README,其基本把方方面面的目錄都考慮到了(人多力量大)。
由于內(nèi)容過于長,因此就不一一展示了。
Russ Cox 現(xiàn)身原因
不過很巧,該項(xiàng)目的作者是前 Google 員工,是 gopl.io 項(xiàng)目(5.1k stars)的作者。
在僅僅過去 23 分鐘后,作為 GoTeam Leader 的 Russ Cox(@rsc)就現(xiàn)身,并提出新的 issue 表達(dá)出了反對(duì)意見:
在 golang-standards/project-layout 項(xiàng)目的 README 中有明確指出這不是官方的標(biāo)準(zhǔn),有如下聲稱:
it is a set of common historical and emerging project layout patterns in the Go ecosystem.
Russ Cox 主要是對(duì)聲稱 "這是一套 Go 生態(tài)系統(tǒng)中常見的歷史和新興的項(xiàng)目布局模式" 這一說法表示了 “不準(zhǔn)確” 的意見。
例如:Go 生態(tài)系統(tǒng)中的絕大多數(shù)包都不會(huì)將可導(dǎo)入的包放在 pkg 子目錄中。更廣泛地說,這里描述的只是非常復(fù)雜的工程項(xiàng)目,而 Go 的倉庫往往要簡單得多。
另外,不幸的是,這套項(xiàng)目布局在組織名字上被稱作 "golang-standards"(Golang 標(biāo)準(zhǔn)) 提出來,實(shí)際上并非真的是官方標(biāo)準(zhǔn),有誤導(dǎo)的情況存在。
Russ Cox 反對(duì)原因
在了解 project-layout 項(xiàng)目所提供的 “標(biāo)準(zhǔn)“ 項(xiàng)目布局和 Russ Cox 提出 issues 的背景后。
我們進(jìn)一步了解 Russ Cox 認(rèn)為這不對(duì)的根本考慮。project-layout 這個(gè)項(xiàng)目有兩個(gè)問題:
- 它聲稱是 Go 標(biāo)準(zhǔn)(Go standards)的主辦方,但實(shí)際上并非如此,因?yàn)檫@些標(biāo)準(zhǔn)絕非 Go 官方標(biāo)準(zhǔn)。
- 它提出的項(xiàng)目布局標(biāo)準(zhǔn)過于復(fù)雜,不是一個(gè)合理的標(biāo)準(zhǔn)。
Go 項(xiàng)目布局的標(biāo)準(zhǔn)是什么
提出這個(gè) issues 后,出現(xiàn)了一大堆人追問 Russ Cox,到底何為 Go 項(xiàng)目的布局標(biāo)準(zhǔn)?
Russ Cox 給出了正式回應(yīng),一個(gè)可導(dǎo)入的 Go repo 的最小標(biāo)準(zhǔn)布局是:
- 在你的根目錄下放一個(gè) LICENSE 文件。
- 在你的根目錄下放一個(gè) go.mod 文件。
- 將 Go 代碼放在 repo 中,放在根目錄中,或者按照你認(rèn)為合適的方式組織成一個(gè)目錄樹。
就這樣了,這就是 "標(biāo)準(zhǔn)",沒有那么復(fù)雜。不需要像 project-layout 項(xiàng)目一樣的布局。像是 Go 官方的 golang.org/x 倉庫打破了 project-layout 所說的這些 "規(guī)則 "中的每一條。
Go 提案
在經(jīng)歷了長時(shí)間的口水戰(zhàn)后,已經(jīng)有人在 Go 官方倉庫提出希望釋出相關(guān)的提案(proposal):
猜測可能會(huì)有如下幾種可能:
- GitHub 項(xiàng)目 golang-standards/project-layout 愿意更名,不再自稱 ”golang-standards“,不過可能性比較低,因?yàn)橐呀?jīng)已多人提出,但作者沒什么表示。
- Go 官方正式提供 Go 標(biāo)準(zhǔn)項(xiàng)目布局的說明。
- Go 官方不做約束,僅做表態(tài),可能輸出文章。
后續(xù)大家繼續(xù)關(guān)注該提案,就可以知道發(fā)展了,傳送門:issues #45861。
按照慣例,我猜測第三種可能性最大,因?yàn)楹茈y有人可以提供所有開發(fā)者認(rèn)可的標(biāo)準(zhǔn),每個(gè)事業(yè)部、團(tuán)隊(duì)的喜好都可能有所不同。
總結(jié)
實(shí)際上,任何東西自稱 “XX 標(biāo)準(zhǔn)”,在名氣大后,都會(huì)帶來一些問題。就像本文提到的 golang-standards/project-layout 項(xiàng)目一樣。
換位思考一下,若你是某個(gè)項(xiàng)目的 Leader,某一天你的同事,被人拿著 “標(biāo)準(zhǔn)” 來建議修改時(shí),說這是這個(gè)項(xiàng)目的 “標(biāo)準(zhǔn)”,會(huì)不會(huì)很奇妙?
無獨(dú)有偶,我有一個(gè)朋友,他們公司早年只有一套 DDD 標(biāo)準(zhǔn),本想統(tǒng)一。結(jié)果后面每一個(gè)介入 DDD 的業(yè)務(wù)同學(xué),都認(rèn)為前人不標(biāo)準(zhǔn),每個(gè)人都自創(chuàng)了一套 DDD 標(biāo)準(zhǔn)。
總是會(huì)有小伙伴想讓定義絕對(duì)的 “標(biāo)準(zhǔn)”,又或是 “最佳實(shí)踐”。其實(shí)是難以定義的,最好的就是能夠一個(gè)團(tuán)隊(duì)內(nèi)形成基本共識(shí),這里面牽扯到的不單單只有技術(shù)...