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

时间:2017-08-24 13:13:05

标签: android kotlin repository-pattern clean-architecture

我目前正在开发一个新闻Feed Android应用。我尝试按照干净的架构原则设计我的应用程序。

在数据层中,我使用存储库模式作为不同数据源的外观:来自API(https://newsapi.org/)的远程数据,来自数据库(Realm或SQLite)的本地数据以及一些来自-memory cache。
在我的域层中,我定义了一些不可变的模型类(Article,NewsSource等),它们由域层和表示层使用(在我看来,表示层中不需要额外的模型类)。

对远程数据源以及本地数据源使用不同的模型类是否有意义?

E.g。远程数据源使用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
}

显然,我不希望我的域模型被任何特定于数据源的契约(注释,RealmObject继承等)“污染”。所以我认为为不同的数据源使用不同的模型是有意义的,并且存储库处理它们之间的映射。

E.g。我们想要从远程API获取所有文章,将它们存储在本地数据库中并将它们返回到域层。

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

出现两个问题: 上面的示例显示了如何使用此方法进行许多分配。 对于要下载并插入数据库的每篇文章,将在该过程中创建三个模型。那会有点矫枉过正吗?

另外,我知道数据层应该使用与域层不同的模型类(内层应该没有关于外层的任何内容)。但是在上面的例子中,这有什么意义呢?我已经有两个不同的模型类用于两个不同的数据源。添加第三个被数据层/存储库用作“中介”模型以处理到其他模型(远程,本地,域)的映射将增加更多的分配。

那么,数据层应该对域模型一无所知,让域从数据层模型到域层模型进行映射吗?

是否应该只使用存储库/数据层的通用模型?

谢谢,非常感谢更有经验的开发人员的帮助:)

2 个答案:

答案 0 :(得分:9)

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

持久层应具有仅处理数据存储和检索的类,在本例中为Realm类。

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

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

为了回答您的第一个问题,映射绝缘解决了不同的问题,将域与数据层分开。数据层不应该知道域模型。域从数据层请求数据,数据层获取数据并通过映射器传递,从而返回域模型。

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

答案 1 :(得分:0)

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

data layer with remote and local

通过这种方式,您可以将通用的数据模型映射到域模型。我不太确定这是否会添加不必要的代码和层,因为那样的话,数据和域模型可能看起来几乎相同。