声明式 Gradle

注意:声明式 Gradle 是一个正在积极开发的实验性项目,在实现过程中会发生频繁的更改。要了解有关当前状态的更多信息,请访问声明式 Gradle GitHub 上的存储库。在这里,您可以访问当前文档、原型和 项目状态看板。订阅 Gradle 构建工具时事通讯 以接收有关该项目的每月更新 - 上次更新时间为 2024 年 5 月 11 日

我们对 Gradle 构建工具的愿景的一部分是提供一种优雅且可扩展的声明式构建语言,使开发人员能够以清晰易懂的方式描述任何类型的软件。

Gradle 的构建语言在最基本的方式上已经是可扩展的,这带来了高度的灵活性。这是 Gradle 成为许多公司(包括大型企业)的首选构建系统以及 Android 和 Kotlin 多平台的默认构建系统的主要原因之一。

但是,我们的构建语言目前并不总是完全声明式、清晰且易懂。虽然长期以来一直是最佳实践,即构建脚本应该是声明式的,并且构建逻辑应该保留在插件中,但这并非许多项目的现实情况。我们已经看到了一些项目在野外混合了声明式和命令式代码,并创建了冗长而复杂的构建脚本。构建脚本中使用的 Gradle 特定概念并不总是为软件开发人员所熟悉。这可能会使 Gradle 对不熟悉 Gradle 的开发人员来说不太容易使用。同时,这也使得 IDE 难以为编辑构建脚本提供可靠的支持。

这篇博文解释了 Gradle 团队对我们称之为“开发者优先软件定义”或简称“声明式 Gradle”的观点。本文概述了我们让“优雅且声明式的构建语言”成为我们愿景现实的计划。

软件开发人员和构建工程师

首先让我们澄清 Gradle 两大用户群体之间的区别:软件开发人员和构建工程师。

大多数 Gradle 构建工具用户是软件开发人员。他们的工作是通过发布功能、修复错误等来改进他们的软件产品。软件开发人员不会以运行构建为一天的开始。虽然他们依赖构建系统来完成他们的任务,但这并不是他们的主要关注点。

第二组用户是构建工程师。与软件开发人员不同,他们的职责是维护构建本身。该群体历来赞赏 Gradle 的灵活性,它可以满足即使是最复杂的构建自动化需求。

实际上,这两个角色之间经常存在重叠。在较小的团队中,一些熟悉 Gradle 的工程师往往会拥有构建。在较大的团队中,通常会有专门的构建工程师。

软件定义与构建逻辑

接下来,让我们澄清软件定义和构建逻辑之间的区别。

**软件定义**是构建的内容。它定义了正在生产的软件的结构,并包含以下信息:

  • 正在生产什么类型的软件?
  • 软件是用什么语言实现的?
  • 软件针对哪些平台?
  • 软件的依赖项是什么?
  • 应该使用哪些工具链来编译/链接/检测/捆绑/记录软件?
  • 在软件可以发布之前需要进行哪些质量检查?

**构建逻辑**是如何构建软件的。它是为 Gradle 添加新功能、集成不同工具以及为软件定义提供约定的代码。

软件定义旨在供软件开发人员阅读和修改。构建逻辑旨在供构建工程师阅读和修改。

在 Gradle 中,软件定义存在于 Groovy DSL 和 Kotlin DSL 构建脚本和设置中。建议将构建逻辑保留在插件中。然而,用户可以灵活地在构建脚本中与软件定义一起包含构建逻辑。这导致了软件开发人员和构建工程师的关注点和需求之间的界限变得模糊。

什么是开发者优先软件定义

我们的战略目标是使软件定义对开发人员更清晰、更简单。

我们认为实现这一目标有两个关键步骤:

使用受限 DSL 分离软件定义和构建逻辑

如上所述,混合软件定义和构建逻辑是不建议的。

我们计划提供一个受限的 DSL,它将软件定义和构建逻辑分开,以便构建语言完全是声明式的。这将有效地强制执行现有的最佳实践。

受限的 DSL 将只允许有限的构造集,例如嵌套块、分配值和选定的方法调用。通用控制流和对任意方法的调用将被禁止。您可以在任何 JVM 语言(如 Java、Kotlin 或 Groovy)中编写构建逻辑,但该逻辑将驻留在插件(本地或已发布)中。

这将提供软件开发人员和构建工程师之间更好的关注点分离,以及更简单的构建视图,而不会限制工具的灵活性。

将软件定义与软件领域匹配

虽然受限的 DSL 是朝着正确方向迈出的一步,但它只是使软件定义真正以开发人员为中心的解决方案的一部分。

