deep-dives

19 posts

Votre diagramme d'architecture est déjà un mensonge

La documentation d'architecture pourrit dès que vous la sauvegardez. Voici comment garder une documentation honnête en utilisant des diagrammes générés depuis le code, des ADR et des tests d'architecture automatisés.

Chaque diagramme d'architecture que j'ai vu dans un wiki était faux. Pas dramatiquement faux. Juste calmement, progressivement faux. Le service nommé « Auth »…

Votre boucle de retry part du principe que la première requête a échoué. Ce n'est probablement pas le cas.

Un timeout ou un crash ne signifie pas que votre requête API a été perdue. Voici comment les clés d'idempotence rendent les retries sûrs, et le pattern de stockage qui empêche réellement les doublons.

Votre service plante au milieu d'une requête . Le client voit un timeout et retry. Vous avez maintenant deux charges. Le client est en colère. La base de…

Un verrou qui survit à votre processus : comment fonctionnent réellement les leases distribués

Les mutex en mémoire disparaissent lors du redémarrage de votre serveur. Voici comment les leases distribués avec des jetons de clôture (fencing tokens) et des TTLs empêchent le travail en double lors des crashs, et où ils échouent encore.

Votre ne survit pas à un . Il ne survit pas à un OOM, à un déploiement progressif, ni à un redémarrage de nœud. À l'instant où le processus se termine, le…

Un circuit breaker sans goroutines, sans timers et sans overhead d'arrière-plan

La plupart des bibliothèques de circuit breaker lancent des threads d'arrière-plan pour tester la récupération. Vous n'en avez pas besoin. Voici une conception pilotée par les requêtes qui élimine tout l'overhead d'arrière-plan sans sacrifier la correction.

Chaque circuit breaker en production que j'ai examiné finit par lancer un thread d'arrière-plan. Il peut s'agir d'une goroutine Go, d'un Java, ou d'une tâche…

Votre service web a un chemin d'arrêt gracieux. C'est le bug.

Les logiciels crash-only traitent chaque échec comme un crash et chaque démarrage comme une récupération. Pour les services web, cela signifie supprimer votre logique d'arrêt et concevoir un état qui survit à un kill -9.

Votre service web a un shutdown handler. Il vide les buffers, ferme les connexions, écrit des checkpoints. Vous l'avez testé une fois, peut-être. En…

Comment tuer un mutant survivant quand vous ne comprenez pas ce qu'il a changé

Le mutation testing a trouvé un survivant et vous n'avez aucune idée de ce que fait la mutation. Voici une méthode pas à pas pour écrire le bon test sans comprendre le mutant au préalable.

Votre rapport de mutation testing est plein de survivants, et au moins l'un d'eux n'a aucun sens pour vous. L'outil dit qu'il a inversé un en à la ligne 47, ou…

Le code d'authentification a besoin de 90% de couverture de mutation. Vos utilitaires de chaînes de caractères, non.

Pourquoi imposer un seul score de mutation à l'ensemble de votre codebase est une erreur, et comment définir des seuils par module qui correspondent au risque réel.

Imposer un seul score de mutation à l'ensemble de votre codebase est un excellent moyen de faire détester les tests à votre équipe. Lancez PIT ou Stryker sur…

Vos tests passent. Votre mutation score est de 40 %. Voici ce que les mutants survivants vous disent vraiment.

La couverture de code dit que vous êtes en sécurité. Le mutation testing dit que vos tests sont surtout de la décoration. Voici comment les mutants survivants exposent le fossé, et comment le combler.

Vos tests passent. Votre rapport de couverture indique 87 %. Mais votre mutation score est de 40 %, et la moitié de vos mutants sont encore vivants. Ce 40 % ne…

Le mutation testing en Rust fonctionne, mais vos temps de compilation vont le détester

cargo-mutants trouve les tests qui font semblant de vérifier votre code. Voici comment fonctionne le mutation testing pour Rust, ce qu'il détecte, et si le coût en temps de compilation en vaut la peine.

Vous avez 100 % de couverture de lignes. Chaque branche est exécutée. Chaque fonction est appelée. Puis quelqu'un change un en dans votre logique de…

Le mutation testing prend 4 heures. Comment les équipes l'utilisent-elles vraiment en CI ?

La plupart des équipes n'exécutent pas de suites complètes de mutation testing à chaque commit. Voici comment les équipes d'ingénierie intègrent réellement le mutation testing en CI sans faire échouer le pipeline de build.

Si votre suite de mutation testing met quatre heures à s'exécuter, félicitations. Vous avez prouvé ce que tout le monde soupçonnait déjà : votre suite de tests…

Vos tests unitaires passent, mais vos données disparaissent quand même

Les tests de base de données simulés vérifient votre syntaxe SQL, pas si les lignes survivent aux crashes, aux écritures concurrentes ou aux incompatibilités de schéma. Voici comment tester la persistance pour de vrai.

Si vous mock votre base de données dans les tests, vous testez que votre couche repository appelle les bonnes méthodes. Vous ne testez pas que les données…

100 exécutions de tests, c'est un mensonge : comment dimensionner vos tests par propriétés

Les 100 exemples par défaut dans les tests par propriétés sont un compromis social, pas une stratégie statistique. Voici comment choisir un nombre d'exécutions qui correspond à vos besoins de confiance et à votre budget CI.

Si vous exécutez des tests par propriétés avec les 100 exemples par défaut, vous avez le pire des deux mondes. Votre CI est plus lente que nécessaire, et vous…

Les tests basés sur les propriétés en Rust trouvent les bugs que vos tests unitaires ne détectent pas

Le test par exemple ne couvre que les entrées auxquelles vous avez pensé. Le test basé sur les propriétés génère des données aléatoires, vérifie les invariants et réduit les échecs à des contre-exemples minimaux.

Vous avez écrit une fonction . Vous l'avez testée avec et . Elle passe. Vous livrez. Un utilisateur passe un slice à un seul élément. Votre fonction l'ignore.…

Les Runtime Contracts en Rust peuvent être sans coût en release, mais le compilateur ne le fera pas à votre place

Rust élimine automatiquement les debug assertions, mais un vrai design-by-contract nécessite plus que debug_assert!. Voici comment construire des runtime contracts sans coût qui disparaissent de votre binaire release.

Rust peut appliquer des runtime contracts en développement et les effacer complètement des builds release. La mise en garde est que le langage ne traite pas…

Zéro, une ou douze : combien d'assertions une fonction de production réclame-t-elle vraiment

Les développeurs dispersent les assertions comme des confettis ou les évitent totalement. Voici le cadre de décision qui distingue les invariants utiles des déclencheurs de crash en production.

La plupart des codebases de production se divisent en deux camps. Le camp A traite comme un assaisonnement décoratif, en saupoudrant une ligne sur deux jusqu'à…

strictNullChecks dans TypeScript est un garde-fou à la compilation, pas un bouclier à l'exécution

Le mode strict attrape les null que vous écrivez, pas les null qui arrivent à l'exécution depuis les API, les requêtes DOM et JSON.parse. Voici où le système de types s'arrête et où vos défenses commencent.

Vous avez activé dans . Vous avez corrigé chaque soulignement rouge. Vous avez mis en production en étant convaincu que et étaient des problèmes résolus. Puis…