Et si Vim avait raison ?

le 20/11/2020 par Yannick Schini
Tags: Software Engineering

Cet article a pour objectif de vous partager une prise de conscience, agrémentée d’un maximum d’exemples concrets, qui je l’espère vous permettra de devenir un.e meilleur.e programmeur.euse. La réalisation que je cherche à transmettre étant le fruit d’un contexte, je vais vous exposer les différentes étapes qui m’y ont mené. Je vais commencer ce voyage en parlant de Vim et il sera à la base de beaucoup d’exemples, mais vous verrez que les enseignements que j’en retire sont bien plus généraux !

Dans le texte suivant, je vais souvent aborder la notion de productivité. Cette productivité, je la définis comme étant la quantité de modifications apportées dans une base de code pour un temps donné. J’ai tout à fait conscience que les activités d’un.e développeur.euse ne se limitent pas à écrire du code, et qu’écrire du code en quantité ne rime pas nécessairement avec qualité, ni avec production de valeur pour l’utilisateur. Toutefois, l'interaction avec une base de code reste une activité centrale pour les développeurs.ses, et si Accelerate nous a appris quelque chose, c’est que faire vite peut aussi permettre de faire bien !

Vim & les IDEs

vim_logo

Il y a quelques mois, j’ai décidé de passer d’IntelliJ à Vim en tant qu’outil principal de développement. Parmi les raisons qui m’y ont poussé, je peux citer pêle-mêle :

  • Le fait que j’étais amené à l’utiliser régulièrement lorsque je me connectais à des machines distantes en SSH, et la frustration qui se dégageait de ma lenteur dans ses tâches.
  • L’impression de fluidité et de vitesse incroyable quand je regardais Ly William Chhim, Vimeur averti, l’utiliser.
  • L’intégration de Vim au terminal qui collait bien à mon envie de “creuser un peu plus Linux”.
  • La réputation de Vim de permettre des gains de productivité une fois passée une période d’adaptation.

Et le mur que j’ai pris en pleine figure était à la hauteur de la réputation de Vim ! J’ai eu l’impression de ne plus savoir marcher. Ma connaissance de Vim s’arrêtant à “h,j,k,l” pour me déplacer, “i” et “esc” pour changer de mode et enfin “:wq” pour quitter, la transition fut difficile. Ma productivité s’est effondrée. Chaque modification, même triviale, me prenait un temps énorme. Et l’austérité de Vim out-of-the-box n’aide pas…

mur_en_briquesMes premiers jours sur Vim, une allégorie.

Après avoir hésité à abandonner environ 856 fois lors des deux premiers jours, j’ai fini par comprendre que si je voulais continuer d’utiliser Vim, il fallait que je développe un nouveau réflexe. Et mon ambition n’est pas seulement de retrouver ma productivité d’avant, mais de progresser !

Dans Vim, à chaque action “qui gratte”, que je trouve peu fluide, inutilement compliquée ou longue, je prenais quelques dizaines de secondes pour trouver une façon plus efficace de faire, commençant par les actions les plus basiques, pas à pas :

  • Je souhaite aller en fin de ligne, pour ça j’ai dû appuyer plein de fois sur “h” ou “l” ? Les trois touches “^”, “0” et “$” sont là pour ça.
  • Je veux ajouter de la configuration à la fin d’une ligne, je dois me déplacer en fin de ligne avant d’appuyer sur “i” pour passer en mode insertion ? “A” combine ces deux actions.
  • Je souhaite insérer une nouvelle ligne en dessous de la ligne actuelle, et pour cela je me suis déplacé en fin de ligne, mis en mode insertion, puis j’ai appuyé sur “entrée” pour revenir à la ligne et y écrire quelque chose ? “o” et “O” sont mes nouveaux amis.
  • Je dois remplacer un mot, un nom de variable ou de fonction par un autre et pour ça j’utilise “dw” pour effacer l’ancien puis “i” pour insérer le nouveau ? “ciw” est plus efficace.
  • ...

Je fais un aparté ici concernant l’aspect 100% clavier de Vim.

L’argument souvent mis en avant pour justifier l’abandon de la souris est celui de la limitation du changement de contexte : les yeux restent sur l’écran et ne cherchent pas la souris, les bras ne bougent pas, on reste dans le flow sans s’interrompre. Après plusieurs mois de pratique, je suis convaincu que cela apporte effectivement un gain.

Un second argument souvent avancé est la limitation d’une éventuelle fatigue, particulièrement si vous êtes les heureux possesseurs d’un clavier ergonomique. Personnellement, je n’ai pas senti de grande différence à ce niveau là.

