Variant Is Out

Posted on Sep 27, 2024

La semaine dernière je parlais de la gestion des erreurs en PHP et comment mieux faire.

De plus en plus je suis lassé de créer mes ValueObjets ou d’utiliser les Results de GrahamCampbell. Non pas que ce derniers soient mauvais, loin de là, mais plutôt que je n’apprécie pas tellement la DX qu’il propose.

Et puis on a tous nos petites habitudes. Ca ne convient pas, tout simplement à mes goûts. Quand j’ai le choix d’utiliser autre chose, j’en profite.

Ces temps-ci sur mes projets perso je me retrouve à créer beaucoup de ces objets de transition, pour plus de type-safety dans mon code. Quitte à utiliser une langage objet, autant ne pas avoir que les inconvénients…

Pourtant créer ces objets de transition, c’est essentiel pour un code fiable. Sinon je me retrouve à tout passer dans des objets avec des clefs indicées. Et puis on s’y perd, on a pas de type-safety.

Alors qu’en Gleam je peux créer mes types très simplement, les utiliser, et être sûr de ce que je fais. Ca fonctionne, c’est rapide, je ne réflechis qu’à ma logique métier (même si je deteste ce terme).

C’est de ce constat qu’est né variant, un générateur de variants. Je veux mes types personnalisés, rapidement et sans trop de contrainte. Je veux mes result types.

Une génération statique

Le plus simple était de faire une génération statique. On déclare ce que l’on souhaite dans un fichier avec l’extension .variant et on lance le générateur. Il crée les fichiers, c’est fini.

Créer ce type de structures à la volée, dans le code, c’est à mon avis plus de problèmes que d’autre chose:

  1. Le LSP est dans les choux.
  2. Plus de travail pour PHP.
  3. Potentiellement des redéfitions qui cassent des parties sans qu’on ne le sache.

Un fichier déposé dans un dossier, et ça génère là où on l’a souhaité. Ce n’est pas parfait mais ça à le mérite de fonctionner et de ne pas interferer dans mon travail.

Trois instructions, et c’est tout

Pour le moment, variant est construit autour de mes besoins, et je n’ai besoin que de 3 instructions:

  1. type, pour un groupement de types autour d’une interface
  2. record, pour un type seul. Sous le capot, type construit des record qui implémentent son interface.
  3. results, pour avoir un type de résultat qui me retourne les types possibles, potentiellement d’un type, et une valeur de ok .

Peut-être qu’on peut faire plus, ou mieux, je ne sais pas. Pour l’instant cela me convient.

Immutable au maximum

Chaque code généré produit une classe avec des champs readonly. Impossible de modifier une valeur sans devoir la cloner. Cela permet d’avoir de véritable ValueObject qui passent les données.

Encore une fois, c’est un design que j’apprécie. On peut fortement remettre en question ce choix, mais il me convient pour l’instant.

C’est disponble maintenant sur Github/composer

Ici : https://github.com/AsymetricData/variant

Vous pouvez essayer en faisant un :

composer require cedriccourteau/variant --dev

Vous ajoutez un fichier mestypes.variant là où vous souhaitez gérérer ces types, avec par exemple

record MonRecordTest(string param, int val)

vous lancez :

php ./vendor/bin/variant

Et voilà, vous avez une classe MonRecordTest avec son constructeur de généré.

Par défaut, pour générer à nouveau vos variants, il faut relancer la commander avec le flag --force pour écrire sur les anciennes générations.