Arquitectura limpia: ¿Utiliza diferentes classs de model para diferentes fonts de datos?

Actualmente estoy desarrollando una aplicación de Android para noticias. Intento diseñar mi aplicación de acuerdo con los principios de la architecture limpia.

En la capa de datos estoy usando el patrón de repository como una fachada para las diferentes fonts de datos: datos remotos de una API ( https://newsapi.org/ ), datos locales de una database (Realm o SQLite), así como algunos en -Memoria caching.
En mi capa de dominio he definido algunas classs de models inmutables (Artículo, NewsSource, etc.) que están siendo utilizados tanto por la capa de dominio como por la capa de presentación (no hay necesidad de classs model adicionales en la capa de presentación en mi opinión).

¿Tiene sentido utilizar diferentes classs de model para la fuente de datos remota así como también para la fuente de datos local?

Por ejemplo, la fuente de datos remota usa Retrofit para hacer llamadas a la API y los models deben ser anotados para que GSON los analice.

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

Los models para la fuente de datos local también pueden tener que cumplir ciertos contratos como models en un Realm DB que necesitan extender RealmObject.

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

Obviamente, no quiero que mis models de dominio estén 'contaminados' por ningún contrato específico de fuente de datos (annotations, inheritance de RealmObject, etc.). Así que pensé que tendría sentido usar diferentes models para diferentes fonts de datos y el repository maneja el mapeo entre ellos.

Por ejemplo, queremos recuperar todos los artículos de la API remota, almacenarlos en la database local y devolverlos a la capa de dominio.

El flujo sería como: la fuente de datos remota realiza una request http a la api de noticias y recupera una list de RemoteArticleModel . El repository mapearía estos models a un model de artículo específico del Dominio ( Article ). Luego, estos se RealmArticleModel models DB (por ejemplo, RealmArticleModel ) y se insertían en el DB. Finalmente, la list de Article se devolverá a la persona que llama.

Surgen dos preguntas: El ejemplo de arriba muestra cuántas asignaciones habría usando este enfoque. Para cada artículo que se va a download e insert en la database, se crearán tres models en ese process. ¿Sería eso exagerado?

Además, sé que la capa de datos debe usar diferentes classs de model que la capa de dominio (la capa interna no debería tener nada que ver con la capa externa). Pero, ¿qué sentido tendría eso en el ejemplo anterior? Ya tendría dos classs de models diferentes para las dos fonts de datos diferentes. Agregar un tercero que esté siendo utilizado como un model de 'mediador' por el data-layer / repository para manejar el mapeo a otros models (remoto, local, de dominio) agregaría aún más asignaciones.

Entonces, ¿la capa de datos no debería saber nada sobre los models de dominio y dejar que el dominio haga la asignación de un model de capa de datos a un model de capa de dominio?

¿Debería haber un model genérico utilizado solo por el repository / capa de datos?

Gracias, realmente agradezco la ayuda de desarrolladores más experimentados 🙂

El principio primordial que debe seguir es la separación de las preocupaciones.

La capa de persistencia debe tener classs que solo se ocupen del almacenamiento y recuperación de datos, en este caso las classs de Realm.

La capa de networking debe tener classs que traten con los datos del server, en este caso las classs de Retrofit.

Mover datos de cualquiera de esas capas a las capas de su empresa requiere que asigne los objects de persistencia y de networking a su dominio.

Para responder a su primera pregunta, el mapeo aísla alnetworkingedor de las diferentes preocupaciones, separando el dominio de las capas de datos. La capa de datos no debe conocer los models de dominio. El dominio solicita datos de la capa de datos, la capa de datos obtiene los datos y los pasa a través de un asignador y, por lo tanto, devuelve el model de dominio.

Para responder a su segunda pregunta, sería una violación de la separación de preocupaciones tener un model genérico para sus capas de datos si obtiene los datos de diferentes fonts. Los models de persistencia y los models de networking representan diferentes partes del sistema y, por lo tanto, deberían representarse mediante diferentes models. El dominio no necesita saber esto, por lo que los datos solicitados deben asignarse a objects de dominio antes de cruzar el límite de return al dominio.