Un argument supplémentaire que j’ai rarement vu cité est celui d’une vitesse accrue grâce à la mémoire procédurale, souvent appelée mémoire musculaire. Sur un clavier, la disposition des touches ne change pas. La distance d’une touche à l’autre ne change pas non plus. Et à force de réaliser les mêmes actions, nos muscles vont s’habituer et les réaliser “machinalement”. Evidemment, il est également possible de développer ces automatismes avec l’utilisation d’une souris, toutefois:

  • le fait d’utiliser la souris va impliquer l’articulation de l’épaule dans le mouvement, soit plusieurs degrés de liberté supplémentaires. Il me semble logique que plus le mouvement implique d'articulations et de degrés de libertés (i.e. est complexe), plus on va mettre du temps à l'assimiler. Les joueurs professionnels de jeux vidéo montrent qu'on peut tout à fait être extrêmement rapide et précis (et utiliser la mémoire musculaire) dans l'utilisation de la souris. Mais, sur la base de mon expérience, c'est beaucoup plus long pour en arriver à un même niveau d'automatisation musculaire pour une même action. C'est également ce qui semble être suggéré par les trois papiers que j'ai pu trouver à ce sujet.
  • au delà de la complexité intrinsèque du mouvement, l’utilisation de la souris va également introduire 2 sources de variabilité qui vont rendre le mouvement plus difficile : l'incertitude sur la position de la souris par rapport au clavier qui fait que le mouvement pour aller chercher la souris ne sera jamais 100% identique, et l'incertitude sur la position du curseur sur l'écran au moment ou la souris est prise en main (qui peut être une fois tout en haut à gauche de l'écran, une fois un bas, ...) qui fait que le mouvement pour aller cliquer sur ce qu'on veut ne sera jamais parfaitement identique non plus.

Dernier point, la souris a été créée afin de pointer des choses et de permettre l’utilisation de hiérarchies de fenêtres complexes avec une organisation spatiale qui rend la navigation au clavier compliquée. Ce n'est pas le cas de l'édition de texte qui est souvent en 2D, à plat sans trop de complexité hiérarchique.

Après avoir retrouvé un rythme décent sur toutes ces petites actions “unitaires” et appris à “marcher” dans Vim, j’ai continué à appliquer le même reflexe de remise en question et d'apprentissage continu à la suite de mon workflow, pour apprendre à “courir” dans Vim:

  • Devoir quitter Vim pour committer mes changements est long ? J’utilise un plugin pour interagir avec Git sans quitter Vim.
  • J’ai besoin de modifier d’autres fichiers de mon projet que celui que j’ai ouvert ? FZF me permet de trouver rapidement un fichier avec son nom.
  • Des opérations sur le File System à réaliser comme copier ou supprimer des fichiers ? NerdTREE.
  • La recherche textuelle à l’échelle du projet ? Ripgrep s’intègre à Vim et FZF.
  • L’autocomplétion ? Un autre plugin, qui permet également le “go to definition”, le renommage intelligent à travers le projet et d’autres fonctionnalités avancées.
  • Et bien d’autres…

Nota: au risque de verser dans le prosélytisme pro-Vim, je peux vous assurer que Vim est très extensible, et qu’énormément des fonctionnalités des IDEs “modernes” sont disponibles via l’écosystème de plugins de Vim !

Au fil des jours et des semaines, j’ai fini par reconstruire toutes les fonctionnalités dont j’avais besoin avec Vim. Cela m’a permis de retrouver, puis dépasser la productivité que j’avais précédemment: pour réaliser des User Stories de complexité et taille similaires, je passais moins de temps à coder qu’avant. Et c’est là que le temps passé, les efforts consentis, toutes les recherches faites commencent à se justifier. En effet, ayant assemblé toutes les fonctionnalités avancées d’un IDE moi-même, j’en connais le fonctionnement en détail et je peux l’adapter. Par exemple :

  • Je peux paramétrer la recherche de fichier pour prendre en compte ou ignorer les fichiers ignorés par Git ou les fichiers de mon venv, ou…
  • Je peux ajuster finement les règles d’indentation par type de fichier
  • Je choisis le language server que j’utilise pour les fonctionnalités avancées relatives à chaque langage et je peux le paramétrer finement (est-ce que mon serveur de langage Python ajoute des parenthèses lorsqu’il autocomplète le nom d’une méthode ?)
  • Je choisis les raccourcis claviers qui me sont le plus adaptés.

Et toute cette construction, cette configuration de Vim et de ses plugins, c’est du code ! A la différence d’autres artisans ou artistes (ébénistes, pâtissiers, peintres, etc.) nos outils à nous sont composés de la même “matière”, le code informatique, que celle qu’on travaille. On peut donc appliquer tout notre savoir-faire, toutes les bonnes pratiques que l’on applique quotidiennement sur nos projets à nos outils ! En effet nos outils sont un projet informatique, sur lequel on possède à la fois la casquette de PO, de développeur et d’utilisateur ! Ce code peut et devrait être versionné, refactoré régulièrement pour éviter l’accumulation de dette technique, et doit vivre en même temps que notre workflow par l’ajout et la suppression de fonctionnalités. Et on doit avoir le même niveau d’exigence vis-à-vis du code de nos outils que dans nos projets.

