Skip to content

Instantly share code, notes, and snippets.

@marcossevilla
Created May 4, 2021 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcossevilla/71e63d9e4708530265496d0127e6b7c0 to your computer and use it in GitHub Desktop.
Save marcossevilla/71e63d9e4708530265496d0127e6b7c0 to your computer and use it in GitHub Desktop.

Vol. 7: De dónde vienen los datos

Bienvenidos y bienvenidas a un volumen más de Un Flutter Más Limpio. Sé que habíamos dejado un poco inconclusos los últimos volúmenes pero vamos a hacer el esfuerzo de terminar todos los artículos restantes este mes.

Sin más que mencionar, vamos al lío.

Dónde nos quedamos

El volumen anterior empezaba con nuestra capa de datos, una capa donde implementamos todas las acciones descritas en la capa de dominio para poder interactuar con un servicio externo, o bien, un servicio local (alguna base de datos en el dispositivos o contacto con el hardware donde corremos).

Vol%207%20De%20do%CC%81nde%20vienen%20los%20datos%204b2a5dadea0b4d1986649d3f5f92ee6a/data.png

Como dice el título, vamos a hablar de dónde vienen los datos. Ya tenemos nuestros modelos donde nosotros establecemos qué datos vamos a ocupar, ahora tenemos que ir a traerlos.

Nosotros les decimos DataSource a las clases que van a traernos los datos "en bruto", convertirlos en los modelos respectivos y pasarlos a su repositorio. Pero igualmente hay otras nomenclaturas, como en la biblioteca Bloc, se les llama DataProvider.

Ustedes pueden llamarle de la manera que les parezca mejor, me parece que el nombre DataProvider quedaría mejor si se crearan Providers de estas clases.

Ya que en Riverpod no creamos Providers para los DataSources, el nombre me basta.

Más de este uso en el artículo sobre lógica de negocio.

La fuente de los datos

Para definir qué es un DataSource, voy a tomar prestado el concepto de DataProvider de bloclibrary.dev...

Proveen los datos puros, deben ser genéricos y versátiles. Se caracterizan por exponer métodos de CRUD.

bloclibrary.dev

Cuando yo utilizo DataSources los separo en dos carpetas: local y remote. Esto porque los DataSources son cualquier vía para traer información, que como mencioné antes puede ser en el mismo dispositivo o bien a un API externo donde tengamos que usar HTTP o algún otro protocolo de internet.

Vol%207%20De%20do%CC%81nde%20vienen%20los%20datos%204b2a5dadea0b4d1986649d3f5f92ee6a/carbon.png

Una duda común es el por qué no usamos los repositorios para hacer todo lo que hace el DataSource. Principalmente porque hay muchas posibles acciones que se efectúen con los datos que nosotros queremos traer.

Un caso que me pasa bastante seguido es que quiero guardar algún dato en una base de datos local (mi opción preferida es hive) y el dato lo traigo de un API REST. La acción de guardar en el dispositivo y la acción del llamado al API son dos funciones distintas. Además de ser dos acciones que se ejecutan en dos fuentes de datos distintas.

Dado lo anterior, mi repositorio se encarga de establecer este flujo con dos fuentes de datos distintas y encargarse de manejar los datos que devuelven varias fuentes de datos y posteriormente comunicarle ese resultado a la lógica de negocio.

Implementando un DataSource

LocalDataSource

https://gist.github.com/b7b982ff771b2179018e95c175de8aa4

Así se ve un DataSource a nivel local. Esta estructura la reutilizo para guardar únicos valores en una Box de Hive, que es el equivalente a una tabla en SQL.

Siempre recomiendo que toda clase a la que vayan a hacerle pruebas le hagan una clase abstracta, así les resulta más fácil hacer sus Mocks con paquetes como Mocktail.

De igual manera, definan las dependencias que van a usar como propiedades de la clase para sólo proveerle un objeto con el cual puede efectuar las acciones que necesite. Este último punto lo vamos a ver más a detalle en el RemoteDataSource.

https://media.giphy.com/media/3orieNQgdcxedKjA3e/giphy.gif

RemoteDataSource

https://gist.github.com/a9862788f9e2f5f9820e0a2cdc1b2580

Hay paquetes que nos facilitan mucho más la estructuración de nuestro código y [dio](https://pub.dev/packages/dio) es uno de ellos. Tengo un artículo sobre Dio por acá, por si te gustaría saber más sobre los beneficios que nos trae y sus capacidades.

Es una estructura muy similar a la del LocalDataSource. Tenemos un patrón de inyección de dependencias donde igual definimos las dependencias como propiedades y pasamos una instancia a nuestra propiedad privada. Todo igual.

La diferencia radica en la implementación de cómo obtenemos los datos, uno accede a la base de datos en Hive y el otro va a un API remoto a tomar estos datos mediante Dio (HTTP).

Otras implementaciones

Para ambos tipos de DataSources, podemos tener diferentes implementaciones por lo que hacemos una interfaz que podemos implementar y definir el cuerpo de los métodos que vamos a usar.

https://gist.github.com/c9d5c5d81a887e428310d711d7684140

Esta otra implementación utiliza el paquete http oficial de Dart y podemos ver que el resultado será el mismo, sólo que con una distinta forma de hacerlo con otro paquete.

Hay 2 grandes ventajas que nos brinda el paquete de Dio comparado a HTTP. Una es la decodificación de nuestra respuesta de una cadena JSON pura a un Map<String, dynamic> de Dart. La otra la vemos en el siguiente punto.

Reusando código

Como han logrado ver desde artículos anteriores, CleanScope se enfoca en desarrollar un proyecto basado en features específicos. Abstrayendo nuestra lógica de datos en DataSources y Repositories podemos llegar a una estructura que, combinada con Dio, es muy ordenada.

El siguiente ejemplo es siguiendo cómo se vería la creación de nuestra capa de datos a ser usada como dependencia para nuestro proyecto utilizando **flutter_bloc**:

https://gist.github.com/18dc465c0d602eb5509a7233447396a1

En el siguiente artículo vamos a entrar en detalle en cómo se ve el repositorio ya implementado, pero por el momento sabemos que recibe como propiedades sus 2 DataSources.

Dio nos permite reutilizar instancias de sus clientes con configuraciones específicas para que hagamos llamadas directas a endpoints sin especificar una URL base. Este funcionamiento lo podemos ver en el GET del RemoteDataSource que construí anteriormente con Dio:

https://gist.github.com/5a65fc9e97f1c08fecc357887a60cd01

Esa es una de las formas en las que nuestros DataSources son mejores utilizados.

Y por cierto... ¡que la fuerza los acompañe!

https://media.giphy.com/media/3o6EhVAZfcTUdGMHq8/giphy.gif

Lo de siempre...

Si aprendiste algo nuevo y te fue de utilidad, podés compartir este artículo para ayudar a otro/a desarrollador(a) a seguir mejorando su productividad y calidad al escribir aplicaciones con Flutter.

También hay una versión de este mismo artículo en inglés publicado en dev.to. De nada. 🇺🇸

Además, si te gustó este contenido, podés encontrar aún más y seguir en contacto conmigo en mis redes sociales:

  • dev.to - donde publico versiones en inglés de mis artículos.
  • GitHub - donde están mis repositorios de código, por si te gustan los ejemplos.
  • LinkedIn - donde conecto profesionalmente.
  • Medium - donde estás leyendo este artículo.
  • Twitter - donde expreso mis ideas cortas y comparto mi contenido.
  • Twitch - donde hago directos informales de los que saco clips con información puntual.
  • YouTube - donde publico los clips que salen de mis directos.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment