12 KiB
Title: Lettre n°12 — 23 février 2026
Date: 2026-02-23 09:00
Category: Newsletter
JsonLD:
Edito
La Craft Letter est récente, et je me pose encore des questions sur son format. Dois-je continuer à faire des résumés détaillés, comme ceux que contient ce numéro à propos de Zig vs C3, ou de la modernisation de code legacy ? Ou des textes d’introduction plus courts sont-ils préférables, comme celui sur AtomVM ? Je vous serais reconnaissant si vous preniez quelques secondes pour répondre à ce sondage minimaliste🇫🇷 (il n’y a qu’une question). Les réponses m’aideront à définir le format des prochaines Craft Letters.
Limiter les contributions open-source avec Vouch
Mitchell Hashimoto est un développeur prolifique et talentueux. Fondateur de HashiCorp (la société derrière Terraform, Vagrant, Vault...), il est aussi le créateur de Ghostty, un émulateur de terminal que je vous recommande. Son nouveau projet, Vouch🇬🇧, est un outil pour la CI qui limite les contributions aux projets open source (Pull Requests et Issues) à certains comptes de confiance. Les contributeurs ne peuvent pas en certifier d’autres : seuls les mainteneurs le peuvent, ce qui garantit qu’ils conservent la main sur leur projet. Par contre, ils peuvent échanger leurs listes de contributeurs de confiance. Sans surprise, le but est de limiter les contributions de basse qualité générées par IA, comme celles qui ont amené le projet Curl à fermer son programme de bug bounty🇫🇷.
Sérialisation rapide en Python
MsgSpec🇬🇧 est une librarie pour (dé)sérialisaliser et valider des données en Python, qu’elles soient au format JSON, YAML, TOML ou MessagePack. Elle utilise du C pour obtenir des performances élevées.
Qui, de Zig ou de C3, résout les problèmes du C ?
Dans mes newsletters précédentes, je vous ai parlé de Zig et de C3, deux langages qui se veulent des successeurs du C. Les deux cherchent à en corriger des défauts, chacun à leur manière.
Cette vidéo🇬🇧 de la chaîne Youtube The Techy Shop explique que ces langages présentent de nombreuses similarités, mais aussi certaines différences, que je peux résumer ainsi :
- C3 est présenté comme une évolution incrémentale de C. Il y introduit de la simplicité, notamment dans la syntaxe et l’outillage. Il élimine une partie des pièges de son prédécesseur grâce à des fonctionnalités comme la gestion des erreurs à l’aide d’un type Option.
- Zig se veut une révolution, et est plus ambitieux —au prix d’une complexité plus grande que que celle de C3. La preuve en est le système de build, qui nécessite l’écriture d’un script en Zig, là où C3 utilise un simple fichier JSON. Mais aussi le compilateur, qui, en plus de LLVM, utilise un backend spécifique à Zig, qui réduit significativement les temps de compilation pour le mode debug et les architectures x86_64.
Les deux sont compatibles avec C, mais C3 n’utilise pas les fichiers d’en-tête du C, ce qui implique de déclarer les fonctions C importées. Zig permet d’intégrer plus facilement du code C, tandis que C3 s’oriente plus vers la réécriture du C existant. Aucun des deux n’offre d’équivalent à l’instruction GOTO du C, ce qui implique un travail d’adaptation pour porter du code C, même s’il existe des moyens de simuler un GOTO.
C3 s’appuie sur l’écosystème C, là où Zig voudrait le remplacer entièrement.
Malgré leurs objectifs affichés, l’expérience de développement en Zig serait ironiquement plus proche de celle du C que celle de C3, car si elle offre plus de contrôle, elle requiert plus de rigueur en contrepartie. C3 minimise les surprises, au prix de fonctionnalités moins avancées.
Les deux langages évoluent rapidement, ont chacun une communauté passionnée. C3 est toutefois plus récent et moins visible. Zig est plus populaire, et a déjà de belle références, comme Bun ou Ghostty.
Au final Zig et C3 résolvent, de façon différente, les problèmes du C : la complexité de l’outillage, les multiples possibilités de se tirer une balle dans le pied. Les deux offrent des performances comparables à du C optimisé, et devraient jouer un rôle important dans la programmation système à l’avenir.
Pour en savoir plus sur C3, cette courte vidéo🇬🇧 explique les différences par rapport à C. Et pour essayer le langage simplement, il y a un tutoriel🇬🇧 en ligne.
Adopter Kotlin dans un environnement dominé par Java
Kotlin possède de nombreux avantages par rapport à Java🇬🇧. Pour n’en citer que quelques-un,
- le code est beaucoup plus concis tout en étant expressif,
- la sécurité est meilleure grâce au contrôle des valeurs nulles par le système de types,
- il n’y a pas de conversions implicites,
- les types primitifs de Java sont des objets en Kotlin,
- la gestion de la concurrence utilise des coroutines (plus légères que les threads),
Le tout avec des performances équivalentes.
Quand je parle de concision de Kotlin, je repense toujours à des collègues qui ont réécrit une application mobile Java de 33 000 lignes. La version Kotlin en faisait seulement 17 000. C’est possible notamment parce que le code boilerplate inhérent à Java n’existe pas en Kotlin.
La migration de Java vers Kotlin peut être tout à fait progressive, puisqu’une application Kotlin peut contenir du code Java, et que l’interopérabilité entre les deux langages est excellente. Cette démonstration🇫🇷 de migration reste intéressante même si elle date un peu, car elle est basée sur un retour d’expérience. Elle montre la simplicité relative d’une migration, grâce à l’outillage fourni par JetBrains.
Jetbrains propose un guide de migration🇬🇧, qui, outre des conseils techniques, fournit des recommandations sur la stratégie à adopter, notamment pour convaincre vos pairs et managers.
Java : le Valhalla est enfin là !
Près de douze ans après son lancement, le projet Valhalla est arrivé dans Java 23🇬🇧, en preview pour l’instant.
En Java, tous les objets sont représentés par des zones mémoires allouées sur le tas (heap), avec un en-tête, et nécessitent qu’on y accède via un pointeur —c’est masqué, mais ce n’est pas sans impact sur les performances. Et ce, même si ces objets ne servent qu’à encapsuler une ou plusieurs valeurs, comme les coordonnées x et y d’un point. Le projet Valhalla résout ce problème.
Il change aussi la façon dont ces données sont stockées dans les collections génériques : au lieu de contenir des pointeurs, elles contiennent directement les valeurs, contiguës en mémoire.
Ces changements améliorent drastiquement les performances, réduisent la fragmentation et la consommation mémoire, ainsi que la fréquence des déclenchements du ramasse-miette. Toutefois, ils ne sont pas applicables à toutes les structures de données.
Moderniser un legacy conséquent sans y perdre ses plumes - Partie II
Dans la première partie, que j’ai résumée dans la lettre précédente, Bruno Boucart expliquait la première phase pour réussir la modernisation d’une grosse application legacy. Elle consiste à en comprendre le métier, le cartographier, puis aligner l’organisation des équipes et l’architecture sur ce découpage. Dans cette seconde partie🇫🇷, il évoque la transformation du code qui doit suivre.
Après l’identification de contextes bornés (bounded contexts) au cours d’ateliers d’Event Storming, il explique comment remplir pour chacun un Bounded Context Canvas🇬🇧. Il s’agit d’un outil de modélisation qui va permettre d’affiner la définition du contexte, et de faire émerger le langage ubiquitaire —le vocabulaire partagé entre les équipes métier et techniques, qui est l’un des concepts les plus importants du Domain Driven Design (DDD).
Rappel : un contexte borné est une notion du DDD, qui désigne un sous-ensemble de la solution technique.
Bruno rappelle ensuite une série de design patterns que l’on peut utiliser pour casser les dépendances entre des parties du code. C’est en effet une étape préliminaire indispensable à l’écriture des tests qui vont permettre d’envisager sereinement des modifications plus importantes.
La réorganisation du code, selon les contextes bornés identifiés précédemment, n’est pas suffisante : elle doit s’accompagner d’une réorganisation de la base de données, de façon à casser là aussi les dépendances entre les parties du système.
Le code refactoré doit refléter fortement le métier : c’est ce qu’on appelle le deep modeling. Cela facilite la collaboration entre experts métiers et techniques, mais assure aussi la durabilité du nouveau code, qui tolérera mieux les évolutions futures du métier. L’une des clés pour cela est l’utilisation du langage ubiquitaire pour nommer les fonctions, les classes, les variables, etc. Le contour des classes doit correspondre à celui des concepts métier qu’elles représente.
L’activité qui mène à cette modélisation proche du métier porte le nom de Conception Souple (Supple Design) en DDD, et possède ses propres design patterns.
Pour améliorer la lisibilité, la testabilité et l’évolutivité, le code métier doit être isolé du code technique (accès à la base de données, appels à des APIs…) et de celui des interfaces utilisateurs. C’est le principe de l’architecture hexagonale (également appelée Ports et adaptateurs).
AtomVM : Erlang, Elixir ou Gleam sur un microcontrôleur
Davide Bettio présente AtomVM🇬🇧, une machine virtuelle capable d’exécuter des projets écrits en Erlang, Elixir ou Gleam sur un microcontrôleur comme un ESP32, un Raspberry PI Pico ou un ESP32. Il en explique aussi l’intérêt : tolérance aux erreurs, gestion de la mémoire, de l’asynchronisme, des valeurs binaires...
Principe de responsabilité unique en programmation fonctionnelle
Christian Ekrem montre comment le Principe de Responsabilité Unique (le S de SOLID, Single Responsibility Principle) s’applique de façon naturelle dans certains langages fonctionnels. En n’autorisant que l’écriture de fonctions pures, Elm interdit des antipatterns🇬🇧 que l’on peut implémenter en TypeScript.
Voilà, c’est tout pour cette semaine.
Avant de vaquer à d’autres activités, pensez à remplir le sondage🇫🇷 si ce n’est pas encore fait !