Aplicaciones móviles multiplataforma con flutter en 2023

Aplicaciones móviles multiplataforma con flutter en 2023

Desarrollar aplicaciones móviles multiplataforma es una tarea compleja, ya que cada entorno es un mundo independiente, con lenguajes, modelos arquitectónicos y patrones muy particulares, lo cual, además de traer problemas particulares a la mesa, también implica invertir esfuerzo con recursos específicos para cada entorno .

Varios frameworks y herramientas han surgido en los últimos años, en un esfuerzo por unificar el desarrollo de aplicaciones para las distintas plataformas. Uno de estos frameworks es Flutter, desarrollado por Google con su primera versión alfa en 2017, ha ido ganando tracción desde su lanzamiento, con la idea de generar aplicaciones nativamente compiladas a partir de una base de código único.

En este post les contamos cuál fue nuestra experiencia desarrollando con Flutter, a inicios del 2023, una aplicación multiplataforma para Android e iOS. Para esto quiero enfocarme en 8 puntos:

  1. Widgets/Componentes
  2. Hot reloading
  3. Diseño y responsividad
  4. Lenguage DART
  5. Librerías y Comunidad
  6. Reactividad y manejo de estados
  7. Compilación para Android e IOS
  8. Seguridad

1. Widgets/Componentes

Flutter incluye un amplio conjunto de widgets para crear interfaces de usuario, tanto para Material Design como Cupertino. Uno de los puntos fuertes de flutter es la forma que propone para escribir componentes en forma de árbol, de padres a hijos, lo cual, en mi opinión, es bastante natural y lógico desde la perspectiva de un programador. Un componente con muchas funcionalidades se puede volver muy grande y complejo, en estos casos, la experiencia nos ha enseñado que lo mejor es aplicar la máxima " dividir y vencerás ", analizando que secciones de un componente podrían convertirse en componentes reutilizables.

Comparando con el desarrollo de una aplicación android de forma nativa, esta tarea ha resultado mucho más sencilla en flutter, por la estructura de widgets que propone, lo que facilita el diseño de un modelo arquitectónico modular orientado a componentes (bastante similar a un modelo de una aplicación react o vue).

Bonus: Otro punto a favor, no necesitamos archivos xml :D :D :D

2. Hot reloading

Hot reload o recarga en caliente es una característica muy conveniente para un desarrollador pues permite recargar secciones de la aplicación en caliente sin necesidad de recompilar toda la aplicación. Flutter incorpora esta característica de forma nativa, lo que es muy útil, pues nos ahorró tiempo de desarrollo al poder visualizar los cambios insertados en la interfaz de usuario de forma mucho más rápida (casi inmediatamente), resultando en un flujo de trabajo más productivo.

3. Diseño y responsividad

El manejo de temas en flutter también nos dejó una sensación positiva ya que es bastante flexible y fácil de manejar, con paletas de color incorporadas por defecto y la posibilidad de personalizar los colores en la mayoría de los widgets.

En este punto, no todas las cosas son super sencillas o están super visibles, requiriendo un poco de investigación o indagación en la documentación dependiendo de lo que queramos hacer.

Un caso de la vida real fue que necesitamos diseñar una paleta con colores personalizados que incluyan gamas de opacidad. Indagando un poco, lo pudimos lograr usando la clase MaterialColor con códigos de color en hexadecimal que en Flutter se escriben con el prefijo 0x.

En cuanto a la responsividad, Flutter incluye cosas por defecto que ayudan bastante en este aspecto como la clase LayoutBuilder , los widgets Expanded y Flexible , el método MediaQuery.of() , etc. La experiencia fue bastante positiva con respecto a una app nativa, sin embargo no estuvo exenta de problemas, sobre todo para componentes complejos; Los más comunes fueron los problemas de overflow de componentes, los adecuados nos dieron algunos dolores de cabeza interesantes :D.

4. Lenguaje DART

Dart es un lenguaje moderno orientado a objetos, soporta tipado fuerte y débil, lo que lo hace bastante dinámico. Aunque falló estrepitosamente en sus intentos por reemplazar un javascript en el mundo web, revivió gracias a que Flutter lo cambió como lenguaje principal de desarrollo lo que disparó su evolución.

En nuestra experiencia es bastante fácil de aprender, sobre todo para programadores que han trabajado con mecanografiado o kotlin . Ha sido optimizado pensando en la perfomance por lo que generalmente es un lenguaje bastante rápido en tiempo de ejecución. En mi opinión la sensación a la hora de trabajar con dart fué positiva aunque no tan divertido como trabajar con kotlin ( para gustos personales no hay nada escrito :D).

5. Librerías y comunidad

La comunidad de flutter ha crecido rápidamente en los últimos años, lo que ha empujado al crecimiento del ecosistema de flutter/dart. Es interesante mencionar que en la última encuesta de StackOverflow Flutter se posicionó por delante de frameworks como React native.

