Application Mobile Flutter, State Management Library : Bloc
Contexte
Les applications mobiles sont en constante évolution depuis l’apparition des smartphones. Elles offrent toujours plus de possibilités mais cela entraine une augmentation de leur complexité. Le nombre de téléchargements de celles-ci s’élève à plus de 200 milliards en 2019.
Aujourd’hui, dans leur utilisation, il est notamment nécessaire de savoir l’état en temps réel de son application. Cela afin de pouvoir connaître la validité ou l’impossibilité à exécuter certaines actions. Par exemple, en cas d’une perte de connexion Wi-Fi, il est important de signaler ce problème à l’utilisateur s’il souhaite se rendre sur une nouvelle page.
Afin de choisir vers quelle architecture s’orienter, il est nécessaire de prendre en compte le besoin métier et les contraintes inhérentes à la gestion d’un projet. Par exemple, pour un ERP, on prendra en compte le besoin de poser des jours de congés tout en prenant en compte la qualité, le coût et le délai pour la gestion de celui-ci. Une bonne architecture peut notamment se définir par sa maintenabilité, simplicité, évolutivité, compatibilité, et interconnectivité .
Choix du SDK
Pour notre application, nous avons décidé d’utiliser le SDK Flutter lancé en Mai 2017 par Google permettant de créer des applications multi-plateformes ( Android, IOS, Web), avec la même base de code.
Flutter se base sur le langage de programmation Dart, lui aussi développé par Google. Dart est relativement proche du langage Java, ce qui fait de lui un langage facile à prendre en main pour les adeptes du langage orienté objet.
De plus, Flutter vous permet de construire des interfaces intuitives et esthétiques pour vos applications, via l’utilisation des widgets tirés des “Design Systems” Material Design de Google et Cupertino d’Apple.
Choix de notre state management library
Au sein de Flutter, il est important de gérer l’évolution des états de l’application au cours de son exécution. Il existe de nombreuses approches pour gérer ces états et de nombreuses librairies implémentent ces approches avec Flutter.
C’est pourquoi je vais vous en présenter quelques-unes et les comparer sur certains critères afin d’obtenir un choix final. Les critères de comparaisons vont être :
- la maturité du package
- sa difficulté d’apprentissage
- sa maintenabilité
- sa testabilité
Commençons tout d’abord avec Provider, c’est la solution recommandée par l’équipe de Flutter. Ce gestionnaire d’état est assez simple à utiliser et son temps d’apprentissage est correct.
Continuons en parlant de GetX, un package performant, et permettant un gain de productivité et une meilleure organisation des ressources. Assez simple à utiliser, avec une prise en main rapide, la solution a récemment gagné en popularité et est très utilisé par les nouveaux arrivants sur Flutter.
Poursuivons avec MobX, cette librairie est inspirée du projet MobX Javascript. Elle permet de générer une grande partie du code, afin de permettre au développeur de se détacher des tâches répétitives et de se concentrer sur des tâches à plus forte valeur ajoutée.
Venons en maintenant à Bloc, un package permettant de structurer au mieux le code afin de mieux pouvoir tester continuellement l’avancement dans le projet. L’apprentissage est plus long et son utilisation est plus complexe, mais Bloc est actuellement la librairie la plus populaire et la plus utilisée pour les projets à long terme de part ses mises à jours régulières et sa haute testabilité.
Voici le tableau obtenu permettant d’évaluer les solutions selon nos critères :
Si vous souhaitez plus de renseignements sur toutes les librairies de state management disponibles, vous pouvez consulter la documentation : https://flutter.dev/docs/development/data-and-backend/state-mgmt/options
Notre choix final s’est porté sur Bloc. En effet, nous souhaitions une application maintenable, testable et ayant une forte capacité d’évolution, ce package nous correspondait donc parfaitement. Malgré sa prise en main plus longue, le résultat se trouvait être meilleur pour nos besoins.
Je vais maintenant vous présenter plus en détail la librairie Bloc et ses principaux concepts à l’aide d’exemples puis nous terminerons en discutant de la testabilité des blocs.
Présentation de Bloc
Comme présenté très brièvement ci-dessus, Bloc est une librairie de state management qui permet de gérer les différents états d’une application (donnée en chargement, erreur, perte de connexion, envoi validé). Bloc signifie Business Logic Component et permet donc de séparer la logique métier de l’affichage à l’utilisateur. Cette librairie est donc assez similaire au célèbre design pattern MVC très utilisé pour l’organisation du code, la définition du rôle de chaque fichier et la séparation de la logique du code en trois parties.
Bloc va recevoir des évènements suite aux actions de l’utilisateur ( clic sur bouton, changement de page, donnée entrée dans un formulaire, etc ) et va retourner un changement d’état sur l’affichage ( page mise à jour, message d’erreur ) afin de communiquer à l’utilisateur le résultat de son action.
Streams
Bloc permet de faire le lien entre deux Streams, le premier correspondant aux évènements en entrée et l’autre aux états en sortie. Pour expliquer ce concept de Stream, je dirais que ce sont des canaux dans lesquels circulent des données de façon asynchrone.
A l’entrée d’un Stream un émetteur va envoyer des informations et à la sortie du Stream un récepteur va les récupérer et y réagir. Dans notre cas, ce sont les éléments de l’interface qui vont permettre d’émettre ces évènements et d’y réagir en se mettant à jour.
Bloc_Builder, Bloc_Listener, Bloc_Provider
Ces trois outils du package flutter_bloc vont nous permettre respectivement :
- De reconstruire le widget en fonction de son changement d’état : à chaque nouvel évènement envoyé par l’utilisateur sur l’application, ce builder va recharger la page en mettant son état à jour
- D’exécuter une action en réponse à ce changement tel qu’un message de validation, d’erreur, ou un changement de page, une redirection, cela dans le but de rendre compte à l’utilisateur le résultat de son action
- De créer et d’apporter un bloc à d’autres pages de l’arbre des widgets.
Mais qu’est ce qu’un widget ? Il s’agit d’un élément d’interface. Ces widgets s’assemblent entre eux afin de composer des pages et sont organisés sous forme d’une arborescence.
Prenons l’exemple d’une page d’accueil. Dans celle-ci nous utilisons BlocProvider pour créer une instance d’un bloc gérant l’état de la connexion( wifi / 4G / pas de connexion ). Nous souhaitons pouvoir gérer l’état de la connexion sur toutes les pages de notre application avec ce même bloc. Il faut donc pouvoir le transmettre à toutes les pages. À la place de re créer ce bloc directement dans tous les widgets, nous pouvons utiliser BlocProvider pour le transmettre.
Voici en image l’exemple ci-dessus : à gauche le bloc est remis dans chacun des widgets, à droite il est premièrement créé puis transmis dans l’arbre des widgets grâce à BlocProvider.
Testabilité des blocs
Bloc a été conçu pour être facilement testable. Ce caractère est essentiel au développement d’une application mobile. Il permet de s’assurer du bon fonctionnement de l’application après un ajout de fonctionnalité, ou encore la modification d’une autre.
La façon dont Bloc réalise ces tests est assez simple à comprendre : Bloc va chercher à comparer si le résultat en sortie est bien égal à la valeur attendue cela notamment grâce à la fonction expect. Imaginons par exemple que nous souhaitons afficher un nombre initialement à 5 sur une page et qu’à l’aide de deux boutons nous pouvons l’incrémenter de 3 ou le décrémenter de 3. Le premier test ici serait de vérifier que la valeur sur la page est bien égale à 5 initialement. Puis par la suite, il s’agirait de vérifier que lors de l’appui sur le bouton lançant l’incrémentation, la valeur retourne 8. Le même principe s’applique pour la décrémentation.
Voici en image la forme que prendrait ces tests pour l’exemple ci-dessus :
Bien évidemment, cet exemple est assez basique, car on ne vérifie qu’un entier. Ces tests peuvent néanmoins être exécutés pour tester toutes les fonctionnalités de votre application tels que : les bonnes redirections lors de changement de pages, les affichages correspondant à l’appui sur un bouton, etc.
Conclusion
Bien que cet article n’ait pu vous présenter tous les concepts liés à Bloc et son utilisation, vous devriez avoir aperçu son utilité quant à la gestion des états d’une application mobile. De plus, son architecture type MVC et sa forte testabilité offrent un cadre idéal de développement tout au long d’un projet d’application mobile, permettant de mieux se retrouver dans le code et d’avancer de façon itérative.
Liens et sources utiles :
Documentation officielle de la librairie BLOC ( en anglais ):
Si vous souhaitez vous former d’avantage sur Bloc, voici la vidéo que je vous recommande : https://youtu.be/THCkkQ-V1-8