Un Flutter Más Limpio Vol. 7: De dónde vienen los datos
En serio, ¿quién rayos los trae?
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).
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.
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
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.
RemoteDataSource
Hay paquetes que nos facilitan mucho más la estructuración de nuestro código y 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.
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
:
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:
Esa es una de las formas en las que nuestros DataSources son mejores utilizados.
Y por cierto… ¡que la fuerza los acompañe!
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.
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.
Originally published at http://github.com.