Android 应用模块化指南

包含多个 Gradle 模块的项目称为多模块项目。本指南涵盖了开发多模块 Android 应用的最佳实践和推荐模式。

不断增长的代码库问题

在不断增长的代码库中,可伸缩性、可读性和整体代码质量往往会随时间下降。这是由于代码库的规模不断扩大,而维护者没有采取积极措施来强制实施易于维护的结构所致。模块化是一种组织代码库的方式,可以提高可维护性并有助于避免这些问题。

什么是模块化?

模块化是一种将代码库组织成松散耦合且自包含部分的实践。每个部分都是一个模块。每个模块都是独立的,并具有明确的用途。通过将一个问题分解为更小、更容易解决的子问题,您可以降低设计和维护大型系统的复杂性。

图 1:示例多模块代码库的依赖关系图

模块化的优势

模块化的优势众多,但它们都围绕着提高代码库的可维护性和整体质量。下表总结了主要优势。

优势 摘要
可重用性 模块化为代码共享和从同一基础构建多个应用提供了机会。模块实际上是构建块。应用应该是其功能的总和,其中功能被组织为独立的模块。特定模块提供的功能可能在某个应用中启用,也可能不启用。例如,:feature:news 可以是完整版本风味包和 Wear OS 应用的一部分,但不是演示版本风味包的一部分。
严格的可见性控制 模块使您能够轻松控制代码库中向其他部分公开的内容。您可以将除了公共接口之外的所有内容标记为 internalprivate,以防止其在模块外部使用。
可定制的交付 Play 功能交付 利用应用包的高级功能,让您可以有条件地或按需交付应用的某些功能。

上述优势只能通过模块化的代码库实现。以下优势可能通过其他技术实现,但模块化可以帮助您更进一步地强制执行它们。

优势 摘要
可伸缩性 在紧密耦合的代码库中,单个更改可能会在看似不相关的代码部分中引发一连串的修改。一个适当模块化的项目将遵循关注点分离原则,从而限制耦合。这通过更大的自主权来赋能贡献者。
所有权 除了实现自主性之外,模块还可以用于强制执行问责制。一个模块可以有一个专门的所有者,负责维护代码、修复错误、添加测试和审查更改。
封装 封装意味着代码的每个部分应该尽可能少地了解其他部分。隔离的代码更易于阅读和理解。
可测试性 可测试性描述了测试您的代码的难易程度。可测试的代码是指可以轻松地独立测试组件的代码。
构建时间 一些 Gradle 功能,如增量构建、构建缓存或并行构建,可以利用模块化来提高构建性能

常见陷阱

代码库的粒度是其由模块组成的程度。更细粒度的代码库拥有更多、更小的模块。在设计模块化代码库时,您应该决定一个粒度级别。为此,请考虑您的代码库的大小及其相对复杂性。粒度过细会增加开销,而粒度过粗则会削弱模块化的优势。

一些常见陷阱如下

  • 粒度过细:每个模块都会带来一定量的开销,表现为构建复杂性增加和样板代码增多。复杂的构建配置使得在模块之间保持配置一致性变得困难。过多的样板代码会导致代码库变得臃肿且难以维护。如果开销抵消了可伸缩性改进,您应该考虑整合一些模块。
  • 粒度过粗:相反,如果您的模块变得过大,您可能会得到另一个单体应用,并错过模块化带来的好处。例如,在一个小型项目中,将数据层放在单个模块中是可以的。但随着项目的增长,可能需要将存储库和数据源分离到独立的模块中。
  • 过于复杂:模块化项目并非总是明智之举。一个主要因素是代码库的大小。如果您不期望您的项目增长到某个特定阈值以上,那么可伸缩性和构建时间方面的收益将不适用。

模块化适合我吗?

如果您需要可重用性、严格的可见性控制或使用Play 功能交付等优势,那么模块化对您来说是必要的。如果您不需要这些,但仍希望从改进的可伸缩性、所有权、封装性或构建时间中受益,那么模块化是值得考虑的。

示例