第二種耦合是建置期耦合(build-time coupling)——一種發生在「建置專案的子專案之間」的關係。建置專案來自第 3 章的 build 視角,把一或多個子領域的原始碼組織為子專案(subproject),負責建置與測試元件。
例如 FTGO 巨石的建置專案可能包含 order-management、customer-management、delivery-management 等子專案。如果修改 customer-management 會迫使 order-management 重新編譯與重新測試(即使後者沒改),代表 order-management 與 customer-management 是建置期耦合的。
設計期耦合決定「修改有多容易」;建置期耦合決定「修改後等回饋等多久」。理想上,只有被改動的子專案需要重新編譯與測試;緊建置期耦合會增加重新編譯與測試的範圍,最壞情況下開發者得等整個元件重建。
Gradle 中的建置期耦合#
實例以 Gradle 為主(其他建置工具大同小異)。
- Gradle 建置專案通常由多個子專案組成,並透過依賴宣告(
api、implementation)指定子專案間的關係。 - 因為 Gradle 支援增量建置(incremental build),只會重建受影響的子專案——也就是被改動的子專案,以及那些(直接或遞移)依賴它的子專案。
範例:假設 FTGO 有以下 Gradle 結構,accounting 與 customer-management 都以 implementation 方式依賴 money,order-management 又透過 customer-management 的 api 依賴傳遞依賴到 money。

Figure 4.9: Dependencies between Gradle projects create build-time coupling (money, accounting, customer-management, order-management)
執行 ./gradlew build:
- 修改
money內的Money類別 → 會重跑money、accounting、customer-management、order-management(透過api傳遞依賴)的測試。 - 修改
customer-management內的Customer→ 只會重跑customer-management與order-management,因為accounting、money不依賴customer-management。
api與implementation的差異:api依賴會被傳遞給上層消費者;implementation不會。把不必對外暴露的依賴宣告為implementation,可以切斷不必要的傳遞建置期耦合,大幅縮小重建範圍。
一個專案應該只與「穩定」的專案建置期耦合#
加速建置的一個核心策略:讓頻繁變動的子專案,不被太多其他子專案依賴。
拆分 API 與 Implementation#
子領域的實作通常變動比 API 頻繁很多,因此把子領域拆成兩個 Gradle 專案:
- API 子專案:給 client 使用的介面與相關類別。
- Implementation 子專案:實作細節。
範例:
- 不分拆時:單一
customer-management專案,client(如order-management)直接依賴它,每次實作改動都會強制 client 重建。 - 分拆後:
customer-management-api(穩定):放CustomerService介面與相關 DTO。customer-management-impl(較頻繁變動):放實作類別。order-management改為依賴customer-management-api;測試使用CustomerService的 mock。
- 效果:Customer Management 內部實作改動不會頻繁觸發 client 重建,顯著縮短回饋時間。

Figure 4.10: Defining an API project + implementation project reduces build-time coupling
在子專案內部減少建置期耦合#
Gradle 子專案對自己也是建置期耦合的——子專案內任何原始檔變動都會重跑該子專案的所有測試,即使被改的程式碼與某些測試完全無關。
加速做法:把單一子專案再拆成多個更小的子專案。
範例:customer-management-impl 內含 web、persistence、domain 三個套件,且 web 與 persistence 都依賴 domain,但彼此不依賴。
- 不分拆:改
web內的類別,Gradle 會重跑全部三個套件的測試,即使domain、persistence完全沒被影響。 - 分拆:把三個套件改為三個子專案,
web與persistence都依賴domain但彼此不依賴——改web不會觸發persistence的測試。

Figure 4.11: Splitting a subdomain's implementation project into several projects can further reduce build-time coupling
這個分拆對速度的提升特別顯著,因為
persistence的測試常常用實體資料庫,本身就慢。讓不相關的測試彼此獨立,是降低部署管線時間的關鍵手法。
巨石架構與微服務架構的差異#
- 大型巨石:由於只有單一程式碼庫,最小化建置期耦合至關重要;第 6 章會介紹相應的設計模式。
- 微服務:每個服務本就相對小,建置期耦合的影響相對小,但仍有意義;第 13 章會介紹組織服務內部程式碼的模式,部分動機就是減少建置期耦合。