
Remesh a opté pour la première façon de faire et partage son expérience
Lorsqu’il faut aborder de nouveaux projets, deux écoles s’affrontent chez les développeurs : certains préfèrent exploiter un code existant et l’adapter à de nouvelles fonctionnalités, tandis que d’autres préfèrent partir de rien bien qu’il y ait un code existant.
Joel Spolsky, un développeur et écrivain américain, fait partie de la première école. Pour lui, écrire un programme à partir de zéro est la pire erreur stratégique qu'un développeur puisse commettre. Dans un billet, il a énuméré plusieurs cas pour mieux se faire comprendre entre autres, le navigateur de Netscape qui n'existe plus aujourd'hui. Netscape 6.0 allait entrer dans sa première version bêta publique à l'époque en sautant la version 5.0. La version 4.0 fut sa dernière version majeure et avait été publiée trois ans plus tôt. Trois ans, c'est terriblement long dans le monde de l'Internet, déclarait Joel : « Pendant ce temps, Netscape était assis, impuissant, alors que sa part de marché s'effondrait », ajoutait-il. La cause, selon Joel, est que ses développeurs ont décidé de réécrire la base de code à partir de zéro.
Vingt ans plus tard, Nicholas Tietz-Sokolsky a publié un billet sur le blog d’ingénierie de Remesh où il vient remettre en cause cette philosophie ne serait-ce que par l’expérience même de Remesh :
« Notre histoire commence en janvier 2019. Remesh était alors une entreprise beaucoup plus petite. Nous avions récemment embauché quelques ingénieurs et nous avions 5 ingénieurs focalisés sur le produit, et une poignée d'ingénieurs focalisés sur l'apprentissage automatique (ML) ou DevOps. Malgré l'embauche récente de ces ingénieurs, notre vitesse était toujours douloureusement basse. L'ajout de fonctionnalités simples a pris du temps. Nous avons eu beaucoup de bogues dans le produit que nous avons simplement reconnu comme étant ‘connus’ et que nous n'avons pas corrigés. Et le produit dans son ensemble semblait n'avoir pas changé de manière significative depuis un certain temps.
« Il est important de comprendre pourquoi nous avons eu ces problèmes. Nous avons supposé (et après la réécriture, validé) que le problème ne venait pas de notre côté : après tout, nous avions embauché des ingénieurs talentueux. Le problème venait en grande partie notre base de code et notre processus. La base de code héritée dans laquelle nous travaillions n'était pas adaptée à la fois aux compétences de notre équipe et aux problèmes que nous résolvions, et notre processus encourageait et s'appuyait sur des connaissances cloisonnées: il n'y avait pas de ‘stack full’ à Remesh ».
L'état de la base de code de Remesh en janvier 2019
L’ancienne application de Remesh a été conçue à l'origine pour quelque chose de très différent de ce à quoi elle sert actuellement. Au départ, Remesh permettait aux utilisateurs de tenir des conversations bidirectionnelles entre des groupes entiers ou un individu et un groupe. Nicholas a illustré le premier cas d’utilisation (conversations bidirectionnelles entre groupes) en parlant des démocrates et des républicains qui se parlent pour trouver un terrain d’entente, le second (conversations bidirectionnelles entre des groupes et un individu) en parlant du maire d’une ville qui s’adresse à ses citoyens pour mieux comprendre leurs besoins.
« Cependant, comme nous avons trouvé l'adéquation au marché des produits, le cas d'utilisation a changé. Nous nous sommes penchés sur un modérateur singulier parlant à un groupe de personnes », a-t-il noté.
À la suite de ce changement, certaines anciennes décisions de conception n'avaient plus de sens et le schéma nécessitait des changements majeurs. Au-delà des problèmes de base de données, il reconnait que la base de code elle-même était assez difficile à comprendre, car les fonctionnalités avaient été boulonnées sans beaucoup de refactoring majeur : « nous avions une couverture de test très médiocre dans les zones qui avaient le plus besoin de refactoring car il s'agissait du code le plus ancien, écrit avant d'établir de bonnes pratiques de test ».
Au-delà de tout cela, les langages et frameworks utilisés ne marchaient pas avec leur équipe. La base de code backend a été écrite dans Elixir, que peu de leurs développeurs connaissaient très bien. L'une des bases de code frontend a été écrite dans une version très ancienne d'Angular et ils avaient deux autres frontend qui étaient en React : « peu de nos ingénieurs étaient à l'aise sur l’un d’eux, sans parler des trois. Les langages et les frameworks utilisés ne convenaient ni à notre équipe ni à notre problème, ce qui nous a un peu ralentis ».
Quelles étaient les options ?
À ce stade, Remesh a réalisé que sa base de code avait besoin d'un changement majeur. Dans ce cas de figure, trois options se posent à vous :
- Le refactoriser jusqu'à ce que le problème soit résolu
- Le réécrire d'une traite
- Le réécrire au coup par coup
« Pour le frontend, le refactoring n'était pas vraiment une option. Notre version d'Angular était suffisamment ancienne pour que, malheureusement, nous n'ayons pas vraiment de chemin de mise à niveau clair vers une version moderne d'Angular (de toute façon nous ne voulions pas être sur une version d'Angular). Et puisque nous anticipions des changements majeurs dans l'interface utilisateur et l'API, un refactoring ne serait pas réalisable. Donc, sur le frontend, nous devions décider entre réécrire d'un seul coup ou réécrire au coup par coup.
« Le back-end avait quelques problèmes que nous voulions résoudre - notre schéma, notre langage et notre base de code ne correspondaient plus au problème que nous résolvions. Nous avons utilisé Elixir pour son support massif de concurrence, pourtant nous n'en avons jamais eu besoin et cela a fini par nous porter préjudice : la façon dont la concurrence est gérée dans la machine virtuelle Erlang a rendu le profilage très difficile, car vous savez ce qui est calculé, mais pas d'où il est appelé - et bonne chance avec le réglage des performances. La base de code Elixir a également limité la contribution de nos ingénieurs ML à la base de code backend : ils travaillaient en Python tous les jours et n'avaient pas le temps de se plonger profondément dans Elixir. Pour faire court, nous voulions quitter Elixir et passer à Python, car alors toute notre équipe aurait pu contribuer, le langage prendrait en charge les problèmes et nous aurions plus de facilité à profiler le code ».
Au bout du compte, l’argument en faveur de la réécriture se résumait vraiment à cette confluence de facteurs :
- Remesh voulait que chaque membre de son équipe puisse contribuer à la base de code backend, et Python avait l’avantage d'avoir déjà une large adoption déjà au sein de l’équipe et d’être facile à apprendre
- L’ancienne base de code était si fragile et si peu testée que sa refactorisation serait un processus ardu.
- Remesh pouvait gagner en efficacité en passant à un framework « opinionated » comme Django, avec beaucoup de valeurs par défaut permettant de gagner du temps (comme Django Admin).
- Remesh voulait avoir l'opportunité de créer une toute nouvelle version influencée par ce que l’entreprise avait appris des clients et pourrait ensuite gérer la transition vers la nouvelle version plutôt que de mener une bataille pendant 12 mois avec beaucoup de clients à chaque changement.
« Pour arriver à cette décision, nous avons fait une planification assez approfondie », indique Nicholas qui note que l’équipe devait impérativement déterminer quel serait le niveau d'effort pour chacune de ces options. « Il est apparu assez rapidement que la réécriture de l'application en gros prendrait du temps, mais que sa refactorisation ou sa réécriture fragmentaire prendrait beaucoup plus de temps, il y avait beaucoup, beaucoup plus d'incertitude autour d'une telle approche. Si nous options pour la refactorisation, nous risquerions beaucoup plus ».
Autant d’éléments qui les ont conduits à tout réécrire : « nous étions déterminés à réécrire, car cela nous permettrait de corriger les erreurs des années passées, et cela nous permettrait de faire avancer le produit en même temps ».
Remesh a donc commencé à tout réécrire à partir de février 2019 « après avoir planifié les fonctionnalités que nous devrions inclure pour la parité des fonctionnalités avec la plateforme existante dans le cadre d'un effort de diligence raisonnable pour nous assurer que c'était la bonne voie ».
« Le processus réel de construction de la nouvelle version s'est déroulé sans heurts après un démarrage cahoteux. C'était douloureux pour tout le monde de passer à une nouvelle pile technologique. Bien que nous ayons choisi Python pour l'accessibilité de toute l'équipe, il y avait encore ceux parmi nous qui avaient besoin de l'apprendre. Et aucun de nos ingénieurs backend ou fullstack ne connaissait Django au départ (alors que notre ingénieur frontend principal le connaissait bien). De même sur le frontend, beaucoup d'entre nous connaissaient React, mais peu d'entre nous avaient une expérience approfondie avec TypeScript, vers lequel nous avons également choisi de migrer. Cela dit, après avoir eu un temps d'apprentissage initial, nous sommes tous devenus assez productifs assez rapidement et nous avons pu apprendre ensemble. Ce fut notre première validation : même avec moins d'expérience dans cette nouvelle pile, nous avons pu créer des fonctionnalités beaucoup plus rapidement. Il faudrait plus de temps pour s’assurer que les gains de productivité provenaient de la nouvelle pile et de la nouvelle base de code, plutôt que du fait que le projet soit entièrement nouveau, néanmoins nous y sommes finalement arrivés ».
Les leçons tirées de cette expérience
Après cette expérience, il a noté des leçons qu’ils ont tirées de leurs échecs pendant le processus, mais aussi de leurs succès :
« Nous avons réussi parce que nous avons commencé avec une vision claire de ce que nous construisions (un vrai MVP, où nous savions que l'ancien produit était «viable»), et nous y avons réduit la portée selon nos besoins afin de rester avec une vision claire. Bien que nous n'ayons pas livré « dans les temps » (d’ailleurs personne ne le fait), nous n’avons pas pris autant de temps que Netscape. La durée totale du projet était inférieure de deux fois au temps que nous avions prévu si nous avions fait une copie exacte (en termes de fonctionnalités) de l'ancien produit, mais nous nous sommes retrouvés avec quelque chose de bien meilleur et avec de nouvelles fonctionnalités très souhaitées, comme la possibilité de télécharger et d'envoyer des vidéos et la possibilité de télécharger un rapport PowerPoint généré automatiquement de votre conversation.
« L'une des autres clés de notre succès a été d'obtenir des commentaires tôt et souvent. Pendant la réécriture, nous avons utilisé le produit en interne très souvent, découvrant des bogues critiques et des problèmes de performances. Nous avons également organisé des démonstrations régulières pour l'ensemble de l'entreprise afin d'obtenir rapidement des commentaires du service customer success, ventes, recherche et éventuellement des premiers clients qui pouvaient tolérer les échecs.
Il a reconnu qu’ils se sont trompés parce qu’ils ont décidé de s’appuyer sur deux technologies que l’équipe n’avait pas beaucoup utilisées beaucoup : « nous avions déjà utilisé TypeScript dans un prototype, mais nous n'avions pas de connaissances approfondies à ce sujet. Tout s'est bien passé, mais nous ne sommes toujours pas...
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.