SoC(Separation of Concerns)是一项原则的缩写,根据该原则,软件系统被划分为独立的职责领域。根据Martin Fowler的观点,职责分离是可维护代码的关键要素。SoC原则允许开发人员更改应用程序的一个层而不影响其他层,这在团队移动开发中尤为重要。
要点
SoC是Separation of Concerns的缩写,意为"职责分离"或"关注点分离"。在编程上下文中,concern一词指任何可分离的功能:用户界面显示、点击处理、数据验证、网络通信或数据库操作。SoC原则要求围绕这些领域对代码进行分组,以便一个领域的更改不会影响其他领域。
SoC缩写广泛应用于技术文献、架构讨论和框架文档中。例如,在Android Architecture Components文档中,多次提到SoC作为分离ViewModel和View的动机。在iOS社区中,该术语用于讨论Massive View Controller问题——缺乏SoC的直接后果。
重要的是要理解SoC不是一次性操作,而是一个持续的过程。随着应用程序的增长,出现新的职责领域,架构需要重新审视。一个良好的代码库在达到每个concern都隔离且可管理的稳定状态之前,会经历多次划分迭代。
Separation of Concerns及其缩写SoC表示同一原则。区别仅在于使用上下文:全名用于正式文档、教育材料以及首次向新开发人员解释概念时。SoC在技术讨论、代码审查和需要简洁的文档中更方便。
在专业环境中,这两个术语可以互换使用。开发人员可以说"这里违反了SoC"或"这违反了Separation of Concerns"——含义不变。然而,在招聘信息和架构要求中,全名更常见,而在聊天和代码审查中——缩写。了解这两种变体对于顺利进入行业是必要的。
存在术语混淆:SoC缩写也用于硬件上下文中的System-on-a-Chip(片上系统)。在移动开发中,上下文总是从环境中明确的——如果讨论涉及代码架构,则指的是Separation of Concerns。在本文中,SoC始终指职责分离原则。
三层架构 — 在移动应用中实现SoC的最常见方式。它将代码分为Presentation(UI)、Domain(业务逻辑)和Data(与数据源交互)。每一层包含严格定义的类型类,并通过接口与相邻层隔离。这种方法对iOS、Android和Flutter项目同样有效。
View和ViewModel构成表示层。View负责渲染界面和传递用户事件。ViewModel存储屏幕状态并将来自Domain层的数据转换为准备显示的格式。ViewModel没有对Activity、Fragment或UIViewController的引用——这确保了UI和逻辑之间的SoC。
例如,在Android Jetpack中,ViewModel在屏幕旋转后依然存在,而UI被重新创建。没有SoC,我们将不得不在Activity中存储状态,将生命周期管理与数据混合。ViewModel独立解决这个任务,展示了职责分离原则的纯粹实现。
Use Cases包含独立于平台的业务规则。这一层不导入Android SDK、iOS UIKit或Flutter框架。Use Case从Repository接收数据,对其应用业务逻辑,并返回结果。得益于SoC,一个Use Case可以在不同屏幕和平台上重复使用。
经典例子 — 注册表单的ValidateAndSaveUseCase。它检查电子邮件和密码的正确性,调用UserRepository进行保存,并返回ValidationResult。UI和数据库都不知道验证规则——它们集中在一个地方,便于修改。
Repository将数据源与应用程序的其余部分抽象开来。ViewModel不知道数据来自哪里——REST API、GraphQL、本地数据库或缓存。Repository决定使用哪个源,并将此逻辑隐藏在接口后面。这是数据获取和消费之间的SoC。
DataSource提供更深入的分离:RemoteDataSource仅负责HTTP请求,LocalDataSource负责与Room、CoreData或SharedPreferences交互。Repository组合它们并应用缓存策略。每个DataSource可以独立替换,这在服务器或数据库之间迁移时至关重要。
这种多层次的DataSource系统在基础设施层面实现了SoC:网络通信、本地存储和缓存——独立的concerns,每个都有自己的逻辑和生命周期。更换HTTP客户端时,只有RemoteDataSource发生变化,而Repository和更高层保持不变,这证实了职责分离的实践价值。
MVP(Model-View-Presenter)— 最早在移动开发中明确实现SoC的模式之一。Presenter包含逻辑并通过接口管理View。View是被动的——只显示Presenter所说的内容。分离简化了测试:Presenter可以在没有模拟器的情况下测试,而View保持简单以至于不会出错。
MVVM添加了响应式绑定:View通过Observable或StateFlow订阅ViewModel的更改。ViewModel不保留对View的引用,消除了内存泄漏的风险,并更强地分离了concerns。在Android中,MVVM通过Jetpack ViewModel和LiveData成为标准,在iOS中——通过Combine和RxSwift。
Clean Architecture(整洁架构)由Robert Martin提出,将SoC推向环的彻底分离。外环(框架和驱动程序)依赖于内环(实体),但反之则不然。在实践中,移动项目很少实现所有四个环——Presentation周围的Domain和Data层就足够了。但"向内"依赖原则本身在更换框架时提供了显著优势。
// View — 仅显示,不含逻辑
final class LoginViewController: UIViewController {
let viewModel: LoginViewModel
func loginTapped() {
viewModel.login(emailField.text, passwordField.text)
}
}
// ViewModel — 包含屏幕逻辑,不依赖UIKit
final class LoginViewModel {
private let loginUseCase: LoginUseCase
func login(email: String?, password: String?) {
loginUseCase.execute(email, password)
}
}
// Use Case — 业务逻辑,不依赖平台
final class LoginUseCase {
private let repo: AuthRepository
func execute(email: String?, password: String?) {
guard let e = email, let p = password else { return }
repo.authenticate(e, p)
}
}
示例展示了三个SoC层次:LoginViewController仅传递事件,LoginViewModel管理状态,LoginUseCase包含业务规则。每个类都独立测试,更换UI框架不会影响Use Case。
Massive View Controller — iOS中最常见的SoC违反。一个管理UI、处理网络请求、解析JSON和存储数据的类在所有层面上都违反了原则。解决方案——将每个职责提取到单独组件中:NetworkingService、JSONParser、CoreDataStack,只给ViewController留下View管理。
在Android中有类似问题——God Activity或God Fragment。一个Activity加载数据、验证表单、显示对话框和更新UI。通过引入ViewModel和Repository来治疗,它们接管状态和数据管理。ViewModel还能防止屏幕旋转时的数据丢失。
第三个违反——混合平台和业务代码。例如,将HTTP请求直接放在SwiftUI View或Android Composable中。这使代码不可移植且难以测试。正确的方法——将请求提取到Repository,通过Use Case调用,View只订阅结果。系统的每个元素解决自己的任务,不超出其边界。
常见问题
不。SoC是将系统划分为职责领域的更通用原则。SOLID是面向对象设计的五个具体规则集。SOLID的第一个原则(单一职责)是SoC在单个类层面上的特殊情况。
使用单一变更原因规则(单一职责)。如果一个类因UI更改、数据格式更改和业务规则更改而发生变化——则SoC被违反。ArchTest(Android)和StrictConcurrency(iOS)等工具有助于自动检测此类违反。
理论上,额外的层次增加间接调用,但在实践中,对移动应用性能的影响可以忽略不计。编译器内联许多调用,JIT和AOT优化消除了开销。代码的可维护性获得的收益远大于在抽象上损失的部分。
从将网络请求从UI提取到Repository开始。然后将业务逻辑分离到Use Cases中。使用依赖注入来连接各层。迭代地进行更改,用测试覆盖新代码——这保证了重构不会破坏现有功能。
在原型中,为了速度可以违反SoC。但如果原型转入产品开发,重构成本可能超过快速启动的好处。最佳做法——即使在原型中也保持最小分离(UI和数据),以免在启动时需要重写所有内容。
总结
我们将开发一款交钥匙移动应用程序
IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。