Android app clean架构:数据层应该有自己的模型类吗?

时间:2017-12-20 10:22:02

标签: android kotlin clean-architecture data-layer

开发Android应用程序并尝试遵循干净的架构指南(但不是非常严格 - 因为对于较小的项目而言可能过度杀伤)时,最好的方法是什么。

在我的情况下,我不确定哪种方法最好(如果有最好的方法)关于 数据层,如果数据层应该在其上运行自己的模型类,或者它是否可以直接在域层模型上运行。

此外,如果数据层应该在自己的模型类上运行,那么DBAPI等数据源是否应该拥有自己的模型(例如API使用Retrofit }和Gson带有Gson注释的模型类,然后映射到数据层模型 OR ,如果数据层模型本身是DB返回的模型, API(这意味着必须为Gson注释数据层模型,以便RetrofitGson能够解析它。

此项目的情况如下: https://github.com/android10/Android-CleanArchitecture/blob/master/data/src/main/java/com/fernandocejas/android10/sample/data/entity/UserEntity.java

以下图片应阐明我所说的3种方法:

图片1 中,DBAPI会返回特定的模型类。对于API,它可能看起来像(使用RetrofitGson):

class ArticleResponse(@SerializedName("source") val source: SourceResponse,
                          @SerializedName("author") val author: String?,
                          @SerializedName("title") val title: String,
                          @SerializedName("description") val description: String?,
                          @SerializedName("url") val url: String,
                          @SerializedName("urlToImage") val urlToImage: String?,
                          @SerializedName("publishedAt") val publishedAt: String?)

然后,本地/远程数据源将这些映射到Article模型(域层使用)。因此,存储库在域层模型上运行并正在打破边界吗?这是方法1。 Image1

图片2 中,DBAPI仍会返回特定的模型类。对于API,它可能看起来像(使用RetrofitGson):

class ArticleResponse(@SerializedName("source") val source: SourceResponse,
                              @SerializedName("author") val author: String?,
                              @SerializedName("title") val title: String,
                              @SerializedName("description") val description: String?,
                              @SerializedName("url") val url: String,
                              @SerializedName("urlToImage") val urlToImage: String?,
                              @SerializedName("publishedAt") val publishedAt: String?)

然而,这些模型然后被映射到数据层操作的数据层模型(ArticleEntity)。在回复域层时,repository会将这些ArticleEntity映射到域层模型Article。这不会破坏边界(右)但需要在数据层中添加一些额外的映射。这是方法2.

enter image description here

图片3 中,DBAPI已经返回数据层模型ArticleEntity。因此,此模型类必须包含解析API请求所需的所有注释(使用Gson):

class ArticleEntity(@SerializedName("source") val source: SourceResponse,
                                  @SerializedName("author") val author: String?,
                                  @SerializedName("title") val title: String,
                                  @SerializedName("description") val description: String?,
                                  @SerializedName("url") val url: String,
                                  @SerializedName("urlToImage") val urlToImage: String?,
                                  @SerializedName("publishedAt") val publishedAt: String?)

如果DB也需要某种注释,那么这些注释也必须添加到这个类中(对吗?)。我能想到的这种方法的一个优点是模型类较少(因为DB和API直接映射到数据层模型)。但是,这不会使来自所有不同数据源(DB,API)的注释/属性炸毁数据层模型类吗?因为数据层模型依赖于特定的数据源实现(例如使用Gson来解析具有确切API响应名称的API请求),是不是从存储库中抽象数据源的全部内容都是违反的。所以这就是方法3。

enter image description here

我的问题是:这3种方法中哪一项最具灵活性和面向未来的方法?

1 个答案:

答案 0 :(得分:2)

如果我是你,我会选择Image1流程。我认为您的数据源的工作是从您的数据库或API或您拥有的任何端点获取任何对象,并将其转换为更容易在存储库中使用的内容。

在Image1和Image2之间,我认为它取决于您要存储的数据以及要存储的对象。根据您的业务规则,您可能需要也可能不需要ArticleEntity。如果你不需要它,你就不必创建它。

但是对于某些用例,您可能需要创建该对象以向您的文章添加一些信息。例如,如果您想要放置有效日期或仅在存储库中使用的任何其他信息,则可以使用Image2。