-
Notifications
You must be signed in to change notification settings - Fork 4
Head First Software Architecture
《Head First Software Architecture》(Raju Gandhi、Mark Richards、Neal Ford,O'Reilly 2024)是一本給軟體架構入門者的書。它不教你背模式,而是給一副思考架構的骨架:任何系統都可以拆成四個維度去看,再用兩條定律去權衡。
本頁的承諾:就算你沒讀過這本書,讀完這頁也能懂本專案為什麼長這樣。 每個概念先用白話講一遍,再落到本 repo 的某個真實目錄、檔案或慣例上。
骨架一覽:
- 四個維度:架構特性(-ility)、邏輯元件(內聚/耦合)、架構風格、架構決策(ADR)。
- 兩條定律:第一定律「一切皆取捨」、第二定律「why 比 how 重要」。
書裡用一個很實際的判準區分兩者:「改這個決定有多痛?」 改起來牽一髮動全身、要重接一堆東西的,是架構;改起來只影響局部、換掉就好的,是設計。架構決定通常更早、更難逆轉,所以更值得慎重。
-
架構級例子:本 repo 用
*.symlink命名慣例 +start/link_dotfiles掃描連結到$HOME。這個「用檔名決定行為」的機制一旦要換掉(例如改成註冊表或 GNU Stow),幾乎每個目錄、每份文件、每個新手心智模型都要跟著改 —— 這是架構。 -
設計級例子:
shellscripts/裡某支 bash 工具內部怎麼寫、要不要多包一個 function,改了只影響那一支,別人無感 —— 這是設計。
架構特性是系統「要好在哪」的那些以 -ility 結尾的品質:可維護性、可移植性、可擴展性…… 書裡強調一件事:你不可能全都要,必須挑出少數幾個驅動特性,其餘都是它們的推論或犧牲品。挑錯驅動特性,整個架構就會用力在錯的地方。
本專案的驅動特性:
| 驅動特性 | 在本 repo 的具體形貌 |
|---|---|
| 可維護性 | topic-per-directory 佈局:一個工具一個目錄,改 zsh 不會碰到 nvim;dp、shellcheck、gitleaks 讓日常變更有固定流程。 |
| 可移植性 | 雙平台:start/bootstrap(macOS)+ start/setup_linux.sh(Linux);start/ 堅持 Bash 3.2 相容,確保裸機 macOS 出廠環境也能跑。 |
| 可組合性 / 可演化性 | 每個工具能獨立增減:新增一個 topic 只要建目錄 + 命名 *.symlink,不需改任何中央清單;Brewfile 也是逐條加減。 |
刻意不追求的特性:效能吞吐、水平擴展、高可用。這是一份個人 dotfiles,沒有 runtime 服務、沒有併發流量,把力氣花在 scalability 上是浪費 —— 這正是「挑對驅動特性」的反面示範。
邏輯元件是系統的功能積木。好的切分追求高內聚(一個元件內的東西彼此相關)與低耦合(元件之間盡量不互相纏死)。書裡的重點是:元件邊界應該沿著「會一起改變的東西」畫。
對應到本 repo 的元件切分:
-
start/是安裝器元件,內聚在「把裸機變成可用環境」這件事;共用 TUI 收斂在start/lib/,不外洩到其他目錄。 -
每個 topic 目錄(
zsh/、tmux/、hammerspoon.symlink/…)是一個高內聚元件,彼此低耦合 —— 它們唯一的共同介面就是*.symlink命名慣例,除此之外互不知道對方存在。 -
claude.symlink/go-tools/把claude-hooks/claude-statusline的 Go 原始碼獨立成一個編譯元件,和被連結的設定檔分開,因為「原始碼」和「設定」的變更節奏不同。
書把架構風格粗分兩大類:單體(所有東西在一個可部署單位裡)與分散式(拆成多個獨立部署、透過網路溝通的服務)。分散式買到彈性與獨立擴展,但付出網路、一致性、維運複雜度。
本專案的風格:模組化單體 + 慣例優於設定。所有設定收在單一 git repo(單體),但內部沿 topic 切成鬆耦合模組;*.symlink 命名慣例本身就是一種零註冊的「外掛註冊機制」 —— 檔名即註冊,不需要中央設定檔登記。
為什麼是這個風格?因為它是被驅動特性逼出來的:要可移植就得一次 clone、一份 git pull 同步全部,分散式會讓「同步」變成災難;要可維護又要能獨立增減工具,就需要單體內部的模組化。分散式風格能給的好處(獨立擴展、容錯)本專案根本不需要,所以自然收斂到模組化單體。
架構決策記錄(ADR)是把「一個重要決定」寫成三段:Context(當時面對什麼處境)、Decision(決定怎麼做)、Consequences(帶來的好與壞後果)。關鍵是 Consequences 一定要誠實列出負面後果 —— 沒有只有好處的決定。
本 repo 的三個真實決策:
ADR-1:用 *.symlink 命名慣例做零註冊連結
-
Context:要把散在各目錄的設定連到
$HOME,而且希望新增工具的成本極低。 -
Decision:
start/link_dotfiles掃描所有*.symlink,連結成$HOME下的.<name>。 - Consequences:(+)加一個工具零註冊,建目錄 + 命名就完成,無中央清單要維護。(-)隱性魔法:行為藏在檔名裡,新手看不到「哪裡定義了這個連結」,心智負擔高。
ADR-2:單一 repo 收全部設定
- Context:想要一致的備份與跨機同步,不想管理多個散落的 repo。
-
Decision:zsh、nvim、tmux、Claude、~90 個
~/.config應用設定全放進一個 repo。 -
Consequences:(+)一次 clone 即完整,
git pull+link_dotfiles就同步全機。(-)repo 巨大且天生會混進機密,被迫採「預設忽略、白名單追蹤」(見claude.symlink的.gitignore58–67 行),白名單維護成了持續成本。
ADR-3:start/ 堅持 Bash 3.2 相容
- Context:全新 macOS 出廠只有 Bash 3.2,bootstrap 必須在 Homebrew 裝好之前就能跑。
-
Decision:
start/內腳本禁用關聯陣列、${var,,}等 Bash 4+ 語法。 - Consequences:(+)裸機第一支腳本就能執行,可移植性落地。(-)放棄現代 bash 語法、寫起來更囉嗦,而且目前只靠人記得、沒有自動驗證(見 Plan-and-Tech-Debt 技術債 #5)。
書的第一定律:架構裡沒有「最佳解」,只有「取捨」。每個決定都是一手交錢一手交貨 —— 你買到某個好處,同時付出某個代價。架構師的工作不是消滅取捨,而是看清楚自己買了什麼、付了什麼。
| 決定 | 買到什麼 | 付出什麼 |
|---|---|---|
*.symlink 命名慣例 |
零註冊、加工具極快、無中央清單 | 隱性魔法,檔名決定行為,新手不易懂 |
| 單一 repo 收全部設定 | 一致、好備份、跨機同步簡單 | repo 巨大且含機密,需 gitignore 白名單只追蹤特定路徑 |
| Bash 3.2 相容 | 裸機可 bootstrap、可移植 | 放棄現代語法,靠人記得,無自動驗證 |
| Go 重寫 hooks / statusline | 啟動快、無 runtime 相依 | 多一道編譯步驟(make -C claude.symlink/go-tools install) |
第二定律:知道「怎麼做」(how)會過時,知道「為什麼這樣做」(why)才是架構的核心資產。程式碼會告訴你 how,但半年後的你(或任何接手者)真正需要的是 why —— 否則只能猜,或把好的決定當成 bug 改掉。
本 repo 的 why 存在哪裡:
-
各層
CLAUDE.md:給 AI 的操作指引 + 最小地圖,說明「這個模組是幹嘛的、怎麼碰」。 -
docs/Quarto book:較完整的人類向說明,push 後由 Netlify 部署。 - Plan-and-Tech-Debt 的「現況 / 計畫」:把每項技術債的來龍去脈寫下來,讓「暫時先這樣」有據可查。
-
Conventional commits +
dp:commit 訊息裡的feat:/fix:/refactor:保留了每次變更的意圖。
先定驅動特性,其餘皆推論。 本 repo 先認定自己要的是可維護、可移植、可組合 —— 於是模組化單體、*.symlink 零註冊慣例、單一 repo、Bash 3.2 相容這一連串決定,全都是從那三個特性順理成章長出來的形狀,而不是東拼西湊的偶然。
- Home — 目錄地圖與快速開始
- Maintenance — 慣例落地:如何新增一個 topic、機密管理、追蹤策略
- Plan-and-Tech-Debt — 每個取捨的「付出」被記錄與排序的地方
- Roadmap — 驅動特性未來要往哪推進
- 書:Raju Gandhi、Mark Richards、Neal Ford,《Head First Software Architecture》,O'Reilly,2024。
- Home — 簡介
- Maintenance — 維護指南
- Roadmap — 路線圖
- Plan-and-Tech-Debt — 計畫與技術債
- Head First Software Architecture — 架構觀