De la suite dans les IDE

Cette prise de conscience (être critique et exigeant vis-à-vis de nos outils qui ne sont finalement “que” du code) ne doit bien évidemment pas s’arrêter à nos IDEs. Notre travail ne s’effectue pas intégralement dans notre IDE. Toutes les actions que l’on réalise peuvent être améliorées pour plus d’efficacité : utiliser un raccourci facilement et rapidement accessible pour ouvrir notre IDE directement avec le bon fichier, comment on trouve le bon fichier, comment on interagit avec nos outils de communication, etc. Toutes ces actions font également partie de notre workflow et sont réalisées avec des outils informatiques. On peut donc également chercher à les optimiser !

Pour moi, c’est encore une fois via Vim et ses extensions que cette prise de conscience a eu lieu. A force d’utiliser FZF dans Vim, j’ai fini par coder quelques alias pour m’aider à utiliser le terminal plus efficacement. Puis, une chose en entraîna une autre... Prenons l’exemple tout simple du choix d’une branche Git. Initialement, mon workflow ressemblait à ça:

  1. Exécuter “git branch -a” pour lister mes branches
  2. Repérer la bonne branche dans la liste
  3. Exécuter “git checkout <nom_de_la_branche>”

Maintenant, il me suffit d’exécuter “gco” pour voir la liste des branches apparaître. Je peux sélectionner une branche via les flèches du clavier ou taper quelques caractères du nom de la branche (via de la recherche approximative), un appui sur entrée et c’est fini. Tout ça sans quitter le clavier des mains, et l’écran des yeux. Il me faut rarement taper plus de 6-7 caractères + 1 appui sur entrée pour arriver au résultat recherché.

Autre exemple, mes déplacements dans le terminal ont été énormément fluidifiés et accélérés par l’utilisation de z. Plus besoin de taper sur tab 5 ou 10 fois pour utiliser l’auto-complétion de cd quand vous voulez aller au fond de votre filetree. La majorité du temps, je tape les 5-6 premiers caractères du dossier que je cherche, j’appuie sur entrée et je suis exactement où je souhaite être.

Toutefois, comme mentionné en introduction, les tâches d’un.e développeur.euse ne se limitent pas non plus à l’édition de code ! Voici deux exemples supplémentaires, inspirés par des collègues, pour montrer que les bonnes pratiques décrites dans cet article s’appliquent plus largement:

  • Hugues Tavenard perdait du temps à retrouver l’adresse du Google Meet qu’il utilise le plus souvent et l’envoyer à ses collègues. Depuis qu’il s’est fait un alias qui met cette info dans son presse-papier, il n’a plus qu’à la coller.
  • Victor Nea a lui développé une commande qui va lancer Chrome et l’amener directement sur la MR de sa branche, ou sur la page de création de MR si sa branche n’en a pas encore. Cela lui évite de devoir ouvrir son navigateur, saisir l’adresse ou cliquer sur le favori, naviguer sur le bon projet, aller sur la page des MRs et enfin sélectionner celle liée à sa branche.

Encore une fois, tout ça n’est “que” du code. Et vous pouvez donc le versionner, le refactorer, etc. On entre là dans le monde des dotfiles ! Nommés ainsi parce que sur les systèmes Unix, les fichiers de configuration sont généralement trouvés dans le /home/ et préfixées d’un point “.”, “dot” en anglais, ce terme regroupe ainsi tous les fichiers de configuration des outils que vous utilisez. Votre configuration Vim ? Vos alias bash ? La configuration de votre linter ? Les variables d’environnements pour ripgrep ? Tout ça, c’est dans vos dotfiles. Et c’est du code.

~/.*Les dotfiles, intimement liés à votre workflow

Il peut être intéressant de modulariser certaines configurations. Par exemple, si vous avez des alias spécifiques à votre projet actuel, il peut être intéressant de les consigner dans un fichier à part plutôt que directement dans votre ~/.bashrc. Cela vous permettra de faire le tri de vos alias beaucoup plus facilement quand vous changerez de projet !

Beaucoup de gens partagent leurs dotfiles. Étant moi-même peu imaginatif, la lecture des dotfiles d’autres personnes me permet souvent de trouver des idées d’amélioration, des solutions à mes problèmes auxquelles je n’avais pas pensé, enfin bref de trouver de l’inspiration ! Beaucoup de bonnes idées sont aussi nées d’échanges avec des collègues !

