整洁的架构:对不同的数据源使用不同的模型 类?

Clean Architecture: Use different model classes for different data sources?

我目前正在开发新闻提要 android 应用程序。我尝试根据干净架构的原则设计我的应用程序。

在数据层中,我使用存储库模式作为不同数据源的外观:来自 API (https://newsapi.org/) 的远程数据,来自数据库(Realm 或 SQLite)的本地数据) 以及一些内存缓存。
在我的域层中,我定义了一些不可变模型 类(文章、新闻源等),它们被域层和表示层使用(不需要额外的模型 类我认为表示层)。

对远程数据源和本地数据源使用不同的模型类有意义吗?

例如远程数据源使用 Retrofit 进行 API 调用,模型需要注释才能被 GSON 解析。

data class RemoteArticleModel(
        @SerializedName("title") val title: String,
        @SerializedName("urlToImage") val urlToImage: String,
        @SerializedName("url") val url: String)

本地数据源的模型也可能必须满足某些特定的契约,例如 Realm DB 中的模型需要扩展 RealmObject。

open class Dog : RealmObject() {
    var name: String? = null
    @LinkingObjects("dog")
    val owners: RealmResults<Person>? = null
}

显然,我不希望我的领域模型 'polluted' 受到任何数据源特定契约(注释、RealmObject 继承等)的约束。所以我认为对不同的数据源使用不同的模型是有意义的,存储库处理它们之间的映射。

例如我们想从远程 API 获取所有文章,将它们存储在本地数据库中并 return 到领域层。

流程如下: 远程数据源向新闻 api 发出 http 请求并检索 RemoteArticleModel 的列表。存储库会将这些模型映射到特定领域的文章模型 (Article)。然后这些将被映射到数据库模型(例如 RealmArticleModel)并插入到数据库中。最后 Article 的列表将 returned 给调用者。

出现两个问题: 上面的例子显示了如何使用这种方法许多分配。 对于将要下载并插入数据库的每篇文章,将在该过程中创建三个模型。那会不会太过分了?

此外,我知道数据层应该使用与域层不同的模型 类(内层不应该与外层无关)。但是在上面的例子中这有什么意义。对于两个不同的数据源,我已经有了两个不同的模型 类。添加第三个被 data-layer/repository 用作 'mediator' 模型以处理到其他模型(远程、本地、域)的映射将增加更多分配。

那么数据层是否应该对领域模型一无所知,让领域做数据层模型到领域层模型的映射?

是否应该有一个仅供 repository/data-layer 使用的通用模型?

谢谢,非常感谢经验丰富的开发人员提供的任何帮助:)

您应该遵循的首要原则是关注点分离。

持久层应该 类 只处理数据的存储和检索,在本例中是领域 类。

网络层应该有 类 来处理来自服务器的数据,在本例中是 Retrofit 类。

将数据从任何这些层移动到您的业务层需要您将持久性和网络对象映射到您的域。

为了回答您的第一个问题,映射隔离围绕着不同的关注点,将域与数据层分开。数据层不应该知道领域模型。域从数据层请求数据,数据层获取数据并通过映射器传递数据,从而 returns 域模型。

回答你的第二个问题,如果你从不同的来源获取数据,那么为你的数据层使用通用模型将违反关注点分离。持久性模型和网络模型代表系统的不同部分,因此应该用不同的模型来表示。域不需要知道这一点,因此请求的数据应该在跨越边界返回域之前映射到域对象。

添加到@Brian 的答案中,您可能可以按照 Clean Boilerplate 中的建议添加或封装数据层:

这样你就有了一个通用的数据模型,它映射到领域模型。我不太确定这是否会添加不必要的代码和层,因为这样数据和域模型可能看起来几乎相同。