每個軟體專案的原始碼和組建邏輯都應該以有意義的方式組織。此頁面列出導致可讀、可維護專案的最佳實務。下列各節也探討常見問題以及如何避免這些問題。

分開特定語言的原始碼檔案

Gradle 的語言外掛程式建立慣例來偵測和編譯原始碼。例如,套用 Java 外掛程式 的專案會自動編譯 src/main/java 目錄中的程式碼。其他語言外掛程式遵循相同的模式。目錄路徑的最後一部分通常表示原始碼檔案預期的語言。

有些編譯器能夠在同一個原始碼目錄中交叉編譯多種語言。Groovy 編譯器可以處理將 Java 和 Groovy 原始碼檔案混合放在 src/main/groovy 中的情況。Gradle 建議您根據語言將原始碼放在目錄中,因為組建效能較高,而且使用者和組建都可以做出更強的假設。

下列原始碼樹包含 Java 和 Kotlin 原始碼檔案。Java 原始碼檔案位於 src/main/java 中,而 Kotlin 原始碼檔案位於 src/main/kotlin 中。

.
├── build.gradle.kts
└── src
    └── main
        ├── java
        │   └── HelloWorld.java
        └── kotlin
            └── Utils.kt
.
├── build.gradle
└── src
    └── main
        ├── java
        │   └── HelloWorld.java
        └── kotlin
            └── Utils.kt

每個測試類型分開原始碼檔案

專案定義並執行不同類型的測試非常常見,例如單元測試、整合測試、功能測試或煙霧測試。最佳做法是將每種類型測試的測試原始碼儲存在專用的原始碼目錄中。分開的測試原始碼對可維護性和關注點分離有正面的影響,因為您可以獨立執行各種類型的測試。

查看範例,了解如何將獨立的整合測試組態新增到基於 Java 的專案。

盡可能使用標準慣例

所有 Gradle 核心外掛都遵循軟體工程範例慣例優先於組態。外掛邏輯在特定脈絡中為使用者提供明智的預設值和標準,也就是慣例。讓我們以Java 外掛為例。

  • 它定義目錄 src/main/java 為編譯的預設原始碼目錄。

  • 編譯原始碼和其他成品 (例如 JAR 檔案) 的輸出目錄為 build

透過堅持預設慣例,專案的新開發人員可以立即知道如何找到方法。雖然這些慣例可以重新組態,但這會讓建置腳本使用者和作者更難管理建置邏輯及其結果。盡可能堅持預設慣例,除非您需要調整至舊專案的配置。請參閱相關外掛的參考頁面,以瞭解其預設慣例。

務必定義設定檔

每次呼叫建置時,Gradle 都會嘗試找出 settings.gradle (Groovy DSL) 或 settings.gradle.kts (Kotlin DSL) 檔案。為此,執行時期會沿著目錄樹狀結構向上走到根目錄。演算法會在找到設定檔後停止搜尋。

務必將 settings.gradle 新增到建置的根目錄,以避免最初的效能影響。檔案可以是空的,也可以定義專案的所需名稱。

多專案建置必須在多專案層級的根專案中具備 settings.gradle(.kts) 檔案。這是因為設定檔定義了哪些專案會參與 多專案建置。除了定義包含的專案外,您可能需要它來 將函式庫新增至您的建置指令碼類別路徑

下列範例顯示標準 Gradle 專案配置

.
├── settings.gradle.kts
├── subproject-one
│   └── build.gradle.kts
└── subproject-two
    └── build.gradle.kts
.
├── settings.gradle
├── subproject-one
│   └── build.gradle
└── subproject-two
    └── build.gradle

使用 buildSrc 來抽象命令式邏輯

複雜的建置邏輯通常很適合封裝為自訂工作或二進位外掛程式。自訂工作和外掛程式實作不應存在於建置指令碼中。只要程式碼不需要在多個獨立專案中分享,使用 buildSrc 來達到此目的非常方便。

目錄 buildSrc 被視為 包含的建置。在發現目錄後,Gradle 會自動編譯並測試此程式碼,並將其置於您的建置指令碼的類別路徑中。對於多專案建置,只能有一個 buildSrc 目錄,它必須位於根專案目錄中。buildSrc 應優先於 指令碼外掛程式,因為維護、重構和測試程式碼比較容易。

buildSrc 使用適用於 Java 和 Groovy 專案的 相同原始程式碼慣例。它也提供對 Gradle API 的直接存取。可以在 buildSrc 下的專用 build.gradle 中宣告其他相依性。

buildSrc/build.gradle.kts
repositories {
    mavenCentral()
}

dependencies {
    testImplementation("junit:junit:4.13")
}
buildSrc/build.gradle
repositories {
    mavenCentral()
}

dependencies {
    testImplementation 'junit:junit:4.13'
}

