生產者與消費者

Gradle 中相依性管理的一個關鍵概念是消費者與生產者的差異。

當您建置函式庫時,您實際上是在生產者端:您正在產生人工製品,這些人工製品將會被其他人(消費者使用

傳統建置系統的許多問題在於它們沒有區分生產者和消費者。

消費者需要廣義地理解

  • 依賴於其他專案的專案是消費者

  • 依賴於人工製品的工作是更細緻的消費者

在相依性管理中,我們做出的許多決定取決於我們正在建置的專案類型,也就是說,我們是哪種類型的消費者

生產者變異

生產者可能希望為不同類型的消費者產生不同的人工製品:對於相同的原始碼,會產生不同的二進位檔。或者,專案可能會產生供其他專案(相同儲存庫)使用但不用於外部使用的人工製品。

Java 世界中的典型範例是 Guava 函式庫,它以不同的版本發布:一個適用於 Java 專案,另一個適用於 Android 專案。

不過,消費者有責任告知要使用哪個版本,而相依性管理引擎有責任確保圖形的相容性(例如確保您不會在 classpath 上同時擁有 Guava 的 Java 和 Android 版本)。這正是 Gradle 的變異模型發揮作用的地方。

在 Gradle 中,生產者變異會透過可消耗組態公開。

強封裝

為了讓生產者編譯函式庫,它需要在編譯 classpath 上擁有所有實作相依性。有些相依性僅作為函式庫的實作細節需要,而有些函式庫實際上是 API 的一部分。

不過,相依於此已產生函式庫的函式庫只需要「看到」您函式庫的公開 API,因此也只需要此 API 的相依性。這是生產者編譯 classpath 的子集:這是相依性的強封裝。

後果是,指派給函式庫的implementation組態的相依性不會出現在消費者的編譯 classpath 上。另一方面,指派給函式庫的api組態的相依性會出現在消費者的編譯 classpath 上。不過,在執行時期,需要所有相依性。Gradle 即使在單一專案中也能區分不同類型的消費者:例如,Java 編譯工作就是不同於 Java exec 工作的消費者。

可以在這裡找到更多關於 Java 世界中 API 和執行時期相依性分離的詳細資訊。

尊重消費者

當您身為開發人員決定包含相依性時,您必須了解這會對您的消費者造成後果。例如,如果您將相依性新增到專案,它就會變成您消費者的傳遞相依性,因此如果消費者需要不同版本,它可能會參與衝突解決。

Gradle 處理的許多問題都是關於修正消費者和生產者預期之間的不匹配。

不過,有些專案比其他專案容易

  • 如果您在消費鏈的末端,也就是說您建置應用程式,那麼您的專案實際上沒有消費者(除了最終客戶):新增排除只會修正您的問題,沒有其他後果。

  • 不過,如果您是函式庫,新增 排除 項可能會導致消費者無法正常運作,因為他們會執行您沒有執行的程式碼路徑

請務必記住,您選擇用來修正問題的解決方案可能會「外洩」給您的消費者。本文件旨在引導您找出適當問題的正確解決方案,更重要的是,做出有助於解決方案引擎在發生衝突時做出正確決定的決策。