6. Dart et de son fonctionnement


Lors de l’article précédent, je vous ai donné un aperçu de ce qu’était Flutter. Cette présentation indiquait que pour développer une application, il fallait utiliser le langage de programmation Dart. Dans cet article je vais vous présenter rapidement l’histoire de ce langage ainsi qu’une introduction sur son fonctionnement.

Histoire

Dart Createurs

Lars Bak et Kasper Lund

Naissance de Dart

Dévoilé en 2011, Dart est un langage créé par Lars Bak et Kasper Lund, des ingénieurs de chez Google, qui, suite à des problèmes rencontrés avec le langage JavaScript, décident d’en créer un nouveau qui permettrait de pallier tous les problèmes de maintien de code base conséquente avec un langage qui rendrait le développement plus concis.

C’est donc une équipe de développeurs, habitués à la création de machines virtuelles et aux compilateurs qui s’attellent à cette tâche. En effet, l’équipe a notamment travaillé sur le moteur V8 de JavaScript et le compilateur Hotspot de Java. Lors de sa première version en 2013, Dart s’utilisait sur les navigateurs, avait un typage dynamique et la compilation était en JIT (just-in-time / à la volée).

Le langage n’a pas un énorme succès et son utilisation reste limitée.

Flutter

Logo de Flutter

En 2017, le projet Flutter émerge avec sa première version alpha. Le framework intègre Dart et propose un kit de développement multiplateforme visant tous les OS mobiles et desktop et le web. Ambitieux n’est-ce pas ? Un peu comme Java et son “ Write once, run anywhere ” (Écrit une fois, fonctionne partout).

Le framework rencontre un certain succès et le langage va subir de grosses évolutions. À ses débuts, le projet se concentre sur la partie mobile, il est alors rapidement possible de créer des applications Android et iOS.

En 2018, la 2e version de Dart est disponible et le paradigme du langage a complètement été revu, il a désormais un typage fort et voit sa compilation possible aussi en AOT (Ahead-of-time/pré-compilé) en plus du JIT (Just In Time). Afin de fonctionner, Dart est accompagné de DartVM, une machine virtuelle.

Machine Virtuelle

Dart fonctionne dans une machine virtuelle qui permet différents schémas de compilation selon les besoins, le fonctionnement et le contenu ne sera pas le même selon si on compile pour en mode debug ou release.

La suite de ce cours va être très technique et pas forcément indispensable pour vos débuts sur Flutter, néanmoins il est toujours intéressant de savoir sur quoi on se lance. Nous reviendrons dans tous les cas sur certaines de ces éléments dans d’autres cours.

Compilation avec Flutter Dans la VM de Dart, on peut remarquer 3 grands types de composants.

Dart VM Dans le composant Runtime, on va retrouver le garbage collector, Dart natives, le runtime type infirmation ( RTTI ) et les snapshots.

Garbage Collector Le composant Runtime possède un Garbage Collector qui s’occupera d’allouer/désaffecter les objets. Et avec Flutter, il peut y en avoir beaucoup, chaque élément d’interface est un Widget, et un Widget est un objet.

C’est un sujet assez long donc si vous voulez avoir plus de détails sur le fonctionnement du G.C. je vous renvoie vers cet article.

Dart Native Selon la destination de votre compilation, vous vous retrouverez avec du Dart Native ou du Dart Web. Dart Native sera utilisé pour faire fonctionner votre code sur un environnement mobile, desktop et serveur. Dans le cadre du développement d’une application en Flutter, la compilation sera différente selon si vous souhaitez compiler une version de développement (debug) ou de production (release).

Lors du développement nous seront en mode debug, ce qui inclut la VM de Dart dans l’application compilée avec le compilateur JIT, ce dernier permet d’utiliser le Hot Reload et des outils de debug.

Dart Platforms L’application comprendra la VM de Dart, ce qui rendra le projet plus lourd (par exemple 100 Mo pour Android au lieu de 30 Mo en version de release) et légèrement plus lent.

Le Hot Reload est un élément critique de Flutter, il permet de rafraîchir une vue sur laquelle on travaille, instantanément la vue est mise à jour avec nos dernières modifications.

En mode production, la compilation se fera sur la machine et l’exécution sur le device. La compilation se fera en AOT et résultera en ARM ou x64.

RTTI Run-Time Type Information. Cela signifie qu’il est possible de vérifier le type d’une variable pendant le runtime (exécution) du programme et même faire de la promotion de type.

Compilation

JIT La compilation Just-it-time permet de mettre en place une compilation durant l’exécution du programme, dite “À la volée”.

AOT La compilation AOT, ahead-of-time, compile en natif (x64 ou ARM). Cette méthode de compilation sera utilisée pour la mise en production d’une application. Cette compilation, comme son nom l’indique, sera effectuée avant le runtime de l’application. Celle-ci sera plus rapide qu’en JIT car tout sera déjà pré-compilé et non compilée à la volée. C’est ce mode de compilation qui sera utilisé pour les versions de production/release d’une application Flutter aussi bien sur iOS que sur Android.

DBC Dart Byte Code. La compilation est différente pour iOS, puisque cet OS interdit la compilation JIT. Donc pour une compilation dans un environnement de Debug sur iOS, les composants seront donc une interprétation du byte code Dart.

Productivité

Hot Reload Le Hot Reload permet de recharger une application en injectant le code modifié depuis la dernière compilation Cela permet un gain de temps non négligeable, car cette fonctionnalité est plus rapide qu’une compilation classique, elle est même quasi instantanée. Les modifications du code sont envoyées directement dans la machine virtuelle déjà en cours de fonctionnement et de son côté Flutter mettra à jour toute l’interface utilisateur. Certains cas nécessiteront tout de même une nouvelle compilation.

Observatory, Debugger, Profiler, C’est un outil web qui permet d’accéder à des outils d’analyse afin d’observer les performances de son application. Il va notamment vous servir dans le cadre d’une compilation en mode profil. Le mode de compilation profil est proche de celui de la release tout en contenant les outils DevTools qui permette d’analyser et débuger le projet à l’aide de l’interface web fourni par la VM de Dart.

Dev Tools Flutter

Mono-Thread et Asynchrone

Dart est un langage monothread qui offre la possibilité de faire de l’asynchrone. Pour comprendre comment tout ça marche, on va jeter un œil du côté des futures, des isolates et de l’ event loop.

Event loop L’event loop permet de gérer un processus à la fois (FIFO). Le fonctionne se rapproche beaucoup de l’event loop de Javascript.

Event Loop Flutter Isolate

Quand vous aurez une application lancée, elle tournera dans ce qu’on appelle un isolate. C’est un espace isolé qui possède sa propre mémoire et une boucle d’évènement (event loop) qui sont exécutées par ordre d’arrivée.

Future Imaginons que dans cet isolate, on cherche à effectuer une tâche, par exemple une requête à un serveur web. Ce genre d’action n’est pas immédiate, il y aura toujours une latence avant que celle-ci soit terminée. Le serveur appelé peut mettre quelques millisecondes à répondre voir plus si la connexion de l’appareil n’est pas optimale. Il faut donc prendre en compte le fait que l’on n’aura pas une réponse immédiate.

Pour prendre en compte cette problématique en Dart, on va faire de l’asynchrone à l’aide des mot-clés Future et Async/Await.

Voici comment cette action se traduirait en code :

void main() async {
 print('On lance la requête au serveur...');
 await getResponse();
 }

Future<void> getResponse() async {
await Future.delayed(const Duration(seconds: 2),() => print('... Et voici la réponse'));}

Concurrence Comme on l’a vu, la machine virtuelle de Dart fonctionne avec un isolate. Lors de la programmation de votre application, si vous avez besoin de mettre en place des opérations lourdes (lecture de base de donnée par exemple) il sera judicieux de créer un autre Isolate spécifique à cette opération afin de limiter l’occupation de celui déjà existant dans la machine virtuelle.