Proto Delivery Boundary Design¶
概念概覽
核心原則:目錄結構反映交付邊界¶
核心知識¶
核心原則:目錄結構反映交付邊界¶
pro 目錄不應按功能分類(如 messages/、services/),而應按**交付對象**分類:
- common/v1/:客戶端 SDK 會包含的型別(client-facing API)
- internal/v1/:純伺服器內部服務,不對外暴露
csharp_namespace 獨立於 package 的關鍵性¶
proto 的 option csharp_namespace 可以與 Go package path 完全獨立,這讓伺服器端重構(改 package name、移動目錄)不影響前端 C# 代碼:
// 移動到 matchrpg/common/v1/ 後
package matchrpg.common.v1; // 伺服器端 Go import 改變
option csharp_namespace = "MatchRpg.V1"; // 保留舊值,前端不需改動
option go_package = "github.com/xxx/proto/matchrpg/common/v1;commonv1";
重構時 import 更新的範圍¶
- 所有 import
matchrpg/v1/common.proto的 proto 檔需更新 import path - Go 代碼約 15 個檔案需更新 import package(機械式工作量)
- C# 代碼因 namespace 不變,零改動
Wire Format 風險評估¶
package rename 在技術上改變了 wire format,但: - Preview/開發階段:風險低,可接受 - 已上線服務:需謹慎,應確認沒有依賴 proto package name 做序列化的邏輯
經驗教訓¶
-
proto 目錄結構應依「交付對象」區分,而非單純依功能分類——這個決策直接決定 codegen 邊界是否清晰
-
csharp_namespace 與 Go package 獨立,是跨語言 proto 重構的緩衝層,重構前先確認這個選項是否已設定
-
Preview 階段是做結構性重構(package rename、目錄移動)的最低風險視窗
常見陷阱¶
-
proto 按功能分類(而非交付對象分類)導致 buf 白名單無法精確,內部服務代碼容易洩漏進 client SDK
-
common.proto 被多個 proto import,移動時若漏更新某個 import path 會導致 buf generate 失敗但錯誤訊息不直觀
最佳實踐¶
-
設計 proto monorepo 時,最早就按 client-facing / internal 分目錄,避免後期重構成本
-
跨 repo 客戶端存在時,優先用 csharp_namespace / java_package 等語言選項吸收 proto 結構變更
-
common.proto 被多個服務 import 時,移動前先用 grep 確認所有引用點,一次性批量更新
相關概念¶
相關視角¶
以下頁面與本概念共享主題,但從不同角度切入。保留獨立視角同時提供交叉參考:
- API Refactoring PR Splitting Strategy — 共享:
api-design/ 獨特:breaking-change,code-review
來源 Sessions¶
| 日期 | Session | 貢獻摘要 |
|---|---|---|
| 2026-03-20 | ce632061-4850-4646-b2a2-cd5752d01b26 | 建立「依交付對象分目錄」的 proto 組織原則,並示範保留 csharp_namespace 實現前端零感知重構 |