On peut même aller encore plus loin que les dotfiles. Si vous savez que vous rejoignez un projet pour un certain temps, il peut être intéressant de regrouper certaines fonctionnalités avancées dans un outil CLI dédié. On peut par exemple imaginer un outil CLI développé dans votre langage favori (en Python par exemple) pour gérer votre environnement de dev si celui est complexe:

  • Démarrage / redémarrage du docker-compose qui porte la BDD et le serveur front
  • Remise à neuf des données dans la BDD suite à l'exécution de tests qui se sont mal passés et l’ont laissée dans un état non attendu
  • etc.

Cette dernière suggestion peut être redondante avec une pratique plus largement répandue d’utiliser un Makefile pour réaliser ce genre d’actions. L’avantage du Makefile, c’est qu’il est généralement inclus au code du projet, et donc accessible et commun à tous les membres du projet. Le débat “make ou outil CLI” dépasse le cadre de cet article, retenez simplement que plusieurs approches existent, et que l’objectif recherché est le même: simplifier et accélérer au maximum toute action que vous allez être amenés à répéter régulièrement !

Le temps passé sur ses outils n'est pas perdu !

Alors évidemment, aucune de ces suggestions prise indépendamment ne va changer votre vie, j’en suis bien conscient. Toutefois, leur impact est important pour plusieurs raisons:

  • Ces gains se cumulent. Lorsque vous avez pris le temps de vous créer un alias pour gagner quelques secondes sur une action “basique”, du temps est gagné à chaque fois que vous utilisez cet alias, et c’est toujours le cas des semaines plus tard, quand vous n’y pensez plus et que cela ne vous demande plus d’effort.
  • On a tendance à sous-estimer les gains liés à l’optimisation de tâches courtes parce que quelques secondes nous paraissent négligeables. Gagner 5s sur la rédaction d’un message de commit avec un “bête” hook, c’est potentiellement raccourcir cette action de 50% ! Et c’est évidemment d’autant plus important qu’on réalise ces petites actions souvent.
  • L’automatisation et l’utilisation d’outils adaptés permet aussi d’éviter des erreurs, souvent longues à corriger par rapport à la durée de l’action initiale. Pour rester sur l’exemple d’un hook de commit qui ajoute la référence du ticket JIRA dans le message de commit automatiquement, combien de temps est perdu dans le cas d’une faute de frappe ? `git commit --amend` n’est peut être pas très long, mais cela représente plusieurs fois la durée de simplement taper le message de commit. Et je ne parle même pas du cas où l'on ne se rend compte de la faute de frappe qu’après le merge sur master ! Qui n’a jamais dit/entendu “ah non, c’est vrai, je peux pas force push le commit que j’ai amendé, il faut que j’aille déprotéger master avant...” ?

Bref, les gains liés à des outils adaptés sont notables, mais combien de temps faut-il “investir” pour en arriver là ? En supposant qu’on investisse 1 heure/semaine à travailler sur ses outils et qu’à la fin de la semaine, cela nous permet de gagner ~5min/jour, soit 25min/semaine, en 3 semaines on aura suffisamment amélioré sa productivité pour rentabiliser cette heure allouée aux outils ! Après tout, on dédie du temps à l’amélioration continue dans tous nos projets, pourquoi en serait-il autrement pour nos outils ?

productivity_over_timeReculer pour mieux sauter: mon passage à Vim résumé en une image

Mais le temps gagné est loin d’être le seul intérêt d’investir dans ses outils !

  • Cela permet d’améliorer la qualité de son travail puisqu’une automatisation plus élevée permet en général moins d’erreurs. Si cette remarque vous semble familière, c’est normal !
  • Cela permet de monter en compétence sur les outils qu’on utilise : son IDE,  Git, Docker, Bash, les regex, la configuration d’applicatifs divers et variés. En prenant ainsi l’habitude d’aller lire la documentation, de fouiller dans la configuration, on s’approprie ses outils et on en tire le maximum.
  • On a également des gains de confort (et donc une plus grande satisfaction dans notre travail), puisque les outils sont plus adaptés à notre workflow personnel !

Et en bonus, comme tout est versioné, il est facile de porter sa configuration sur un autre poste (son poste personnel, le poste du client final quand on fait du conseil, sa nouvelle machine fraîchement déballée, etc) !

Conclusion

J’espère vous avoir fait comprendre l’intérêt d’investir du temps et de l'énergie dans vos outils ! Prenez le temps d'apprendre à vous servir efficacement de vos outils, privilégiez des outils que vous pouvez facilement modifier, étendre, interconnecter. Vous avez la chance de pouvoir façonner les outils que vous utilisez à votre guise, de les adapter à vos besoins et à vos envies. Profitez-en ! Vous en sortirez plus efficaces dans ce que vous faites tous les jours, et cela ouvrira vos horizons sur plein de nouveaux sujets.