程序員: 我要成為軟體架構師。
資深架構師: 好目標。
程序員: 我要領導團隊,決定資料庫、框架、Web 伺服器。
資深架構師: 那你不需要當架構師。
程序員: 為什麼?這些不都是重要決策嗎?
資深架構師: 你沒列出什麼是真正重要的決策。你說的那些與重要決策無關。
程序員: 資料庫不重要?我們花那麼多錢買它!
資深架構師: 資料庫只是IO 裝置,提供排序、查詢、報表工具,但只是系統的附屬品。
程序員: 附屬品?沒有資料庫系統跑不起來!
資深架構師: 業務邏輯或許用到這些工具,但不應依賴它們。好架構下,業務邏輯不依賴資料庫。
程序員: 那業務邏輯怎麼用資料庫?
資深架構師: 依賴反轉。讓資料庫依賴業務邏輯,而非相反。
程序員: 編譯時怎麼辦?調用者不依賴被調用者?
資深架構師: 運行時依賴方向不變,編譯時反轉。上層程式碼零引用下層。
程序員: 不引用怎麼調用?
資深架構師: 面向介面。發送者不知接收者具體類型,只持有介面。
程序員: 這不就是多態?
資深架構師: 關鍵在介面歸屬:介面定義在上層模組(業務邏輯包),下層實現它。
public class BusinessRule {
private BusinessRuleGateway gateway; // 介面
public BusinessRule(BusinessRuleGateway gateway) { this.gateway = gateway; }
public void execute(String id) {
gateway.startTransaction();
Something thing = gateway.getSomething(id);
thing.makeChanges();
gateway.saveSomething(thing);
gateway.endTransaction();
}
}
public interface BusinessRuleGateway { // 介面定義在業務層!
Something getSomething(String id);
void startTransaction();
void saveSomething(Something thing);
void endTransaction();
}
public class MySqlBusinessRuleGateway implements BusinessRuleGateway {
public Something getSomething(String id) { /* 從 MySQL 讀取 */ }
public void startTransaction() { /* 開啟事務 */ }
public void saveSomething(Something thing) { /* 存入 MySQL */ }
public void endTransaction() { /* 提交事務 */ }
}
編譯時依賴:database → businessRules(實現依賴介面)
運行時依賴:BusinessRule → MySqlBusinessRuleGateway(多態調用)
資深架構師: 每個業務邏輯只定義自己需要的介面,不建立大而全的 Gateway。這是介面隔離原則 (ISP)。
程序員: 那不會介面爆炸、類爆炸嗎?
資深架構師: 會,但這才是真正的架構決策——讓核心業務不受外部技術綁架,換資料庫、換框架、換通訊協議時,業務代碼零修改。
程序員: 這太耗時了!
資深架構師: 反而省時。乾淨架構讓測試快、部署輕、變更安全。
| 草率決策 | 後果 | 正確做法 |
|---|---|---|
| 先選資料庫 | 後發現檔案系統更適合 | 先做業務模型,再評估持久化方案 |
| 先選 Web 框架 | 框架約束業務建模,引入大量無用依賴 | 先定義 HTTP 介面契約,再選輕量實現 |
| 全棧框架 | 團隊被框架綁架,升級痛苦 | 微核心 + 插件化,按需引入 |
架構師不做「選資料庫、選框架」這類**技術採購決策**,而做**「如何讓業務邏輯不依賴這些技術」**的**結構性決策**。若干年後若不轉管理,或許能悟透這一切。