Flutter + TDD Clean Architecture 1

214

Explicación y estructura del proyecto 

Mantener su código limpio y probado son las dos prácticas de desarrollo más importantes. En Flutter, esto es aún más cierto que con otros marcos. Por un lado, es bueno hackear una aplicación rápida juntos, por otro lado, los proyectos más grandes comienzan a desmoronarse cuando mezclas la lógica de negocios en todas partes. Incluso los patrones de administración de estado como BLoC no son suficientes en sí mismos para permitir una base de código fácilmente extensible.

 

El secreto de las aplicaciones que se pueden mantener

Aquí es donde podemos emplear una arquitectura limpia y un desarrollo basado en pruebas. Todos debemos esforzarnos por separar el código en capas independientes y depender de abstracciones en lugar de implementaciones concretas.

¿Cómo se puede lograr tal independencia? Aunque nos estamos adelantando un poco, en la imagen de “cebolla” en capas a continuación, las flechas horizontales —> representan el flujo de dependencia. Por ejemplo, las “entities” no dependen de nada, los casos de uso dependen solo de “entities”, etc.

CleanArchitecture

 

Todo esto es bueno, un poco abstracto (juego de palabras) . Además, si bien la esencia de la arquitectura limpia sigue siendo la misma para cada marco, el demonio reside en los detalles. Principios como SOLID y YAGNI suenan bien, incluso puedes entender lo que significan, pero no te servirá de nada si no sabes cómo comenzar a escribir código limpio.

 

El proyecto que construiremos

Como con cualquier cosa, la teoría solo puede llevarte tan lejos: el verdadero aprendizaje proviene de hacer . Crearemos una aplicación para obtener datos interesantes sobre los números: ¡una aplicación Number Trivia!

Tiene todos los componentes principales, como obtener datos de una API , caché local, manejo de errores, validación de entrada y más. En cuanto a la gestión estatal, decidí ir con BLoC. ¡No tienes que hacerlo! No puedo enfatizar esto lo suficiente.

La arquitectura limpia no se trata de una técnica particular de gestión del estado.Como verá en poco tiempo, la arquitectura adecuada de su aplicación hará que la elección de la administración estatal sea casi intrascendente. Todavía no elegiría el enfoque StatefulWidget, pero cualquier otra cosa es genial.

 

Arquitectura limpia y Flutter

Para dejar las cosas claras y específicas de Flutter, permítanme presentarles la propuesta de arquitectura limpia de Flutter de Reso Coder para demostrar algo, me atrevo a decir, más importante que el flujo de dependencia: flujo de datos y llamadas.

Por supuesto, esta es solo una descripción general de alto nivel que puede o no decirle mucho, dependiendo de su experiencia previa. Diseccionaremos y aplicaremos este diagrama a nuestra aplicación Number Trivia en poco tiempo.

 

Clean-Architecture-Flutter-Diagram

.

Explicación y organización del proyecto

Cada “característica” de la aplicación, cómo obtener algunas curiosidades interesantes sobre un número, se dividirá en 3 capas: presentación , dominio y datos . La aplicación que estamos construyendo tendrá solo una característica.

3 capas de una función de aplicación:

number_trivia-feature

Presentación

Estas son las cosas a las que estás acostumbrado desde la arquitectura Flutter “impura”. Obviamente necesita widgets para mostrar algo en la pantalla. Estos widgets luego envían eventos al Bloc y escuchan los estados (o un equivalente si no usas Bloc para la administración del estado).

Capa de presentación:

Captura de Pantalla 2019-09-12 a la(s) 17.09.02               presentation-layer-diagram

 

Captura de Pantalla 2019-09-12 a la(s) 12.25.42

 

Aplicado a la aplicación Number Trivia

Tendremos solo una página con widgets llamada NumberTriviaPage con un solo NumberTriviaBloc .

Estructura de carpetas de presentación:

presentation-layer-2

 

Dominio

El dominio es la capa interna que no debería ser susceptible a los caprichos de cambiar las fuentes de datos o portar nuestra aplicación a Angular Dart. Contendrá solo la lógica comercial central ( casos de uso ) y los objetos comerciales ( entidades ). Debe ser totalmente independiente de cualquier otra capa.

Captura de Pantalla 2019-09-12 a la(s) 18.09.39

Pero… ¿Cómo es la capa de dominio completamente independiente cuando obtiene datos de un Repositorio, que es de la capa de datos? ¿Ves ese elegante degradado colorido para el repositorio? Eso significa que pertenece a ambas capas al mismo tiempo. Podemos lograr esto con inversión de dependencia.

Captura de Pantalla 2019-09-12 a la(s) 18.11.56

Esa es solo una manera elegante de decir que creamos una clase abstracta de Repositorio que define un contrato de lo que debe hacer el Repositorio: esto entra en la capa de dominio. Luego dependemos del “contrato” del Repositorio definido en el dominio, sabiendo que la implementación real del Repositorio en la capa de datos cumplirá este contrato.

Captura de Pantalla 2019-09-12 a la(s) 18.13.27

 

Aplicado a la aplicación Number Trivia

No habrá mucha lógica de negocios para ejecutar en la aplicación, ya que solo mostramos datos numéricos interesantes. En cuanto a los objetos comerciales, habrá una sola entidad bastante delgada llamada Number Trivia, solo un número y el texto de la trivia.

Captura de Pantalla 2019-09-12 a la(s) 18.15.17

Datos

La capa de datos consiste en una implementación de Repositorio (el contrato proviene de la capa de dominio ) y las fuentes de datos ; una es generalmente para obtener datos remotos (API) y la otra para almacenar en caché esos datos. El repositorio es donde usted decide si devuelve datos nuevos o almacenados en caché, cuándo almacenarlos en caché, etc.

Puede notar que las fuentes de datos no devuelven entidades, sino modelos . La razón detrás de esto es que la transformación de datos sin procesar (por ejemplo, JSON) en objetos Dart requiere un código de conversión JSON. No queremos este código específico de JSON dentro de las Entidades de dominio , ¿qué pasa si decidimos cambiar a XML?

Captura de Pantalla 2019-09-12 a la(s) 18.18.13

Por lo tanto, creamos clases de Modelo que extienden Entidades y agregan algunas funcionalidades específicas (toJson, fromJson) o campos adicionales, como ID de base de datos, por ejemplo.

Aplicado a la aplicación Number Trivia

Remote Data Source realizará solicitudes HTTP GET en la API de Numbers. Local Data Source simplemente almacenará en caché los datos utilizando el paquete shared_preferences.

Estas dos fuentes de datos se “combinarán” en Number Trivia Repository que será la única fuente de verdad para los interesantes datos de trivia numérica.

La política de almacenamiento en caché será muy simple. Si hay una conexión de red, siempre obtenga datos de la API y almacénelos en caché. Luego, si no hay red, devuelva los últimos datos almacenados en caché.

Captura de Pantalla 2019-09-12 a la(s) 18.22.25

 

Siguiente …

Una vez establecida la estructura fundamental de la arquitectura de la aplicación Number Trivia, comenzaremos a implementar la capa interna y más estable: el dominio. También agregaremos todos los paquetes necesarios para desarrollar la aplicación, incluidos los específicos de prueba como mockito. ¡Estamos haciendo un desarrollo basado en pruebas, después de todo!

 

Abajo déjanos un comentario un comentario.

 

 

Fuente: Reso Coder