我正在尝试根据干净的架构正确设计应用程序,但我很难确定在哪一层(数据/域)上实现某些逻辑。在我的应用程序中,有一个功能可以显示数据(用户联系人),这些数据可以在设置中本地设置,也可以通过 API 检索。向用户显示哪个版本取决于其他设置和应用程序的使用模式,例如API返回数据,但用户在应用程序的设置中设置了使用本地数据的首选项。选择数据源的逻辑应该在哪一层实现?
假设域中有一个 GetUserContactsUseCase。 那么,据我了解,有以下几种方法:
方法1
UserRepository,包含 2 个来源:
LocalData - 包含所有本地设置,例如联系人数据和优先级设置。
RemoteData - 从 API 加载和缓存数据。
GetUserContactsUseCase 访问 RemoteData 和 LocalData(显然需要重命名为 RemoteDataRepository 和 LocalDataRepository),确定优先级,然后从中获取数据。该解决方案的缺点是存储库似乎应该确定数据源本身。
方法2
UserRepository 独立决定优先级。这保持了层的封装,但在这种情况下,UserRepository 包含的业务逻辑似乎应该位于 UseCase 中,而不是存储库中。也不可能从存储库调用用例。一种解决方案似乎是编写一个单独的 UseCase 来确定 UserContacts 的来源并将其结果(例如 UserContactFetchMode)传递给 UserRepository。这个用例仍然会回到方法 1,因为它需要相同的 LocalData 和 RemoteData。
问题: 请建议组织此活动的最佳方式。
我不确定这是否与我的问题相关,但我怀疑存储库本身之间的功能分配级别存在一些混乱,例如,可能需要创建多个实例,而不是单个 LocalPreferences,如 LocalUserData、LocalPreferencesData 等
确定信息来源是业务逻辑,而不是数据访问逻辑。逻辑不属于存储库,它属于用例。您的存储库可能返回相同的模型,甚至实现相同的接口,但它需要可选择的事实意味着您涉及属于用例的业务逻辑。
通过将选择逻辑移至用例,您可以让存储库保持沉默,只关心与其数据存储的通信。
这种“感觉”是错误的,因为它看起来像是一个关注点分离问题,但事实并非如此。它们是不同的关注点,因为它们具有在它们之间切换的业务逻辑。放入 RemoteUserContactsData 和 LocalUserContactsData 的接口并将切换推入 UseCase 中,这将变得相当明显。