En https://pub.dev podemos encontrar todo tipo de paquetes para casi cualquier funcionalidad que necesitemos, muchos desarrollados por la misma Flutter Community , por tanto no hemos tenido grandes problemas a la hora de encontrar las librerías necesarias para casi todas las funcionalidades que necesitamos.

En nuestra experiencia lo más desafiante y difícil con respecto a este punto, fue el manejo de mapas fuera de línea con servidores de mosaicos personalizados.

6. Reactividad y manejo de estados

La programación reactiva es un paradigma de programación declarativa que se enfoca de los flujos de datos (data streams) y la propagación de cambios. Por tanto, el enfoque pasa a estar en los datos, y es necesario que nuestra aplicación sea capaz de manejar el estado de los datos relevantes durante el flujo de ejecución de una aplicación.

Flutter y Dart incorporan clases nativas que permiten trabajar con flujos de datos como StatefullWidget, Stream, StreamControllers, etc. En nuestra experiencia, a medida que la aplicación se va tornando compleja, la implementación de un sistema reactivo con las clases nativas, se va tornando excesivamente complejo y dificil de mantener.

Un ejemplo sería una aplicación de comercio electrónico donde es necesario manejar un estado con información relevante durante todo el proceso de una compra. Por tanto fué necesario buscar librerías y patrones que nos permitan simplificar la implementación y potenciar la reutilización de código al máximo. Existen varias librerías que se enfocan en la reactividad como rxdart , flutter_bloc que utiliza el patrón BloC, riverpod , etc.

Inicialmente probamos varias cosas, y nos decantamos por riverpod , sin embargo, a medida que nuestra aplicación fué creciendo nos encontramos que estas librería tienen una limitante: la reactividad limitada está a clases que solo pueden ejecutarse dentro del arból de UI de flutter, lo cual no llevar a cabo porciones de código reutilizables a clases o funciones comunes.

Aunque seguimos usando riverpod para casos bastante específicos, probé de construir un sistema reactivo bastante peculiar que supliera nuestras necesidades. En primer lugar utilizando la librería flutter_hooks que nos permitió simplificar nuestros componentes en gran medida, get_it para centralizar servicios con porciones de código reutilizables, y ganchos personalizados con los necesarios para dar vida a nuestro sistema reactivo con manejo de estado. Lindo desafío y aventura xD.

7. Compilación para Android e iOS

Como mencionamos en la introducción, Flutter permite tener una fuente de código única que puede compilar tanto para Android como para IOS. Esto es cierto en cuanto a la funcionalidad de la aplicación, pero por supuesto, como Android e IOS son mundos totalmente diferentes, existen archivos de configuración que no se comparten y son únicos para cada uno, como los archivos de build, configuración de permisos, etc.

Para Android el proceso es mucho más fluido ya que se puede trabajar con cualquier entorno. Para iOS, sin embargo, necesitamos una MAC con Xcode para poder compilar y probar nuestras aplicaciones en este sistema operativo, lo que implica que debemos tener cierto conocimiento de desarrollo de aplicaciones IOS.

También nos encontramos que ciertas librerías necesitaban configuraciones especiales para uno u otro sistema operativo. Aún con todo esto la base de código de funcionalidades es única, lo cual ya es un montón de ahorro en tiempo y recursos.

Algo interesante que logramos y que vale la pena mencionar es la posibilidad de utilizar archivos .env con bastante facilidad, para configurar variables por ambiente (desarrollo, testing, producción), lo que no pudimos lograr de forma sencilla en los proyectos en que utilizamos desarrollo nativo

8. Seguridad

Este es uno de los puntos más débiles de flutter en la actualidad ya que el escáneo de vulnerabilidades en librería e integración con herramientas de escáneo de código estático está muy verde y es prácticamente nulo. La única herramienta que encontramos para escanear vulnerabilidades fue osv-scanner de Google que está lejos de tener la solidez como herramientas del mercado.

A la fecha, la integración con sonarqube sólo se puede lograr a través de un complemento no oficial y la integración con herramientas como trivy , dependency-check o grype es nula.

Por tanto, no podemos recomendar Flutter aún ( aunque nos gustaría ) para aplicaciones con información delicada como aplicaciones financieras o bancarias. Esperemos que el panorama vaya cambiando en los próximos años.


Conclusión

Nuestra experiencia con Flutter fue bastante positiva sobre todo en lo que se refiere al flujo de desarrollo y diseño de aplicaciones móviles. La performance de Dart es bastante prometedora, permite tener una fuente de código única y comprobar que la evolución con respecto a frameworks como React Native es positiva. En el campo de la seguridad de aplicaciones e integración a pipelines de devsecops aún queda mucho trabajo por delante, por tanto no es muy recomendable para aplicaciones con información sensible.

Este fué un resumen de nuestra experiencia trabajando con Flutter, esperemos que hayan disfrutado como nosotros lo hemos hecho, ¡¡Hasta la próxima!!.