Sous le capot d’Inbox (traduction Française)

Article rédigé par Garrick Toubassi, Directeur de l’ingénierie.

Article traduit en Français par Sami Jaber (DNG Consulting – sami.jaber@dng-consulting.com)

Article original : http://gmailblog.blogspot.nl/2014/11/going-under-hood-of-inbox.html

Note de l’auteur : Notez que cet article est beaucoup plus technique que les articles au menu habituel de ce blog.  Il vous emmènera dans les coulisses du développement de Inbox. Si vous êtes un ingénieur pratiquant, un codeur aspirant ou simplement intéressé par la manière dont la sauce est réalisée (mmm la sauce), cette lecture est pour vous !

Gmail est né il y a une dizaine d’années, arrivant dans un monde dominé par les téléphones à ouverture, les casquettes de camionneur utilisant les standards d’aujourd’hui sur du Web sans saveur. Chaque Click sur une page nécessitait plusieurs secondes d’attentes pour avoir le rafraîchissement de la page complète. Du coup, lorsque nous avons développé Gmail, nous avons choisi une approche différente en essayant de construire un nouveau genre d’application Web s’exécutant dans un navigateur et s’appuyant sur une logique riche en JavaScript et un modèle local de données. Cela nous a permis de gérer tous ces clicks à l’intérieur du navigateur sans attendre le retour du serveur. 10 ans après, cette architecture est devenue la norme, elle a été adoptée par la plupart des sites Web et supporte pléthore de Framework et d’outils (AngularJS, Meteor, BackBone, Ember ou NodeJS).

Mais depuis ces dix dernières années, beaucoup de choses ont changé. Les possibilités et la diversité des périphériques ont explosé. Les utilisateurs s’attendent à être capables de passer d’un PC à un téléphone tout en ayant le même type d’expérience utilisateur.

La conséquence est que les développeurs doivent faire face à de nouveaux challenges. Comment construire une application de qualité multiplateformes tel que Android, le Web et iOS sans sacrifier à la qualité ou la vélocité d’exécution. En tant que développeur, vous vous êtes peut-être demandé si vous deviez réécrire votre application trois fois pour qu’elle soit optimisée sur chaque plateforme au bit près de performance ? Ou alors vous ciblez une application destinée à intégrer le marché le plus tôt possible en utilisant des capacités hybrides tirant partie des mêmes technologies (mais sacrifiant par la même occasion l’intégration et l’expérience utilisateur) ?

Faire face au challenge

Ces questions ont pesé lourdement lorsque nous avons démarré la construction d’Inbox. Notamment après avoir travaillé des années sur Gmail et sachant que les utilisateurs attendraient de nous, quoi que nous choisissions, quelque chose d’aussi rapide et optimisé que Gmail. Inbox est aujourd’hui là. Nous avons donc pris la décision de construire trois applications natives séparées pour s’intégrer de manière transparente dans chacune de nos plateformes cibles : Android (via Java+ Android SDK), le Web (via JavaScript +DOM/CSS) et iOS (via Objective-C-UIKit).

Bien évidemment, il y a plusieurs éléments d’Inbox qui sont partagés par les trois plateformes : le code destiné à gérer les opérations réseau, le cache d’objets, le stockage local d’objets persistants (local persistent storage), la gestion de l’édition des utilisateurs de manière locale et distante et le support de l’Offline. Cette logique doit être fidèlement et correctement implémentée et à jour sur les trois clients. Les réécrire trois fois avec trois différents langages aurait absorbé des ressources d’ingénierie et aurait ralenti la mise en production de nouvelles fonctionnalités dans Inbox.

Trancher dans le lard

Pour arriver à gagner ce challenge, nous avons choisi une nouvelle approche dans laquelle le modèle de données et la logique applicative (conceptuellement le « modèle » et « modèle-vue-controlleur ») est écrite une seule fois en Java. Ce modèle de données abstrait les concepts uniques à Inbox comme les « Conversations », les « Rappels », les « Contacts » et les « Labels » et fournit ainsi un modèle de données totalement observable pour mettre en place le Databinding (la mise en corrélation des modifications d’interface graphique avec le modèle de données).

Nous avons construit l’application Inbox pour Android au-dessus de ce modèle Java.

L’affaire se corse

Sur le Web, l’histoire a été plus intéressante. Nous avons utilisé le compilateur Open Source GWT pour traduire le code Java en modèle de données JavaScript. Ces dernières années, GWT a fait d’énormes progrès dans sa manière de générer du JavaScript qui soit facilement et de manière performante intégré à du JavaScript natif. A titre d’exemple, la méthode Reminder.snooze() fournie par le modèle de données Java est exposé exactement de la même manière en JavaScript.

Pour iOS, nous avons développé un compilateur (désormais OpenSource) J2ObjC qui traduit notre modèle de données Java en Objective-C. Et encore une fois, nous avons obtenu une API naturelle sur laquelle nous avons pu construire notre application native iOS (utilisant aussi Reminder Snooze()). Le lecteur curieux pourrait se demander comment nous avons géré la différence de modèle (impedance mismatch) entre un langage à base de ramasse miettes et un langage à comptage de référence (avec ObjectiveC, la mémoire est géré à la main). Généralement, J2ObjC s’appuie sur le pool de destruction automatique (voir « autorelease pool »), ainsi les objets qui seraient normalement libérés par la ramasse miettes sont libérés lorsque le pool est libéré. Le seul problème avec cette approche est la gestion des cycles de références. Lorsque des cycles existent dans notre modèle de données Java, nous utilisons une annotation Java pour identifier qu’il y a une @WeakReference. Une fois transpilé, la propriété correspondante en Objective-C aura le modificateur __weak, ce qui aura pour effet de bloquer la chaîne de rétention. En pratique, cela n’a pas été un problème majeur et nous avions des tests automatiques permettant de détecter les rares cas où le modèle de données possédait des erreurs de ce type.

Conclusion

Si vous construisez une application qui a une interface graphique riche et autonome, qui cible plusieurs plateformes, doit être optimisé sans compromettre les performances et l’expérience utilisateur, vous avez désormais une nouvelle option à considérer : un modèle de données partagé, compilé, tirant partie totalement des interfaces graphiques natives.  Cela a marché pour nous avec Inbox dans lequel  nous partageons deux tiers du code total et délivré un produit avec les mêmes fonctionnalités et date de mise en production sans avoir à réécrire les choses trois fois. Si vous souhaitez en savoir plus sur les technologies qui sont la force d’Inbox, consultez les sites suivants : http://gwtproject.org et http://j2objc.org.

Garrick Toubassi (Google)