包含 buildSrc 的典型專案具有下列配置。buildSrc 下的任何程式碼都應使用類似應用程式程式碼的套件。buildSrc 目錄可以選擇性地主控建置指令碼,如果需要其他設定(例如套用外掛程式或宣告相依性)。

.
├── buildSrc
│   ├── build.gradle.kts
│   └── src
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
├── settings.gradle.kts
├── subproject-one
│   └── build.gradle.kts
└── subproject-two
    └── build.gradle.kts
.
├── buildSrc
│   ├── build.gradle
│   └── src
│       ├── main
│       │   └── java
│       │       └── com
│       │           └── enterprise
│       │               ├── Deploy.java
│       │               └── DeploymentPlugin.java
│       └── test
│           └── java
│               └── com
│                   └── enterprise
│                       └── DeploymentPluginTest.java
├── settings.gradle
├── subproject-one
│   └── build.gradle
└── subproject-two
    └── build.gradle

buildSrc 中的變更會導致整個專案過期。

因此,在進行小幅增量變更時,--no-rebuild 命令列選項 通常有助於取得更快的回饋。請記得定期執行完整建置。

gradle.properties 檔案中宣告屬性

在 Gradle 中,屬性可以在建置指令碼、gradle.properties 檔案中定義,或作為命令列上的參數。

在臨時場景中,在命令列上宣告屬性是很常見的。例如,您可能想要傳入特定的屬性值,以控制執行時間行為,僅針對此建置呼叫。建置腳本中的屬性很容易變成維護的頭痛,並混淆建置腳本邏輯。gradle.properties 有助於將屬性與建置腳本分開,並應探索為可行的選項。這是放置 控制建置環境的屬性 的好位置。

典型的專案設定會將 gradle.properties 檔案放置在建置的根目錄中。或者,如果要將檔案套用至機器上的所有建置,檔案也可以存在於 GRADLE_USER_HOME 目錄中。

.
├── gradle.properties
└── settings.gradle.kts
├── subproject-a
│   └── build.gradle.kts
└── subproject-b
    └── build.gradle.kts
.
├── gradle.properties
└── settings.gradle
├── subproject-a
│   └── build.gradle
└── subproject-b
    └── build.gradle

避免重疊的任務輸出

任務應定義輸入和輸出,以取得 增量建置功能 的效能優點。在宣告任務的輸出時,請確定寫入輸出的目錄在專案中的所有任務之間是唯一的。

混合或覆寫由不同任務產生的輸出檔案會影響最新檢查,導致建置較慢。反過來,這些檔案系統變更可能會阻止 Gradle 的 建置快取 正確識別和快取原本可以快取的任務。

使用自訂 Gradle 發行版標準化建置

企業通常希望透過定義常見慣例或規則,為組織中的所有專案標準化建置平台。您可以借助初始化腳本來達成此目的。 初始化腳本 使得在單一機器上的所有專案中套用建置邏輯變得非常容易。例如,宣告內部存放庫及其憑證。

這種方法有一些缺點。首先,您必須向公司中的所有開發人員傳達設定流程。此外,統一更新初始化腳本邏輯可能會具有挑戰性。

自訂 Gradle 發行版是解決此問題的實用方案。自訂 Gradle 發行版由標準 Gradle 發行版加上一個或多個自訂初始化指令碼組成。初始化指令碼與發行版綑綁在一起,並在每次執行建置時套用。開發人員只需將其簽入的 Wrapper 檔案指向自訂 Gradle 發行版的網址即可。

自訂 Gradle 發行版也可能在發行版的根目錄中包含一個 gradle.properties 檔案,提供組織範圍的 屬性集,用以控制建置環境

以下是建立自訂 Gradle 發行版的典型步驟

  1. 實作下載和重新封裝 Gradle 發行版的邏輯。

  2. 定義一個或多個具有所需邏輯的初始化指令碼。

  3. 將初始化指令碼與 Gradle 發行版綑綁在一起。

  4. 將 Gradle 發行版封存檔上傳到 HTTP 伺服器。

  5. 變更所有專案的 Wrapper 檔案,使其指向自訂 Gradle 發行版的網址。

build.gradle
plugins {
    id 'base'
}

// This is defined in buildSrc
import org.gradle.distribution.DownloadGradle

version = '0.1'

tasks.register('downloadGradle', DownloadGradle) {
    description = 'Downloads the Gradle distribution with a given version.'
    gradleVersion = '4.6'
}

tasks.register('createCustomGradleDistribution', Zip) {
    description = 'Builds custom Gradle distribution and bundles initialization scripts.'

    dependsOn downloadGradle

    def projectVersion = project.version
    archiveFileName = downloadGradle.gradleVersion.map { gradleVersion ->
        "mycompany-gradle-${gradleVersion}-${projectVersion}-bin.zip"
    }

    from zipTree(downloadGradle.destinationFile)

    from('src/init.d') {
        into "${downloadGradle.distributionNameBase.get()}/init.d"
    }
}