/img/ruby2crystal.png

Cela fait quelques mois que je suis de près le développement d’un langage informatique qui a fait son apparition il y a quelques années déjà : Crystal.

Je suis vraiment un grand fan de code. Au point parfois de regarder mon IDE en me disant : “c’est beauuuuu…” Mais du coup, mon côté esthète me pousse vers des langages dont la syntaxe est fluide, concise et intuitive. C’est cette envie de joli code qui m’a poussé à abandonner PHP, ses $variables, ses -> et ses ; en fin de ligne. Beuark. J’ai aussi longtemps snobé le Javascript, pour à peu près les mêmes raisons, même s’il est difficile de s’en passer ! Il a été sauvé quand j’ai découvert SandardJS et appris que les points-virgules du Javascript étaient optionnels, car oui, je suis point-virgule-phobe et je l’assume. Je peux désormais lire mon code Javascript sans être pris de spasmes.

Je suis tombé dans le Ruby il y a une grosse dizaine d’années, en pleine hype Ruby on Rails, attiré par ces tutos qui montraient comment monter un blog en 3 minutes 27 chrono. J’ai appris à dompter la bête au fil des ans, et j’ai appris à apprécier l’expressivité de ce langage. Cette flexibilité, elle vient du fait que Ruby propose plusieurs manières de faire la même chose. Ce langage ne contraint pas le développeur dans un mode de pensée unique, il le laisse libre de s’attaquer à un problème de la manière qui lui semble la plus adaptée. C’est ce qui donne Ruby cette impression d’être un langage informatique lisible par les humains.

Mais Ruby a ses limites.

D’abord, Ruby est relativement lent. C’est un langage interprété, et non pas compilé. Mais dans un projet web Rails, on parvient à contourner ce handicap avec du cache, des optimisations et de la sueur. Et puis on nous a promis que Ruby 3x3 serait 3 fois plus rapide que Ruby 2, chaque nouvelle version va dans cette direction, donc on peut s’en accommoder. Ensuite, un framework tel que Rails a tendance à être gourmand en ressources serveur. Rien de catastrophique non plus, on s’y adapte, et de la même manière, ça s’optimise. Ces deux défauts sont souvent les plus cités par les détracteurs du langage, mais ils ne sont pas - à mon humble avis - le véritable défaut de Ruby.

Ruby est un langage typé dynamiquement. C’est très flexible. C’est très facile à rendre en main et cela donne une fausse impression de liberté. Par exemple, en Ruby, il est tout à fait possible d’écrire :

a = 12
b = 'douze'
a = b

#=> 'douze'

On se dit “génial, pas de contraintes, pas de déclarations lourdes et figées, vive le code magique !”, jusqu’au jour où on se retrouve confronté à des bugs qui se cachent dans une mauvaise affectation de variable cachée dans une vieille méthode enfouie dans une classe pourrie codée il y a 4 ans à l’arrache pour cacher la misère. Et ne me dites pas que vous écrivez toujours du super code, bien propre et testé, je ne vous croirai pas.

On se retrouve aussi régulièrement confronté au problème des variables nulles qui font planter toute l’appli.

Sur un petit projet, ce genre de problème est facile à résoudre. Mais sur un projet complexe qui est développé sur plusieurs années, cet avantage devient vite un handicap.

Fort de ce constat, je me suis mis en quête du Graal : un langage de développement aussi propre que le Ruby, mais plus rapide, plus léger, et plus facile à débugger.

De nombreux rubyistes se tournent actuellement vers Elixir (et son framework web Phoenix), un langage fonctionnel (et non pas orienté-objet, à la fois interprété et compilable, qui ressemble énormément à Ruby et qui coche les deux premières cases allègrement, avec des benchmarks de folie. Je suis activement le développement d’Elixir et j’ai même fait un petit projet avec Phoenix, mais quitte à chercher le Graal, autant aller jusqu’au bout et cocher cette dernière case…

C’est là que j’ai découvert Crystal.

Crystal, c’est - pour simplifier - du Ruby compilé. Je simplifie, parce que de fait, au fil des versions, Crystal s’éloigne de sa source première d’inspiration pour développer des fonctionnalités propres à un langage compilé. Mais il est tout à fait possible de prendre du code Ruby, de le coller dans une classe Crystal et de le voir se compiler avec le sourire. Un exemple (simpliste, mais bon, vous saisissez l’idée) :

def myClass
  10.times do
    puts "Crystal et Ruby sont vraiment proches"
  end
end

Crystal propose un écosystème de plugins, équivalent des gems de ruby, appelés “shards”. Il doit encore être étoffé, mais cette liste régulièrement mise à jour les classe par catégories.

Plusieurs frameworks web existent. J’ai d’abord testé Amber. Très bon, très complet et flexible, proposant plusieurs ORMs afin de satisfaire les besoins de chacun, il est activement développé et cherche à accueillir les développeurs Rails en proposant un écosystème très proche du bébé de DHH. Il existe également un framework plus minimaliste, inspiré de Sinatra et appelé Kemal. Athena est un framework orienté API. Mais celui qui m’a convaincu s’appelle Lucky.

Développé par des gens de Thoughtbot, il tire profit du typage statique de Crystal pour soulever les bugs dès la compilation. À cette fin, il n’utilise pas un mélange Crystal-HTML à l’image d’ERB pour son moteur de template, mais du Crystal pur.

Je ne fais que découvrir ce langage et ce framework, mais ils semblent prendre une direction qui correspond en tout point à mes attentes. J’ai l’intention de faire basculer la partie API de ma plus grosse appli web sur Lucky dès que j’en aurai le temps, et dès qu’Avram (l’ORM utilisé par Lucky) permettra de gérer les champs jsonb de Postgresql, ce qui est imminent.

Je ne peux donc que vous conseiller de jeter un oeil à cet écosystème prometteur, réservé à ceux qui aiment le beau code et n’ont pas peur de sortir des sentiers battus.