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

Eli*_*as 8 android repository-pattern kotlin clean-architecture

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

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

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

例如,远程数据源使用Retrofit进行API调用,并且需要对模型进行注释以便由GSON进行解析.

data class RemoteArticleModel(
        @SerializedName("title") val title: String,
        @SerializedName("urlToImage") val urlToImage: String,
        @SerializedName("url") val url: String)
Run Code Online (Sandbox Code Playgroud)

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

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

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

例如,我们希望从远程API获取所有文章,将它们存储在本地数据库中并将它们返回到域层.

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

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

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

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

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

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

Bri*_*ian 11

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

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

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

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

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

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

  • 最干净的方法是为要通过边界传输的每个对象都有一个单独的映射器。这样,您就可以实现单一职责,即,映射器将负责将数据对象转换为域对象。数据类只担心它代表的数据 (3认同)