Avec les premières versions du SDK, les plus anciens développeurs Android se souviennent qu'il fallait utiliser l'IDE Eclipse et le système de build Ant pour développer son app. Ce dernier étant basé sur des fichiers XML, il fallait passer par des scripts externes dès qu'il fallait ajouter un peu de logique à la construction de l'app. En 2014, l'expérience de développement connaît une avancée majeure avec l'arrivée d'Android Studio et le système de build Gradle. Basé sur le langage Groovy, Gradle permet de coder une logique de build aussi complexe que nécessaire et a engendré tout un écosystème de plugins.
Cependant, Groovy étant un langage à typage dynamique, il est compliqué d'y implémenter une auto-complétion pertinente. De plus, certains problèmes ne sont visibles qu'à l'exécution du programme. Depuis la sortie d' Android Gradle Plugin 4.1 en 2020, il est possible d'écrire les scripts Gradle directement en Kotlin.
On peut donc écrire ses scripts de build avec la même syntaxe que le reste de l'application et on a accès à toute la puissance de Kotlin pour le faire. Le typage fort permet de découvrir la syntaxe possible en fonction du contexte dans lequel on se trouve, même si les concepts de Gradle se passent difficilement d'avoir à consulter la documentation.
Sur le plan technique, l'interopérabilité est assurée. Cependant, l'intégration d'un plugin non documenté pour cette nouvelle syntaxe, exploitant la dynamique de Groovy, peut poser quelques difficultés. De plus, il est regrettable que les applications générées avec Android Studio continuent d’utiliser des scripts en Groovy, qu'il faudra convertir à la main en KTS.
NOTRE POINT DE VUE
Malgré ces légères contraintes, il est important de noter que de plus en plus de projets adoptent chaque jour KTS, qui devient le nouveau standard vers lequel migrer, sans réelle urgence, mais si l'occasion se présente.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Les frameworks UI suscitent souvent des débats : templates externes ou implémentation programmatique, outil graphique pour la conception ou écriture manuelle ? La technologie historique de mise en page visuelle d’Android ne fait pas exception. Elle présente un cycle de vie délicat à maîtriser et peut être lourde lors de la création de nouveaux composants graphiques. De plus, conçues au milieu des années 2000, les APIs graphiques tenaient compte de contraintes obsolètes pour les smartphones actuels, ce qui limitait l’évolution d’Android.
Les équipes de Google sont reparties d’une feuille blanche pour créer Jetpack Compose, en adoptant une API déclarative et réactive, inspirée par le framework React. Le code est plus lisible, avec une structure proche de ce qui est affiché, et plus concis : la complexité de la mise à jour de l’état de l’UI est masquée. Jetpack Compose est une technologie complexe : l’intégration s’appuie sur un plugin du compilateur Kotlin, un moteur de calcul de différences et de nombreuses bibliothèques de composants. En effet, l’intégralité des composants du design system Material a été ré-implémentée pour Compose.
La maturité du framework est impressionnante. Les cas d’usage courants sont documentés, facilement implémentables, tout comme les solutions pour les cas limites. Il peut toutefois manquer certaines fonctionnalités par rapport aux anciens composants (ex : sur les animations des listes ou la sûreté de typage de la navigation). Il est regrettable de devoir dépendre de versions non finales des bibliothèques de support, dont les APIs peuvent changer rapidement, pour utiliser les dernières version des composants et bénéficier des dernières fonctionnalités. Cependant, la communauté des développeurs reste enthousiaste et produit régulièrement des articles et des bibliothèques complémentaires.
NOTRE POINT DE VUE
Jetpack Compose est aujourd’hui un choix sûr pour développer une nouvelle application sur Android. Attention en revanche à la migration d’une app existante : si Jetpack Compose s’intègre très bien avec des sources de données réactives (ex : un ViewModel avec LiveData, RxJava ou Flow), l’intégration sur une base de code monolithique et impérative pourrait nécessiter d’importantes modifications.
HISTORIQUE 2022
Adopt - Voir le Tech Radar 2022
La sérialisation d'objets est cruciale en développement logiciel pour la gestion de systèmes distribués, des services web et l'échange d'informations entre différentes plateformes.
Des solutions populaires comme Gson, Moshi ou Jackson, fonctionnent bien sur la JVM et permettent de tirer parti de la reflexion. Développé par JetBrains, KotlinX Serialization se distingue par sa simplicité, sa compatibilité multiplateforme et sa prise en charge des types Kotlin, y compris la nullabilité et les sealed class.
KotlinX Serialization supporte d'autres formats que JSON, comme Protobuf, CBOR, Hocon et Properties. La librairie est performante, légère, sans dépendance sur la reflexion et utilise un plugin de compilation pour générer les sérialiseurs/désérialiseurs. On regrette cependant que l'adapter de KotlinXSerialization pour Retrofit2, développé par Jake Wharton, soit encore externe au repository de Retrofit, mais celui-ci vient de se stabiliser, il va donc rejoindre les autres adapter officiels.
Bien que Gson, Moshi ou Jackson soient populaires et puissants, KotlinX Serialization est performant, léger, offre une meilleure intégration avec Kotlin et est compatible multiplateforme.
NOTRE POINT DE VUE
Si vous êtes satisfait de votre solution actuelle, inutile de changer immédiatement. Cependant, si vous démarrez un nouveau projet Kotlin ou si votre projet nécessite de tirer parti de ces avantages, KotlinX Serialization est aujourd'hui la bibliothèque que BAM utilise sur tous ses nouveaux projets.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Avant l’arrivée de SwiftUI, il existait deux alternatives pour faire de l'UI en iOS :
En 2019, Apple a publié SwiftUI, un nouveau framework déclaratif dans la même tendance que Jetpack Compose. Ce framework est également requis pour certaines nouveautés ou améliorations, comme les widgets ou les animations iOS.
Il présente de nombreux avantages : d’une part, la syntaxe est claire et simple, ce qui facilite la montée en compétence ; d’autre part, l’écosystème bénéficie d'un soin particulier d'Apple, avec des outils dédiés directement intégrés à XCode. Il permet également de profiter de l'écosystème préexistant. En effet, SwiftUI est aisément interopérable avec UIKit et Combine, facilitant la transition vers ce nouveau framework.
En revanche, SwiftUI présente encore quelques lacunes. Certaines APIs ne sont pas encore accessibles sous SwiftUI et nécessitent un bridge vers UIKit. De plus, le framework étant récent, des bugs apparaissent régulièrement et doivent être contournés dans l'attente d'un correctif. Ceux-ci n'affectent généralement pas la production, mais peuvent offrir une expérience frustrante aux développeurs.
Cependant, le défaut majeur de SwiftUI est bien l'absence assumée de rétrocompatibilité avec les anciennes versions des OS. Cette stratégie pousse à abandonner le support de versions plus anciennes mais surtout limitera l'adoption du framework tant qu'utiliser des nouveautés sera synonyme de laisser des utilisateurs sur le carreau. Certaines APIs comme les lazy grids ou les previews stables que nous considérons essentielles ne sont disponibles qu'à partir d'iOS 14, ce qui nous pousse à considérer cette version d'iOS comme le minimum requis pour un projet SwiftUI.
NOTRE POINT DE VUE
SwiftUI est un framework que nous recommandons si la version minimale supportée par votre application est iOS 14, ce qui permet de couvrir 93% de la population française.
HISTORIQUE 2022
Adopt - Voir le Tech Radar 2022
Les outils de développement iOS sont vétustes : le format "xcodeproj", pour un simple nouveau projet induit 344 lignes incompréhensibles (cela peut monter à 3000 lignes ou plus). Impossible de l'éditer à la main et donc de le review. Et à plusieurs développeurs, les conflits git sont inévitables. Il est donc impossible de l'éditer à la main et de le review. Aussi, à plusieurs développeurs, les conflits git sont inévitables.
Tuist propose de ne plus versionner ce projet "xcodeproj", mais de versionner une configuration en Swift qui le génère à la volée. Sur un de nos projets, nous passons par exemple de 1788 lignes de code à 19 lignes. Le fichier est bien plus lisible, et les conflits disparaissent.
Tuist aide à la modularisation. Pour un projet en architecture micro framework, il automatise la création de liens entre les projets dans un même espace de travail, génère un graphe de dépendances afin de documenter le projet et propose un cache afin d'optimiser la compilation.
Tuist accélère le développement. En une commande qui échafaude l'architecture de fichier, on génère le squelette d'une page, d'un appel API... Tuist permet également de générer un accès typé aux assets (images, vidéos, sons, etc.) afin d'éviter un crash due à une erreur de nom de fichier.
La communauté de Tuist est très active et les développeurs sont réactifs, ce qui permet de résoudre rapidement les problèmes et de contribuer facilement.
NOTRE POINT DE VUE
La migration d'un projet existant vers Tuist est assez simple : nous avons migré un de nos plus gros projets (comprenant 1600 fichiers et 50 frameworks) en quelques jours. Nous recommandons l'adoption de Tuist pour tous les nouveaux projets et la migration des projets existants.
HISTORIQUE 2022
Trial - Voir le Tech Radar 2022
SwiftUI introduit de nouvelles fonctionnalités pour l'UI par rapport à UIKit, ainsi que pour la gestion de l'état et du cycle de vie des composants grâce à son approche réactive.
Il offre des ObservableObjet et des EnvironmentObject pour externaliser le state. Ces primitives de code sont très puissants, mais nécessitent une architecture bien pensée pour tirer pleinement parti de leur potentiel.
C'est pourquoi nous nous sommes tournés vers The Composable Architecture (TCA) : une architecture très inspirée du "one-way data flow" de Redux, qui vise à structurer le state, le rendre testable et facilement réutilisable. Son objectif est également d'améliorer l'expérience de développement en liant tous les changements de state à des actions utilisateur.
Contrairement à des bibliothèques concurrentes comme ReSwift, TCA est conçu pour SwiftUI. Il propose également des mécanismes d'injection de dépendances intégrés qui facilitent le développement. Les créateurs de TCA ont bâti une communauté active et ont produit de nombreux tutoriels ainsi qu'une doc complète, ce qui permet de lisser la courbe d'apprentissage. Elle reste cependant volumineuse, ce qui nécessite une exploration préalable, et son accès est payant. De plus, TCA est très opiniâtre dans sa gestion du state, ce qui complique parfois son intégration avec le reste de l'écosystème iOS.
Bien que ces problèmes puissent être contournés facilement, la bibliothèque est encore récente et présente certaines lacunes :
Pour l'instant, nous utilisons TCA avec prudence dans nos projets, en attendant de voir si ce framework souffre des mêmes problèmes de scalabilité que Redux.Nous avons cependant hâte de la sortie de la première version stable, qui embarquera une meilleure gestion de la navigation ainsi.
NOTRE POINT DE VUE
Chez BAM, nous utilisons The Composable Architecture sur des projets en production et nous vous recommandons de regarder cette bibliothèque pour la gestion du state sur vos prochaines apps en SwiftUI.
HISTORIQUE 2022
Assess - Voir le Tech Radar 2022
L'injection de dépendances (DI) est un design pattern très utilisé en développement, qui permet de faciliter les tests, de rendre le code plus modulaire et d'améliorer la maintenabilité. Hilt est un framework d'injection de dépendances pour Android qui a été publié par Google en 2020. Il est basé sur Dagger 2, la célèbre bibliothèque d'injection de dépendances, et fournit une mise en œuvre simplifiée de l'injection de dépendances dans les apps Android.
L'un des problèmes clés résolu par Hilt concerne le code boilerplate nécessaire pour configurer Dagger, pour l'injection de dépendances dans les apps Android. Dagger, bien qu'il soit puissant, peut être complexe à configurer. Hilt simplifie ce processus en fournissant un ensemble d'annotations, qui peuvent être utilisées pour marquer les classes à injecter et générer automatiquement le code Dagger sous-jacent. Cela permet aux développeurs de se concentrer sur l'écriture de la logique métier plutôt que de se soucier des subtilités de Dagger.
Hilt et Dagger résolvent les dépendances lors de la compilation, tandis que Koin est un localisateur de services, qui le fait là l'exécution. Cette différence a un certain impact sur les performances de l'app à l'exécution. Cependant, les bibliothèques d'injection de dépendances au moment de la compilation peuvent complexifier la création d'une architecture micro-frontend pour votre app, tandis que les localisateurs de services peuvent faciliter cette tâche.
Nous avons déjà mentionné Koin dans notre précédent Radar. Nous déconseillons de tenter de remplacer Koin par Hilt dans une codebase existante et volumineuse.
NOTRE POINT DE VUE
Lorsque vous démarrez un nouveau projet, essayez Hilt si vous souhaitez éviter les erreurs à l’exécution et suivre les conseils de Google. Sinon, optez pour Koin si vous souhaitez une bibliothèque légère, simple d’utilisation et compatible avec les projets Kotlin Multiplatform. Nous vous conseillons d’ajuster votre choix en fonction de votre équipe, de votre environnement et de vos plateformes.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Le pattern d'injection de dépendance est largement utilisé pour appliquer le principe d'inversion de contrôle, lors du développement d'applications Android. En effet, cela permet de rendre le code plus modulaire, maintenable et facile à tester. Cependant, la mise en place de l'injection de dépendance peut être fastidieuse.
Koin répond à tous ces enjeux avec une configuration des dépendances directement dans le code via un DSL très intuitif et simple à utiliser. Cependant, il répond au même besoin que le framework recommandé par Google pour Android : Dagger-Hilt.
Les deux fonctionnent très différemment. Koin gère l'injection des dépendances au runtime, alors que Hilt se configure via les annotations standard de Java pour l'injection, génère du code et injecte les dépendances directement lors de la compilation.
Hilt sera donc plus performant au runtime et pourra détecter les erreurs dès la compilation, tandis que Koin n'impactera pas la compilation mais risque d'émettre des exceptions au runtime s'il est mal configuré. En pratique, l'impact de Koin au runtime est minime si ce n'est négligeable.
NOTRE POINT DE VUE
Maintenant que Hilt a gagné en maturité, le choix entre les deux n'est pas évident. En fonction des besoins, il est recommandé de privilégier Koin pour sa simplicité d'utilisation, son intégration parfaite au sein de l'écosystème Kotlin et sa compatibilité avec Kotlin Multiplatform, ou Hilt pour ses performances élevées au runtime, son respect des standards et la détection des erreurs à la compilation. Néanmoins, le choix final doit être adapté aux préférences de l'équipe et aux besoins spécifiques du projet.
HISTORIQUE 2022
Adopt - Voir le Tech Radar 2022
Le stockage des données dans l'application revêt une grande importance. Afin d'améliorer l'expérience utilisateur et d'éviter les temps d'attente pour les résultats de requêtes, il est recommandé de mettre en place un système de cache. Les bases de données relationnelles offrent de réels avantages pour cet usage :
Sur mobile, SQLite s'est imposée comme la solution pour faire des bases relationnelles. Cependant, il est fortement déconseillé d'utiliser directement cette technologie que ce soit pour des raisons de complexité ou de typage. Il est alors courant d'utiliser un ORM (Object-Relational Mapping) : une librairie faisant l'interface entre une base de données et le reste du code.
Dans le contexte d'Android, Google a créé et intégré Room dans Android Jetpack, un ensemble de bibliothèques visant à simplifier la tâche des développeurs. Avec Room, il est possible de déclarer facilement toute la structure de la base de données et les différentes requêtes en quelques lignes de codeKotlin, avec des annotations.
Room est une librairie mature, existant depuis 2018, qui bénéficie d'une documentation complète et est facile à utiliser. Elle s'intègre facilement en Kotlin et offre la possibilité de faire des opérations réactives. Par exemple, lorsqu'une table est modifiée (ajout, modification ou suppression de lignes), Room émet automatiquement une nouvelle valeur, permettant aux composants de se mettre à jour.
Cette fonctionnalité est compatible avec les bibliothèques réactives les plus courantes, telles que :
Il existe des concurrents sérieux à Room, tels que SQL Delight ou Realm, qui proposent une version compatible avec Kotlin Multiplatform, ce que Room ne propose pas.
NOTRE POINT DE VUE
Vous devriez prendre le temps de comparer Room avec ses concurrents, mais l'utilisation de Room sur votre projet nous semble sans risque, à moins que vous envisagiez un projet Kotlin Multiplatform.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Il y a quinze ans, Adrian Cockcroft, architecte chez Netflix, a introduit la notion d’architecture microservice. Le but : minimiser la friction des équipes "serveur". Au programme : une séparation des responsabilités, un stockage optimisé et une plus grande agilité du côté des équipes de développement.
Aujourd’hui, les applications mobiles rappellent de plus en plus les applications serveurs par leur stockage relationnel en local, la complexité croissante de leur features ou encore les interconnexions avec de multiples services.
Les problèmes de développement relatifs aux applications mobiles et serveurs sont également similaires : base de code grandissante, temps de build croissant, difficulté à respecter la pyramide des tests.
C’est ainsi que des ingénieurs de plusieurs entreprises, telles que Soundcloud et JustEat ont popularisé l’approche de micro-features (ou micro-applications) en remplaçant un monolithe par de plus petits modules de différents types :
Les avantages sont multiples. Si les modules sont bien découpés, il est possible de développer sur un périmètre plus petit. Cela implique des logiques métiers plus facilement testables ainsi qu’un temps de build diminué grâce au cache.
Par ailleurs, si l’équipe s’agrandit ou que l’entreprise développe d’autres produits, il sera possible de mutualiser du code commun entre les différents projets (par exemple, les modules d’authentification).
Mais un bon découpage des modules implique une bonne expertise du domaine métier. À titre d’exemple, il faut particulièrement travailler l’interface pour augmenter la cohérence et diminuer le couplage de chaque module avec les autres. Cela demande également une connaissance de l’architecture ainsi qu’ une bonne conception, en plus d’un investissement initial.
Et comme pour les micro-services, un outillage spécifique devient nécessaire pour éviter que le rêve ne tourne en cauchemar. Il suffit que l’architecture soit mal implémentée, ou l’équipe non formée, pour que l’architecture ralentisse le projet au lieu de l’accélérer.
Un avantage du développement mobile est le packaging des micro-features en un seul binaire, contrairement aux micro-services en web. Par ailleurs l’outillage devient de plus en plus stable : par exemple, Tuist aide sur iOS.
NOTRE POINT DE VUE
Chez BAM, les micro-features sont devenues un choix de référence dans les nouveaux projets iOS. Nous avons pu tester à quel point cette architecture permettait de simplifier les évolutions ou refonte partielle d'une grosse application dans le domaine de la santé.
HISTORIQUE 2022
Assess - Voir le Tech Radar 2022
Pour rendre un code maintenable et testable, l’injection de dépendance permet de déterminer de manière dynamique et configurable quelle implémentation concrète sera utilisée à l’exécution.
Dans la précédente édition de ce radar, nous vous conseillions d'utiliser Resolver pour l'injection de dépendances, un framework "moderne" créé par Michael Long et utilisant les Property Wrapper de Swift 5.1.
L'écosystème de l'injection de dépendances a évolué depuis, et Michael Long a créé Factory une nouvelle librairie qui remplace Resolver. Elle est d'après l'auteur, plus rapide, plus petite et plus simple à utiliser. Mais surtout elle devient safe au compile time : alors que Resolver s'attend à ce que les dépendances soient injectées au "runtime" et émet une erreur si ce n'est pas le cas, Factory permet de vérifier au "compile time" que toutes les dépendances sont bien injectées. C'est un gros plus pour la qualité du code, mais cela complexifie la mise en place d'une architecture en micro framework.
Récemment, l'auteur a sorti une version 2.0 de Factory qui permet de déclarer des containers d'injection de dépendance. La notion est subtile, mais elle permet de réaliser l'inversion de contrôle, non plus avec le pattern "Service Locator" comme "Resolver", mais avec le vrai pattern "Dependency Injection". Utiliser une vraie injection de dépendances par container diversifie théoriquement les cas d'usages : s'il est toujours possible de faire ce que faisaient Resolver ou Factory 1.x, d'autres cas d'usages sont possibles, en particulier pour l'injection de vue SwiftUI.
NOTRE POINT DE VUE
Il y a donc beaucoup de changements sur Resolver / Factory mais la direction que prend l'auteur est claire : rendre Factory plus adapté pour des projets en SwiftUI et plus documenté. Le contrecoup : une API plus complexe, en particulier dans le cadre d'une architecture micro-frontend. Nous vous conseillons donc de suivre les évolutions de Factory pour vos projets en SwiftUI, mais de rester sur Resolver pour vos applications UiKit.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Anciennement, le développement de widgets sur Android excluait l'utilisation de Jetpack Compose, obligeant les développeurs à recourir à RemoteViews (une interface utilisateur légère et modifiable depuis un processus externe à l'application principale) et un code XML complexe. Ce processus rendait la création et la maintenance des widgets laborieuse et moins intuitive.
S'appuyant sur le runtime de Jetpack Compose, Glance offre une API déclarative pour faciliter la création d'interfaces utilisateur de widgets. Parmi les fonctionnalités clés de Glance figurent notamment la gestion du state et une intégration simplifiée avec d'autres bibliothèques Jetpack, telles que Jetpack DataStore pour la gestion des données. De plus, Glance permet l'interopérabilité avec RemoteViews en les enveloppant dans AndroidRemoteViews. Il permet enfin de définir comment un widget doit réagir lors du redimensionnement, grâce à l'introduction de SizeMode, qui résout une importante difficulté que l'on rencontrait sur les projets avant Glance, en proposant trois options : Single, Exact et Responsive.
NOTRE POINT DE VUE
Il convient de souligner que Jetpack Glance est toujours en version Alpha et n'est pas complètement stable. Les développeurs souhaitant utiliser cette bibliothèque devraient l'essayer sur des projets non critiques afin d'évaluer sa maturité et sa pertinence pour leurs besoins spécifiques.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Les plateformes mobiles iOS et Android ont toujours été incompatibles entre elles : Elles n’utilisent ni le même langage (Kotlin vs Swift), ni le même environnement d’exécution (Machine Virtuelle vs exécution native sur iOS) ni les mêmes APIs (frameworks propre à chaque OS). Bien qu’il ait toujours été techniquement possible de partager du code entre les 2 plateformes via les Foreign Function Interface (FFI) des langages, ces dernières ne sont utilisées que pour le code de certaines bibliothèques (ex : SQLite est utilisable sur iOS et Android) et très rarement pour le code applicatif.En effet, le code métier d’une application expose souvent un modèle de données complexe et de nombreuses fonctions qu’il est très fastidieux d’interfacer via les FFIs.
La promesse de Kotlin Multiplatform Mobile est de pouvoir écrire le code métier et les couches de données (ex : la sérialisation JSON ou les DTOs d’une base de données locale) en Kotlin et d’exposer ces implémentations via une bibliothèque consommable par chaque plateforme (un .aar pour Android et un .framework pour iOS). Le framework assure la traduction des appels et des structures de données de Swift vers Kotlin et vice-versa. On bâtit ainsi une sorte de SDK dédié à l’application, sur lequel il ne reste qu’à implémenter le code propre à chaque plateforme (en particulier l’UI).
Nous avons consacré plusieurs semaines à cette technologie pour l'évaluer et avons également publié plusieurs bibliothèques l'utilisant. Avec un peu de maîtrise on peut créer un cœur commun aux deux plateformes et consommer la même API. Si on est prêt à quelques concessions (quelques features de Swift ne sont pas supportées et il faudra faire appel à des bibliothèques externes pour l'interopérabilité des coroutines par exemple) Kotlin Multiplatform répond aux attentes.
Depuis Octobre 2022, KMM est maintenant en bêta, et se dote d'un nouveau modèle mémoire pour la partie native pour remplacer l'ancien, qui était très controversé car compliqué à prendre en main pour les développeurs habitués à Kotlin/JVM. Kotlin Multiplatform permet aux applications adressant nativement iOS et Android de partager du code entre elles. Cela peut être fait de manière graduelle, et même une application complètement écrite en KMM permet d'implémenter les API natives de ces OS si nécessaire. Cependant, l'éco-système KMM est encore incomplet et manque de stabilité, ce qui nous bloquerait pour démarrer un projet entièrement basé sur cette technologie.
NOTRE POINT DE VUE
Nous avons fait évoluer KMM de “hold” à “assess” et allons continuer d'expérimenter régulièrement avec cette technologie. Cependant, le support de Jetpack Compose pour iOS qui vient d'être annoncé ne serait-il pas l'élément manquant pour que cette technologie décolle réellement ?
HISTORIQUE 2022
Hold - Voir le Tech Radar 2022
Les APIs de lecture de média sur Android telles que Jetpack Media, Jetpack Media2 et ExoPlayer, ont été développées indépendamment, avec des objectifs différents et des fonctionnalités qui se chevauchent. Les développeurs Android devaient non seulement choisir la bibliothèque à utiliser, mais aussi écrire des adaptateurs lorsque des fonctionnalités de plusieurs API étaient nécessaires.
Jetpack Media3 résout ce problème en fusionnant et en affinant les fonctionnalités communes de ces API existantes, notamment l'interface utilisateur, la gestion de la lecture et les sessions médias, en une seule API plus cohérente et facile à utiliser, tout en tirant parti des fonctionnalités améliorées et des meilleures pratiques de développement.
L'interface de lecture d'ExoPlayer a également été mise à jour, améliorée et rationalisée pour servir d'interface de lecture commune pour Media3.
NOTRE POINT DE VUE
Media3 est actuellement en version bêta, nous conseillons donc d'envisager de l'adopter pour les nouveaux projets et de préparer la migration pour les projets existants utilisant les API de gestion des médias précédentes. Chez BAM, nous avons attendu cette migration avec impatience, car nous avons éprouvé des difficultés avec les anciennes APIs et nous allons pouvoir la tester sur le prochain projet média.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Les tests de snapshot sont de plus en plus répandus sur les projets Frontend et en particulier mobiles. Ils permettent une forme de tests unitaires sur une partie du code qui est souvent difficilement testable unitairement. C'est en particulier le cas sur Android où le code utilisant le framework est peu ou pas utilisable dans le contexte d'un test unitaire (et donc pas sur un device). Le framework Android propose des méthodes pour réaliser des tests d'UI, mais elles nécessitent de faire tourner ces tests sur des devices (réels ou émulés) ce qui consomme beaucoup de ressources en CI et est complexe à mettre en œuvre.
Paparazzi propose une solution élégante et inédite à ce dernier problème : Instancier des View Android sans nécessiter de device ou d'émulateur. En interne, Paparazzi utilise notamment une partie du code qu'Android Studio met en œuvre pour proposer des prévisualisations de Layout. On obtient des rendus bitmap pour chacune des configurations sélectionnées. Une première utilité est la prévisualisation du rendu des écrans sans avoir à tester le code sur différents devices. Mais le gros intérêt est de pouvoir facilement dérouler des tests de non-régression visuelle. Paparazzi propose un framework complet pour dérouler ce type de tests, générer les écrans de référence et détecter les écarts par rapport à celles-ci.
Nous avons intégré cette bibliothèque à plusieurs de nos projets Android et c'est vraiment le bon outil pour nos tests de non-régression visuelle (sans pour autant remplacer les tests unitaires). Cependant comme elle repose sur un détournement de l'API interne d'Android Studio elle peut être sujette à régressions et problèmes, comme ce fut le cas avec Jetpack Compose 1.2 ou Android API 33 qui n'ont pas été supportés pendant plusieurs mois par la version release de Paparazzi. Sur les écrans complexes, on peut aussi rencontrer des problèmes en cas de recomposition (par exemple avec des composants qui modifient leur état provoquant une recomposition) sur le même écran.
NOTRE POINT DE VUE
Ce genre de problème pourrait empêcher une montée de version majeure de la version d'Android ou de Jetpack Compose, et c'est pourquoi nous vous conseillons d'intégrer cette bibliothèque avec précaution.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Que ce soit pour optimiser le temps de compilation ou pour organiser un projet de taille importante, il est maintenant très courant d'avoir des projets modulaires en Android. Cependant et jusqu'à peu, Gradle ne proposait pas de méthode standard pour centraliser la déclaration des dépendances et de leurs versions. Plusieurs pratiques co-existaient dans la communauté à ce sujet, mais aucune n'était vraiment satisfaisante pour ce qui est de faire monter les versions des dépendances et beaucoup empêchent de fonctionner les suggestions de l'IDE quant aux nouvelles versions. On se retrouve alors à naviguer sur le site de chaque dépendance ou bien Maven pour vérifier si une nouvelle version est disponible.
RefreshVersions propose une solution élégante à ce problème : vérifier sur Maven si de nouvelles versions de chaque dépendance sont disponibles et l'indiquer en commentaire dans un fichier qui centralise les versions des dépendances. Libre au développeur de sélectionner la dernière version disponible d'une dépendance, en commitant une modification de ce fichier central.
refreshVersions propose également un catalogue intégré de la plupart des dépendances courantes ce qui permet de les découvrir via l'auto-complétion lorsque l'on ajoute une dépendance à un module. Saluons également l'outil de migration intégré qui permet d'adopter l'outil en quelques minutes si le projet a une structure classique. Dommage cependant que l'outil commence tout juste à supporter les fichiers Gradle Catalog qui est la nouvelle solution poussée par Gradle pour centraliser la déclaration des dépendances et ne permet pas de se baser uniquement sur celui-ci.
NOTRE POINT DE VUE
Ce projet mérite d’accroître sa notoriété et doit encore évoluer pour s'intégrer dans un maximum de projets existants. Cependant si l'outil de migration fonctionne pour votre projet, il vous fera déjà gagner un temps précieux. En phase avec la philosophie du projet (c'est au développeur de sélectionner les bibliothèques à mettre à jour), nous avons adopté cet outil sur tous nos nouveaux projets Android.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Lorsque l'on teste un programme, il est difficile de tester plus que la logique unitaire sans faire de test end-to-end. Ces derniers sont souvent coûteux en temps et peuvent se révéler difficiles à maintenir lorsque le produit change beaucoup.
C'est avec l'objectif de trouver un juste milieu entre ces deux approches que les tests de snapshots ont été imaginés puis appliqués aux technologies web. Leur usage se répand de plus en plus et c'est justement ce que promet la librairie swift-snapshot-testing. Elle permet en effet de prendre des captures d'écran ou de l'arborescence de rendu d'une application iOS native (SwiftUI ou UIKit).
Cela permet de fournir des tests d'affichages et de non-régression efficaces à moindre frais, la librairie étant facile à installer et configurer, tandis que les tests eux-mêmes sont rapides à mettre en place. C'est d'autant plus vrai qu'il est possible de paramétrer le test pour prendre des captures de plusieurs formats différents automatiquement, ce qui est utile pour s'assurer que le rendu est bien celui auquel on s'attend.
Également, nous observons que swift-snapshot-testing n'introduit pas de perte de performance lors des phases de compilation ou de test.
En revanche, la librairie souffre de plusieurs défauts, notamment de différences de rendu entre les architectures Intel et ARM. Cela pousse à baisser la précision des tests ou à ne développer l'application que sur une seule architecture du processeur (ce qui s'applique également aux fournisseurs de CI). Il est également assez difficile de tester certaines librairies tierces en fonction de leur recours aux animations, bien que cela soit de mieux en mieux supporté.
NOTRE POINT DE VUE
Chez BAM, nous avons utilisé swift-snapshot-testing sur plusieurs projets, en lancement ou existants, avec succès. Cela nous a permis et nous permet encore de nous prémunir de régressions visuelles ou de nous assurer que nos designs correspondent aux attentes sur tous les appareils cibles. Cependant, bien qu'ils ne soient pas majeurs, ces divers problèmes nous empêchent de recommander cette librairie aveuglément.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
JUnit est le framework de test unitaire le plus répandu pour Java, et par extension pour les autres langages de la JVM, dont Kotlin.
Introduit en 2017, JUnit 5 propose une nouvelle API plus lisible et permettant d'écrire des tests paramétrés de manière efficace. Malheureusement cette version n'est toujours pas supportée officiellement par la plateforme Android. Des ports non-officiels existent, par exemple android-junit5. Prise en isolation, cette bibliothèque fonctionne très bien et permet de profiter de la nouvelle API sur votre projet.
Cependant la plupart des autres bibliothèques utilisables pour les tests unitaires (Jetpack testing et Paparazzi par exemple) ne supportent pas l'API de JUnit 5.
Il y a ainsi de grandes chances qu'au cours de votre projet vous ayez à utiliser ce genre de dépendances, ce qui vous forcera à utiliser JUnit 4 pour les tests qui en dépendent, entraînant une complexification de la configuration du projet.
NOTRE POINT DE VUE
Pour ces raisons évoquées, nous ne vous conseillons pas d'utiliser JUnit 5 tant que Google n'en propose pas un support officiel pour Android.
HISTORIQUE 2022
Il s'agit d'un nouveau blip cette année.
Anciennement appelé AsyncDisplayKit, Texture est un framework créé par Facebook et dont le développement est assuré par Pinterest.
Il permet de définir des composants visuels et de les agencer avec des flexbox. Le framework est très performant et succinct par rapport à UIKit, et il est facile de le connecter avec des composants UIKit existants. Lorsque Swift UI était encore récent (arrivé sur iOS 13 et plus abouti à partir d'iOS 14), Texture était une bonne alternative pour avoir des flexbox sans sacrifier la compatibilité des devices les plus anciens. Nous avons alors choisi de l'utiliser chez BAM.
Toutefois, Texture possède plusieurs inconvénients. Le code nécessaire pour l'affichage est certes moins verbeux que UIKit, mais il reste plus long et complexe qu'avec Swift UI. La documentation disponible est très lacunaire et il peut arriver de ne pas comprendre pourquoi quelque chose ne marche pas. Enfin, l'activité de cette librairie est désormais très faible : la dernière mise à jour date de septembre 2021 et peu de sites hors la documentation officielle proposent des ressources.
Swift UI étant désormais disponible sur un grand parc d'appareils (iOS 14 et supérieurs étant utilisés par 94% des utilisateurs en mars 2023), nous vous conseillons de privilégier cette librairie graphique. Si toutefois, vous voulez assurer une forte compatibilité, nous vous recommandons de rester sur UIKit, l'effort pour passer à Texture étant trop important.
NOTRE POINT DE VUE
Si vous êtes actuellement sur un projet Texture, il n'est pas forcément nécessaire d'effectuer le changement dès aujourd'hui. C'est un compromis à trouver entre maintenir une uniformité dans le code et limiter les problèmes dus à Texture.
HISTORIQUE 2022
Assess - Voir le Tech Radar 2022
Retrouvez l'avis de nos experts sur les techniques, plateformes, outils, langages et frameworks associés aux principales technologies mobiles que nous utilisons au quotidien chez BAM : React Native, Flutter et Native.