Clean Arquitecture: Mi visión en Flutter (1/2).

Clean Arquitecture... Hoy en día son muchos los programadores que necesitan implementar los conceptos de esta arquitectura, bien por que les gusta, bien por que les obligan 😉, por ello quiero dar mi visión de cómo utilizarla en Flutter, hablaré de los motivos y el por qué y daré unos ejemplos prácticos. Por supuesto no pretendo explicar qué es o qué ventajas o inconvenientes tiene, eso se lo dejo a los que les gusta comparar arquitecturas.

Clean Arquitecture (CA)

CA se suele representar con un círculo para indicar el aislamiento de las distintas capas y cómo que cada una de ellas sólo ve la superior


Ahora bien, en las propias palabras de clean coder - uncle bob estos círculos hay que tomarlos como un esquema, no son las tablas de la ley, pueden ser más o pueden ser menos. Lo que es realmente importante es que cumplan las Reglas de Dependencia, esto es que cuanto más en el exterior la implementación es más concreta y cuando vamos al centro ha de ser más abstracta y no podemos acceder a capas que no sean adyacentes.

Por lo tanto podemos adaptar la CA a Flutter y determinar los conceptos que utilizaremos.

Déjenme proponerles una visión inicial

Como se puede ver es una simple adaptación de la imagen anterior, donde las diferentes capas aíslan unas de otras, teniendo este esquema en mente, veamos su explicación:

Proveedores

Es la capa más externa y por lo tanto es la encargada de las acciones físicas y la más especializada, por ejemplo de acceder a una b.d. local, o bien de recuperar información de un api. Puede haber tantos proveedores como sean necesarios pero cada proveedor interactuará solamente con un elemento externo. Por ejemplo si tenemos que acceder a distintos servidores de api cada uno de ellos los utilizaremos desde su propio proveedor.

Los proveedores suelen ser un número muy determinado y concreto.

Repositorio

Esta pieza aísla a los controladores del conocimientos de los proveedores. Así los controladores no saben cuantos hay ni qué hacen los proveedores. De esta manera si en algún momento la estructura de los proveedores cambia, por ejemplo se aglutinan todos los apis en un único servidor y ya no hay dos o tres sino uno, podemos cambiar la parte física y solo quedara afectado el repositorio, evitando que tengamos que modificar todos los controladores que hayan usado alguna llamada al proveedor.

El repositorio es único.

Controladores

Los controladores son los que manejan las llamadas al repositorio y gestionan los estados de dicha comunicación notificándolos a la capa de UI. Además los controladores manejan los datos a nivel de la necesidades de negocio, siendo los responsables de generar los datos tal y como los va ha necesitar la capa de UI en Flutter.

Dicho en general los controladores son los responsables de la lógica de negocio y están fuertemente ligados a la capa de UI.

En flutter los controladores y la capa de UI al estar fuertemente ligados, es difícil distinguir quien es el responsable de alguna acción, por ejemplo la navegación, que es el caso más controvertido, ya que para algunos el conocimiento de la navegación es parte de la lógica de negocio, pero en cambio otros autores  (de Flutter) determinan que se debe de usar exclusivamente en la parte de UI, normalmente argumentado que sino esto puede suponer problemas a la hora de hacer pruebas unitarias.

Yo en este caso utilizo ambos, en función de las necesidades o de donde ocurra el evento, si es un botón, por ejemplo de ir a registro, pues lo pongo en su onTap, pero si en una llamada a un controlador veo que como resultado tengo que navegar puede ser que haga la llamada en el propio controlador. Por supuesto esto es por que estoy usando GetX, sino, si hago navegación con contexto, tengo que hacerlo siempre en el UI .

Controladores puede haber tantos como necesidades haya, normalmente hay muchos más que proveedores.

UI

Interfaz de usuario, son las paginas y componentes visuales que nuestra aplicación maneja. Invoca a los controladores y recibe sus eventos para reflejar de cara al usuario lo que esté aconteciendo.

Son nuestros elementos más numerosos.

El repositorio, la manzana de la discordia

Esto igual levanta algunas ampollas, pero... 

En este esquema el repositorio puede ser un poco controvertido, nos podemos preguntar ¿Realmente es necesario tener un repositorio? Bueno, a mi entender, un repositorio sólo tiene sentido cuando existen varios proveedores y existe una mínima posibilidad de que puedan cambiar a futuro.

En la realidad tendremos uno o dos y no van a cambiar a lo largo de la aplicación, o sea, que no se van a segmentar o a unir.

Tengamos en cuenta que estas arquitecturas están pensadas para aplicaciones grandes  sobre todo, y yo, siguiendo la máxima KISS (keep it simple stupid) "Mantén todo simple estupi..." recomiendo no usar el repositorio cuando la aplicación no lo requiera, por ejemplo cuando tengamos un único proveedor (v.g. de api), ya que literalmente es un desperdicio de tiempo y de llamadas a métodos complicando el desarrollo y por ende el mantenimiento.

Así la arquitectura quedaría:



Implantando la arquitectura

Esta arquitectura le corresponde un modelo de directorios, puede haber diversas opciones, hay a quien le gusta tener muchos directorios con mucha profundidad, pero a mí, personalmente si algo no se usa, mejor no ponerlo (recordad lo del KISS).

Los directorios los pondré en inglés ya que la mayoría de la gente (desgraciadamente) tiene que programar en él.



Quiero recalcar que yo sigo el principio KISS por lo que si en un directorio solo hay un archivo, no lo necesito. Motivo por el que repository.dart no tiene un directorio conteniéndolo. Haz tu según tu gusto.

En esta imagen se puede ver diferenciadas dos partes la visual UI+main y por otro lado data.

En el caso de data también incluyo los modelos, no es que sean una capa en si misma pero como suele haber bastantes modelos prefiero tener una carpeta para poderlos localizar fácilmente. Estos modelos suelen ser los objetos para convertir de json a dart.

Cómo ya dije anteriormente repository.dart es opcional.

En cuanto a la disposición de UI no entra dentro de esto, yo personalmente utilizo un esquema donde widgets comunes van a una carpeta y luego solo creo carpeta cuando una pagina se va ha descomponer en varios ficheros:



En este ejemplo Home es una pagina con varios componentes por lo que le creo su propio directorio a diferencia de las otras paginas que como no son mas que un fichero no lo hago. En la carpeta widgets guardo todo lo común.

Se que hay personas que les gusta tener cada pagina en un directorio e incluso que tienen distinta organización o nombre, me parece perfecto.

En la siguiente entrega veremos un ejemplo de implementación de todo esto usando Getx.


Un Saludo.

Comentarios

Publicar un comentario

Entradas populares de este blog

Clean Arquitecture: Mi visión en Flutter (2/2), implementando con Getx

Getx 2 - variables reactivas - Lista, Mapas, Objetos