Android 应用模块化的指南

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

不断增长的代码库问题

在一个不断增长的代码库中,可扩展性、可读性和整体代码质量往往会随着时间的推移而下降。这是因为代码库在增加规模时,维护人员没有采取积极措施来强制执行易于维护的结构。模块化是一种以提高可维护性并帮助避免这些问题的方式来构建代码库。

什么是模块化?

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

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

模块化的优势

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

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

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

优势 摘要
可扩展性 在一个紧密耦合的代码库中,一个更改可能会触发看似不相关的代码部分的一系列更改。一个正确模块化的项目将采用 关注点分离 原则,因此限制了耦合。这通过更大的自主权赋予了贡献者权力。
所有权 除了赋予自主权外,模块还可以用来强制责任制。一个模块可以有一个专门的所有者,负责维护代码、修复错误、添加测试和审查更改。
封装 封装意味着代码的每个部分都应该对其他部分的了解最少。隔离的代码更易于阅读和理解。
可测试性 可测试性反映了测试代码的难易程度。可测试的代码是指可以轻松隔离测试组件的代码。
构建时间 一些 Gradle 功能,例如增量构建、构建缓存或并行构建,可以利用模块化来提高构建性能

常见陷阱

代码库的粒度是指它由多少个模块组成。粒度更高的代码库拥有更多更小的模块。在设计模块化代码库时,您应该确定粒度级别。为此,请考虑代码库的大小及其相对复杂性。粒度过细会导致开销成为负担,而粒度过粗则会降低模块化的益处。

一些常见的陷阱如下

  • 粒度过细:每个模块都会带来一定程度的开销,形式是构建复杂性增加和样板代码。复杂的构建配置使保持模块之间配置一致变得困难。过多的样板代码会导致代码库笨重,难以维护。如果开销抵消了可扩展性改进,您应该考虑合并一些模块。
  • 粒度过粗:相反,如果您的模块变得过大,您可能会最终得到另一个单体,并错过模块化带来的优势。例如,在小型项目中,将数据层放在单个模块中是可以的。但随着项目的增长,可能需要将存储库和数据源分离到独立的模块中。
  • 过于复杂:对项目进行模块化并不总是合理的。主要因素是代码库的大小。如果您不希望项目超出某个阈值,则可扩展性和构建时间上的收益将不会适用。

模块化是否适合我?

如果您需要可重用性、严格的可见性控制或使用Play 功能交付,那么模块化是必要的。如果您不需要,但仍然希望从改进的可扩展性、所有权、封装或构建时间中获益,那么模块化是值得考虑的。

示例