具有多个 Gradle 模块的项目称为多模块项目。本指南涵盖了开发多模块 Android 应用的最佳实践和推荐模式。
不断增长的代码库问题
在不断增长的代码库中,可扩展性、可读性和整体代码质量往往会随着时间的推移而下降。这是由于代码库规模不断扩大,而维护人员没有采取积极措施来实施易于维护的结构而导致的。模块化是一种以改进可维护性和帮助避免这些问题的方式来构建代码库的方法。
什么是模块化?
模块化是一种将代码库组织成松散耦合且自包含的部分的做法。每个部分都是一个模块。每个模块都是独立的,并服务于明确的目的。通过将问题分解成更小、更容易解决的子问题,可以降低设计和维护大型系统的复杂性。
模块化的优势
模块化的优势很多,尽管它们都集中在提高代码库的可维护性和整体质量上。下表总结了主要优势。
优势 | 总结 |
---|---|
可重用性 | 模块化提供了代码共享和从同一基础构建多个应用的机会。模块实际上是构建块。应用应该是其功能的总和,其中功能被组织成单独的模块。特定模块提供的功能在特定应用中可能启用也可能不启用。例如,:feature:news 可以是完整版本风格和可穿戴应用的一部分,但不是演示版本风格的一部分。 |
严格的可见性控制 | 模块使您可以轻松控制向代码库其他部分公开的内容。您可以将除公共接口之外的所有内容标记为internal 或 private ,以防止在模块外部使用它。 |
可自定义的交付 | Play 功能交付 使用应用包的高级功能,允许您有条件地或按需交付应用的某些功能。 |
上述优势只有在模块化代码库中才能实现。以下优势可能可以通过其他技术实现,但模块化可以帮助您更有效地执行它们。
优势 | 总结 |
---|---|
可扩展性 | 在紧密耦合的代码库中,单个更改可能会触发代码看似无关部分的一系列更改。正确模块化的项目将采用关注点分离原则,从而限制耦合。这通过更大的自主权赋予了贡献者权力。 |
所有权 | 除了支持自主权外,模块还可以用于执行问责制。一个模块可以有一个专门的所有者,负责维护代码、修复错误、添加测试和审查更改。 |
封装 | 封装意味着代码的每个部分都应该对其他部分具有尽可能少的了解。隔离的代码更易于阅读和理解。 |
可测试性 | 可测试性描述了测试代码的难易程度。可测试的代码是指可以轻松隔离测试组件的代码。 |
构建时间 | 某些 Gradle 功能(例如增量构建、构建缓存或并行构建)可以利用模块化来提高构建性能。 |
常见陷阱
代码库的粒度是指它由模块组成的程度。更细粒度的代码库具有更多、更小的模块。在设计模块化代码库时,您应该确定粒度级别。为此,请考虑代码库的大小及其相对复杂性。粒度过细会使开销成为负担,而粒度过粗会降低模块化的优势。
一些常见的陷阱如下
- 粒度过细:每个模块都会带来一定量的开销,形式为构建复杂性和样板代码增加。复杂的构建配置使保持模块之间配置一致变得困难。过多的样板代码会导致难以维护的笨拙代码库。如果开销抵消了可扩展性改进,则应考虑合并某些模块。
- 粒度过粗:相反,如果模块变得太大,您最终可能会得到另一个单体,并错失模块化提供的优势。例如,在小型项目中,将数据层放在单个模块中是可以的。但随着它的增长,可能需要将存储库和数据源分离到独立的模块中。
- 过于复杂:并非总是需要将项目模块化。一个主要因素是代码库的大小。如果您预计项目不会超出某个阈值,则可扩展性和构建时间方面的收益将不适用。
模块化是否适合我?
如果您需要可重用性、严格的可见性控制或使用Play 功能交付带来的好处,那么模块化是必要的。如果您不需要这些好处,但仍然希望从改进的可扩展性、所有权、封装或构建时间中获益,那么模块化值得考虑。
示例
- Now in Android - 一个具有模块化功能的完整 Android 应用。
- 多模块架构示例