Clean Architecture中数据源选择逻辑实现:Domain还是Data层?
Clean Architecture下的数据源选择逻辑与Repository职责划分
最优架构方案
按照Clean Architecture的分层职责原则,数据源选择逻辑应放在Data层的Repository实现中,具体组织方式如下:
1. Domain层定义抽象与业务逻辑
- 定义
UserRepository接口:仅暴露业务所需的方法(如fun getUserContacts(): Flow<List<Contact>>),完全屏蔽数据源细节。 GetUserContactsUseCase依赖UserRepository接口,专注处理业务逻辑(比如对返回的联系人数据做业务规则过滤、转换等),不参与任何数据源的选择判断。
2. Data层实现数据获取策略
- 拆分单一职责的数据源:
LocalContactDataSource:负责本地联系人数据的读写RemoteContactDataSource:负责从API获取联系人数据UserPreferenceDataSource:负责读取用户的数据源偏好配置
- 实现
UserRepositoryImpl,依赖上述三个数据源:
在getUserContacts()方法内,根据UserPreferenceDataSource获取的配置,判断优先加载本地还是远程数据;同时可扩展实现 fallback 逻辑(比如本地数据为空时自动请求远程)、缓存同步(比如远程数据返回后更新本地缓存)。这部分逻辑属于数据获取策略,是Data层的核心职责,完全封装在Repository实现内部,对Domain层透明。
对两种方案的问题分析
- 方案1:UseCase直接访问具体数据源,违反了Clean Architecture的依赖倒置原则,导致Domain层与Data层耦合,无法灵活替换数据源(比如切换远程API或本地存储方式),同时也违背了Repository的封装职责。
- 方案2:误解了业务逻辑与数据策略的边界。数据源选择属于“如何获取数据”的实现细节,而非业务规则(业务规则是“展示符合用户需求的联系人”),因此放在Data层的Repository实现中是合理的,不存在“侵入业务逻辑”的问题。
Repository职责拆分建议
你的怀疑是正确的,应该拆分单一职责的数据源实例:
- 避免使用单一的
LocalPreferences处理所有本地数据,而是拆分为LocalContactDataSource(联系人数据)、UserPreferenceDataSource(配置偏好)等独立类,每个类只负责一类数据的读写,符合单一职责原则,提升代码的可维护性和可测试性。
内容的提问来源于stack exchange,提问作者Oleksii Kolotylenko
相关产品推荐
相关产品推荐

