Saltar al contenido principal

Caso de estudio de arquitectura

Un recorrido por una aplicación Flutter que implementa el patrón arquitectónico MVVM.

Los ejemplos de código en esta guía son de la aplicación de ejemplo Compass, una aplicación que ayuda a los usuarios a crear y reservar itinerarios de viajes. Es una aplicación de muestra robusta con muchas características, rutas y pantallas. La aplicación se comunica con un servidor HTTP, cuenta con entornos de desarrollo y producción, incluye un estilo específico de la marca y contiene una alta cobertura de pruebas. De esta forma y otras más, simula una aplicación Flutter del mundo real rica en funciones.

Una captura de pantalla de la pantalla de inicio de la aplicación de brújula.
Una captura de pantalla de la pantalla principal de la aplicación de brújula.
Una captura de pantalla de la pantalla del formulario de búsqueda de la aplicación de brújula.
Una captura de pantalla de la pantalla de reserva de la aplicación de brújula.

La arquitectura de la aplicación Compass se asemeja bastante al patrón arquitectónico MVVM tal como se describe en las guías de arquitectura de aplicaciones de Flutter. Este caso de estudio de arquitectura demuestra cómo implementar esas guías recorriendo la función "Home" de la aplicación Compass. Si no estás familiarizado con MVVM, deberías leer esas guías primero.

La pantalla Home de la aplicación Compass muestra la información de la cuenta del usuario y a la vez una lista de los viajes guardados del usuario. Desde esta pantalla se puede cerrar sesión, abrir páginas detalladas de viajes, eliminar viajes guardados y navegar a la primera página del flujo principal de la aplicación, que permite al usuario crear un nuevo itinerario.

En este caso de estudio, aprenderás lo siguiente:

Este caso de estudio fue escrito para ser leído en orden. Cualquier página dada podría hacer referencia a las páginas anteriores.

Los ejemplos de código en este caso de estudio incluyen todos los detalles necesarios para comprender la arquitectura, pero no son fragmentos de código completos y ejecutables. Si prefieres seguir el desarrollo con la aplicación completa, puedes encontrarla en GitHub.

Estructura de paquetes

#

Un código bien organizado es más fácil de trabajar para múltiples ingenieros con un mínimo de conflictos de código y es más fácil de navegar y entender para los nuevos ingenieros. La organización del código tanto beneficia como se beneficia de una arquitectura bien definida.

Hay dos formas populares de organizar el código:

  1. Por funcionalidad: Las clases necesarias para cada funcionalidad se agrupan juntas. Por ejemplo, podrías tener un directorio auth, que contendría archivos como auth_viewmodel.dart, login_usecase.dart, logout_usecase.dart, login_screen.dart, logout_button.dart, etc.
  2. Por tipo: Cada "tipo" de arquitectura se agrupa junto. Por ejemplo, podrías tener directorios como repositories, models, services y viewmodels.

La arquitectura recomendada en esta guía se presta a una combinación de ambas. Los objetos de la capa de datos (repositorios y servicios) no están vinculados a una única funcionalidad, mientras que los objetos de la capa de UI (vistas y view models) sí lo están. A continuación se muestra cómo se organiza el código dentro de la aplicación Compass.

  • lib/
    • ui/
      • core/
        • ui/
          • <shared_widgets>
        • themes/
      • <feature_name>/
        • view_models/
          • <view_model_class>.dart
        • widgets/
          • <feature_name>_screen.dart
          • <other_widgets>
    • domain/
      • models/
        • <model_name>.dart
    • data/
      • repositories/
        • <repository_class>.dart
      • services/
        • <service_class>.dart
      • model/
        • <api_model_class>.dart
    • config/
    • utils/
    • routing/
    • main_staging.dart
    • main_development.dart
    • main.dart
  • test/// Contiene pruebas unitarias y de widgets.
    • data/
    • domain/
    • ui/
    • utils/
  • testing/// Contiene mocks que otras clases necesitan para ejecutar pruebas.
    • fakes/
    • models/

La mayor parte del código de la aplicación se encuentra en las carpetas data, domain y ui. La carpeta data organiza el código por tipo, ya que los repositorios y servicios se pueden usar en diferentes funcionalidades y por múltiples view models. La carpeta ui organiza el código por funcionalidad, porque cada funcionalidad tiene exactamente una vista y exactamente un view model.

Otras características notables de esta estructura de carpetas:

  • La carpeta UI también contiene un subdirectorio llamado "core". Core contiene widgets y lógica de temas que son compartidos por múltiples vistas, como botones con el estilo de tu marca.
  • La carpeta domain contiene los tipos de datos de la aplicación, ya que son utilizados por las capas data y ui.
  • La aplicación contiene tres archivos "main", que actúan como diferentes puntos de entrada a la aplicación para desarrollo, staging y producción.
  • Hay dos directorios relacionados con las pruebas al mismo nivel que lib: test/ tiene el código de prueba, y su propia estructura coincide con lib/. testing/ es un subpaquete que contiene mocks y otras utilidades de prueba que se pueden usar en el código de prueba de otros paquetes. La carpeta testing/ podría describirse como una versión de tu aplicación que no distribuyes. Es el contenido que se prueba.

Hay código adicional en la aplicación compass que no pertenece a la arquitectura. Para ver la estructura completa del paquete, consúltala en GitHub.

Otras opciones de arquitectura

#

El ejemplo en este caso de estudio demuestra cómo una aplicación cumple con nuestras reglas arquitectónicas recomendadas, pero se podrían haber escrito muchas otras aplicaciones de ejemplo. La UI de esta aplicación se apoya en gran medida en los view models y ChangeNotifier, pero se podría haber escrito fácilmente con streams, o con otras librerías como riverpod, flutter_bloc y signals. La comunicación entre las capas de esta aplicación manejó todo con llamadas a métodos, incluyendo el sondeo para obtener nuevos datos. En su lugar, podría haber utilizado streams para exponer los datos desde un repositorio a un view model y seguir cumpliendo con las reglas cubiertas en esta guía.

Incluso si sigues esta guía al pie de la letra y decides no introducir librerías adicionales, tienes decisiones que tomar: ¿Tendrás una capa de dominio? Si es así, ¿cómo gestionarás el acceso a los datos? La respuesta depende tanto de las necesidades de cada equipo que no hay una única respuesta correcta. Independientemente de cómo respondas a estas preguntas, los principios de esta guía te ayudarán a escribir aplicaciones Flutter escalables.

Y si lo miras de cerca, ¿no son todas las arquitecturas MVVM de todos modos?

Comentarios

#

Dado que esta sección del sitio web está evolucionando, ¡agradecemos tus comentarios!