Cet article est publié sous licence CC BY-NC-SA
Ruby est typé dynamiquement, c’est ce qui fait son charme, mais dans certaines situations cela peut s’avérer être un frein au développement si on n’a pas les bons outils pour détecter les erreurs rapidement. Qui ne s’est jamais trompé sur le type d’un paramètre ou fait une faute de syntaxe lors d’un appel de méthode un peu obscure ?
Plus vite ce genre d’inattention est détecté, moins il est couteux de le corriger.
Je vous propose donc de vous parler d’un outil qui peut être salvateur dans ces cas de figure : Sorbet.
En quelques mots, Sorbet est un vérificateur de type progressif pour Ruby. Développé par Stripe et devenu open-source en 2019, le projet est toujours en développement actif.
Cette gem fait à la fois de la vérification statique et dynamique. Elle est composée d’une interface de ligne de commande qui peut analyser un projet très rapidement, ce qui peut, par exemple, réduire le temps d’exécution des tests ou d’un système qui tourne lors de l’exécution du code.
L’aspect progressif de cette gem vient du fait qu’elle puisse être adoptée au fil du temps : par défaut rien n’est analysé. On peut donc, par exemple, développer une fonctionnalité puis ajouter le typage une fois le code solidifié. Il existe aussi plusieurs niveaux de rigueur allant du plus permissif jusqu’à interdire totalement l’usage du type undefined
.
Pour que Sorbet soit en mesure de vérifier le typage, il faut qu’il ait connaissance des types d’objets en entrée et sortie de chaque méthode, des types des constantes et variables, et ce, pour toute la base de code de la bibliothèque standard de Ruby jusqu’aux différents modules du framework sans oublier les gems.
Pour cela il existe 2 systèmes d’annotations :
# typed: true
class Welcome
extend T::Sig
sig {params(name: String).returns(String)}
def hello(name)
"Hello #{name} !"
end
end
Welcome.hello('World') # => "Hello World"
Welcome.hello(42) # => Parameter 'name': Expected type String, got type Integer with value 42 (TypeError)
Cette déclaration est vérifiée aussi bien à l’exécution qu’en passant par la ligne de commande. L’accès au code source de la méthode étant obligatoire pour ce format, il est donc à privilégier pour tout le code qu’on écrit.
T::Sig
, ni de l’implémentation finale de la méthode.# welcome.rb
class Welcome
def hello(name)
"Hello #{name} !"
end
end
# welcome.rbi
class Welcome
sig {params(name: String).returns(String)}
def self.hello(name); end
end
Cette méthode exige de synchroniser 2 fichiers, elle est donc à privilégier pour toutes les dépendances du projet qui n’ont pas vocation à être modifiées régulièrement : gems, bibliothèques, etc.
On vient de mettre le doigt sur un inconvénient majeur : comment récupérer les signatures de toutes ces dépendances ? Lorsqu’on travaille avec un framework (Rails ou autre) et plusieurs gems, devoir chercher les signatures de chaque méthode peut vite donner le tournis. Heureusement pour nous, Sorbet propose de générer les fichiers RBI à notre place, malheureusement pour nous il le fait assez mal. C’est ce qui m’a fait abandonner l’idée d’utiliser cette gem dans une application Rails lorsque j’avais voulu la tester. Mais depuis peu (juillet 2022), Sorbet recommande officiellement d’utiliser Tapioca pour toute la génération des RBI et a mis à jour sa documentation en conséquence. On a maintenant à portée de main des commandes fonctionnelles pour récupérer les RBI communautaires ou officiels et générer les autres fichiers manquants.
Après quelques jours d’utilisation, voici ce que j’ai noté :
Ses avantages :
Ses inconvénients :
La V3 de Ruby a vu naître un tout nouveau système de typage nommé RBS, bien que celui-ci soit natif il n’est encore qu’à ses débuts et est assez limité : il ne propose pas de solution pour vérifier les annotations RBS, ni d’annotations de type au même endroit que la définition de méthode. L’équipe de Sorbet est néanmoins impliquée dans le groupe de travail Ruby 3 pour le typage statique, on peut donc espérer une compatibilité entre les deux systèmes à l’avenir.
L’équipe Synbioz.
Libres d’être ensemble.
Nos conseils et ressources pour vos développements produit.