另一个问题是,当前的软件定义并非在所有情况下都使用反映底层软件领域的概念。要使用 Gradle,开发人员通常需要了解 Gradle 特定的构建块,例如依赖项配置和任务。这些概念特定于构建逻辑,因此应该只与构建工程师相关。在大多数情况下,软件开发人员应该能够通过使用他们已经熟悉的概念(例如库、应用程序、版本和测试套件)来配置他们需要的一切。

Android Gradle 插件是基于 Gradle 的更具声明性软件定义 DSL 的一个很好的例子。虽然更广泛的 JVM 生态系统尚未达到我们期望的状态,但最近的功能(例如 测试套件工具链)是朝着这个方向迈出的一个显著步骤。

我们的目标之一是提供更广泛的此类高级构造,这些构造可以在各个生态系统之间共享。这将使现有的生态系统更加一致,例如 Java、Android 和 KMP。它还将使将来更容易实现对新生态系统的支持,例如 iOS 或 .NET。

IDE 体验

以开发人员为中心的软件定义的关键方面是它使提供出色的 IDE 体验变得更容易。

软件定义传统上是手动编辑的。使用 Groovy DSL,由于 Groovy 语言的动态特性,只有基本的 IDE 辅助是可能的。使用 Kotlin DSL,在支持的 IDE(如 IntelliJ IDEA 和 Android Studio)中可以获得出色的支持。这包括自动完成、智能内容辅助、快速访问文档、导航到源代码以及上下文感知重构。使用 Kotlin DSL,您可以使用与处理生产代码时相同的编辑体验来编辑构建逻辑。

但是,对于 IDE 供应商来说,在构建脚本中允许任意代码时,自动更改软件定义或创建 UI 编辑器是困难的。通过使软件定义完全声明式,支持将变得容易得多。我们知道 IDE 供应商非常有兴趣提供这种功能。有了它,软件开发人员可以根据自己的偏好和专业知识水平选择编辑模式(UI 或手动)。

性能方面也需要考虑。例如,IDE 同步过程涉及一系列步骤,包括依赖项解析等复杂计算,以在 IDE 中提供项目的完整视图。通过可以快速可靠地解析的完全声明式软件定义,我们可以在 IDE 中快速提供项目的初始视图,即使对于大型项目也是如此。

Gradle、Google 和 JetBrains 之间的合作

Gradle、Google 和 JetBrains 拥有悠久而富有成果的合作历史。我们最近一次主要的联合努力导致了 Kotlin DSL 成为新 Gradle 构建的默认值。这引发了 Kotlin DSL 的流行热潮,并使许多用户能够在支持的 IDE 中享受 Gradle 构建脚本的完整 IDE 辅助功能。

今年 10 月,我们与来自三家公司的代表会面时,将大部分注意力集中在声明式软件定义上。我们都认识到,当前许多项目中软件定义与构建逻辑和更低级构造的混合,对用户体验造成了现有约束。Gradle、Google 和 JetBrains 正在合作提供解决方案来解决这些问题。我们正在密切合作,以确保该解决方案能够很好地适用于 Android 和 Kotlin 多平台生态系统,并提供出色的 IDE 支持。

Gradle 团队负责领导这个项目,并与 JetBrains 和 Google 密切合作,以确保在 IntelliJ IDEA 和 Android Studio 中提供出色的 IDE 支持。这个项目是 Gradle 的首要任务之一。我们已经在积极开发初始原型。明年年初,我们计划与早期采用者分享针对简单项目的初始解决方案,首先从 Android 开始。

与此同时,JetBrains 正在进行一项具有类似目标的实验,称为 Amper。我们的目标之一是利用这个实验来促进声明式 Gradle 的开发,并为 Kotlin 和 Kotlin 多平台提供出色的用户体验。因此,除了专注于声明式 Gradle 的专门小组外,我们还与 JetBrains 的 Amper 团队密切合作。

我们希望这种合作能够改善多个生态系统(包括 Java、Android 和 Kotlin 多平台)的用户体验。

过渡

我们对以开发者为中心的软件定义感到兴奋,并坚信它将使使用 Gradle 的软件开发人员和构建工程师都更加满意。同时,我们也意识到目前数十亿行代码与这种方法不兼容。

我们的目标之一是,一旦新软件定义可用,就让团队能够轻松地逐步迁移到新软件定义。我们目前正在研究使用受限的 DSL 语法,该语法将与现有的声明式 Kotlin DSL 脚本兼容。受限的 DSL 将成为 Groovy 和 Kotlin DSL 旁边的另一个选项。现有的 DSL 将继续得到完全支持,我们正在探索允许将构建文件逐步迁移到受限 DSL 的方法。我们还在研究可以帮助过渡的工具。

反馈

我们很想知道您对我们以开发者为中心的软件定义的愿景和计划有何看法。如果您有任何问题或反馈,请随时通过我们的 论坛社区 Slack 中的 #declarative-gradle 频道与我们联系。

了解更多

讨论