Android 应用程序干净架构:数据层是否应该有自己的模型类?

Eli*_*as 6 android data-layer kotlin clean-architecture

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

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

此外,如果数据层应该在自己的模型类上运行,数据源是否应该像DBAPI拥有自己的模型(例如用于API使用RetrofitGson带有Gson注释的模型类),然后映射到数据层模型,或者数据层模型本身应该是DBand返回的模型API(这意味着必须对数据层模型进行注释,以便Gson能够在Retrofitand 的情况下解析它Gson)。

这个项目就是这种情况: 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?)
Run Code Online (Sandbox Code Playgroud)

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

图 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?)
Run Code Online (Sandbox Code Playgroud)

然而,这些模型随后被映射到数据层模型(ArticleEntity),数据层在该模型上进行操作。当响应领域层时,repository将这些映射ArticleEntity到领域层模型Article。这不会打破边界(正确),但它需要在数据层中进行一些额外的映射。这是方法2。

在此处输入图片说明

图 3DBAPI已经返回数据层模型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?)
Run Code Online (Sandbox Code Playgroud)

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

在此处输入图片说明

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

小智 4

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

在Image1和Image2之间,我认为这取决于你想要存储什么数据以及你想要存储的对象是什么。您可能需要也可能不需要 ArticleEntity,具体取决于您的业务规则。如果您不需要它,则不必创建一个。

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