应用程序的体系结构定义了代码的组织方式以及各部分如何通信。一个好的架构有利于维护、测试和演进。糟糕的架构会产生技术债务,从而阻碍开发。本指南介绍了现代应用程序中使用的基本概念和模式。
为什么架构很重要
应用程序从小规模开始,然后不断发展。如果没有结构,代码就会变成一堆混乱的依赖关系。错误成倍增加,新功能需要时间,开发人员也会遭受损失。
良好架构的好处
- 更容易理解代码。
- 编写更简单的测试。
- 不破坏现有功能的新功能。
- 更快的开发人员入职。
- 更少的错误和返工。
糟糕架构的迹象
- 一个地方的变化会破坏其他地方。
- 测试很困难或不可能。
- 没有人理解整个代码。
- 重构似乎有风险。
- 随着时间的推移,发展速度会减慢。
基本原则
职责分离
每个模块必须有明确的职责。 UI 不应包含业务逻辑。数据访问不应与表示混合在一起。
依赖倒置
高层模块不应该依赖于低层模块。两者都必须依赖于抽象。这允许您交换实现而不影响其余部分。
单一事实来源
数据必须具有单一事实来源。避免不一致并简化数据流。
不变性
不可变的数据更具可预测性。减少与共享状态相关的错误。
架构模式
MVC(模型-视图-控制器)
分离数据(模型)、界面(视图)和协调逻辑(控制器)的经典模式。简单,但控制器在复杂的应用程序中往往会变得太大。
MVP(模型-视图-演示者)
View 是被动的,Presenter 包含表示逻辑。它有助于测试,因为 Presenter 不依赖于 UI。
MVVM(模型-视图-视图模型)
ViewModel 以反应方式向 View 公开数据。数据绑定将两者连接起来。在 Android(使用 ViewModel + LiveData/Flow)和 iOS(使用 SwiftUI/Combine)上很受欢迎。
MVI(模型-视图-意图)
单向流动。用户意图产生新的状态。单一、不可变的状态为视图提供支持。可预测且可测试。
干净的架构
具有向内依赖性的同心层。业务核心不知道框架或UI。最大的可测试性和灵活性。
公共层
表示层
UI 和表示逻辑。 ViewModel、演示者、可组合项、小部件。对状态变化做出反应并捕获用户意图。
域层
纯粹的业务逻辑。用例或交互器。它不知道 UI 或数据源。可重复使用且可单独测试。
数据层
访问 API、[数据库0 和缓存。抽象数据源的存储库。将外部模型映射到域模型。
Android 架构
喷气背包组件
视图模型、实时数据、房间、导航。促进推荐架构的官方组件。
Hilt 用于依赖注入
自动管理依赖关系。促进依赖倒置和测试。
推荐模式
UI层→领域层→数据层。 ViewModel 监视存储库中的数据。存储库结合了本地和远程源。
iOS 中的架构
SwiftUI + 组合
声明式和反应式。视图自动对状态变化做出反应。
带有 ObservableObject 的 MVVM
ViewModel 发布更改。查看观察和更新。逻辑和 UI 之间清晰分离。
协调员
默认导航。将流程逻辑与屏幕逻辑分开。
跨平台架构
颤动
有状态树小部件。用于状态管理的 BLoC 或 Riverpod。清洁架构非常适用。
反应本机
基于组件的钩子。 Redux 或 MobX 用于全局状态。依赖注入的上下文。
Kotlin 多平台
跨平台共享业务逻辑。每个上都有本机 UI。六边形架构效果很好。
状态管理
当地州
它属于单个组件。易于管理。
全局状态
在组件之间共享。需要 Redux、MobX、Provider、BLoC 等解决方案。
服务器状态
来自 API 的数据。缓存、加载、错误状态。 React Query 或 TanStack Query 等库可以提供帮助。
通信标准
回调
简单直接。可以在复杂的场景中创建回调地狱。
观察者/听众
解耦。组件观察变化而不知道是谁发出的。
事件总线
解耦的全球通信。如果过度使用它会使调试变得困难。
反应流
组件观察到的数据流。 RxJava、Kotlin Flow、组合、RxSwift。
模块化
按功能
每个模块都包含功能的所有内容:UI、域、数据。促进并行开发。
每层
用于表示、域和数据的独立模块。确保职责分离。
混合动力
将两者结合起来。功能模块依赖于共享层模块。
测试和架构
可测试性
良好的架构允许隔离测试。依赖注入使模拟变得更容易。
单元测试
他们单独测试业务逻辑。快速可靠。
集成测试
测试层之间的交互。验证完整的流程。
用户界面测试
测试用户界面。速度较慢,但验证真实体验。
架构文档
ADR(架构决策记录)
记录重要决定及其原因。帮助新成员和未来的决定。
图表
可视化层、模块和依赖关系。 C4 型号是一种流行的选择。
贡献指南
制定标准和惯例。每种类型的代码的放置位置。
架构的演变
增量重构
不要一次重写所有内容。在创造价值的同时逐步改进。
绞杀者图案
逐步更换系统的某些部分。新架构中的新代码,旧代码正在被删除。
功能标志
它们允许您以受控方式测试生产中的架构更改。
常见错误
过度设计
该问题的架构过于复杂。从简单开始,根据需要进行演变。
忽略架构
从一开始就没有结构。技术债务迅速积累。
复制而不理解
采用标准是因为它很时尚,但不了解权衡。每个环境都有不同的需求。
结论
应用架构是一项长期投资。从坚实的原则开始,选择适合上下文的模式,并随着产品的发展而发展。目标是今天可以运行并且明天仍然可以维护的代码。
##常见问题解答
1) 哪种架构最适合小型应用程序? 简单的MVVM就足够了。不要使用 MVP 的简洁架构使事情变得复杂。
2) 清洁架构值得吗? 对于寿命较长的中型和大型应用程序,是的。对于 MVP 来说,这可能有点过分了。
3) 如何从糟糕的架构迁移? 增量式。逐个模块地重构。扼杀者模式有帮助。
4) 我应该在 Android 和 iOS 上使用相同的模式吗? 不一定。每个平台都有自己的语言。原理是一样的。
5) 模块化总是必要的吗? 对于小型应用程序来说,没有。对于大型团队和复杂的应用程序来说,这是必不可少的。
另请阅读
- [应用后端:架构、技术和最佳实践1
- [应用中的微服务:移动分布式架构2
- [TypeScript 应用程序:TypeScript 开发指南3
- [React Native vs Flutter:完整比较4
- [应用程序中的缓存:良好实践和基础知识5
- [应用程序中的缓存:良好实践和基本步骤6
