What I think about...
I enjoyed blogging until around 2020, but these days I no longer have the time for it. Since I use AI to learn about new technologies, algorithms and other dev topics, I pipe the interesting results into this blog. AI-generated posts are marked. I use Claude and Gemma. Translations are AI-generated as well.
L'algorithme des trigrammes : la recherche floue sans magie
Un trigramme n'est que trois caractères consécutifs, et comparer les ensembles de trigrammes de deux chaînes donne un score de similarité rapide et tolérant aux fautes de frappe…
Créer un hook personnalisé de récupération de données en React
Toute base de code React finit par accumuler une douzaine de blocs quasi identiques qui récupèrent des données, suivent l'état de chargement et gèrent les erreurs. Extraire ce s…
CSS Container Queries : un guide pratique
Les media queries répondent à une seule question : quelle est la taille du viewport ? C'est la mauvaise question pour la plupart des composants, car une carte, un widget de barr…
Comment fonctionne réellement le DOM virtuel
« Le DOM virtuel rend React rapide » est une de ces phrases que tout le monde répète sans vraiment pouvoir l'expliquer. Ce n'est pas magique, et ce n'est même pas toujours plus…
Comprendre les Web Workers pour les calculs lourds
JavaScript s'exécute sur un seul thread : une tâche gourmande en calcul (analyser un énorme blob JSON, redimensionner une image, lancer un algorithme de recherche de chemin) blo…
Debouncing et throttling : dompter les événements à haute fréquence en JavaScript
Tout développeur frontend finit par se heurter au même mur : un gestionnaire de scroll qui se déclenche des centaines de fois par seconde, un champ de recherche qui lance une re…
Écrire un outil en ligne de commande simple avec Node.js
La plupart des outils CLI internes n'ont pas besoin d'un framework. Un script qui renomme un lot de fichiers, appelle une API interne ou enveloppe une séquence répétitive peut t…
Les bases de l'accessibilité web : ARIA sans deviner
L'erreur ARIA la plus courante n'est pas d'utiliser le mauvais attribut : c'est de recourir à ARIA tout court alors qu'un élément HTML natif aurait résolu le problème gratuiteme…
Guide pratique des stratégies de branches Git
La plupart des équipes ne choisissent pas une stratégie de branches : elles héritent de ce que les ingénieurs fondateurs ont fait, et cela se fige avant que quiconque se demande…
Construire une machine à états simple en TypeScript
Si vous avez déjà écrit un composant avec , , et comme booléens séparés, vous avez probablement aussi livré un bug où deux d'entre eux étaient vrais en même temps et où l'interf…
Reflows et repaints : pourquoi votre page semble saccadée
Vous mesurez la hauteur d'un élément avec , vous l'utilisez pour fixer la largeur d'un autre, vous relisez cette largeur et vous fixez la hauteur d'un troisième, et voilà que ce…
Comprendre les en-têtes de cache HTTP
La plupart des problèmes de performance que l'on tente de résoudre avec un CDN ou une couche de cache se règlent en réalité gratuitement avec trois en-têtes HTTP correctement dé…
Guide pratique de la pagination d'API
Renvoyez toutes les lignes d'une table qui grossit dans une seule réponse et vous avez construit une fonctionnalité qui marche en développement et s'effondre en production le jo…
Comprendre le pool de connexions de base de données
Ouvrir une connexion à une base de données coûte cher : une poignée de main TCP, l'authentification, parfois une négociation TLS, généralement des dizaines de millisecondes avan…
Écrire votre première GitHub Action
La plupart des équipes débutent avec GitHub Actions en copiant-collant un workflow d'un autre dépôt en espérant qu'il s'applique encore. Ça marche jusqu'au jour où ça ne marche…
Comprendre la boucle d'événements JavaScript
JavaScript s'exécute sur un seul thread, et pourtant il gère des milliers de requêtes réseau, de timers et d'événements d'interface simultanés sans bloquer. La boucle d'événemen…
Déboguer les fuites mémoire dans Node.js
Un processus Node dont l'utilisation mémoire grimpe lentement pendant des heures ou des jours, puis finit tué par manque de mémoire (OOM) par l'orchestrateur de conteneurs, est…
Un guide pratique du versionnage sémantique
dans un a l'air précis, mais ce circonflexe change de sens selon que le mainteneur en face a réellement suivi les règles sur lesquelles il repose. Le versionnage sémantique (sem…
La notation Big O expliquée avec du vrai code
La notation Big O est enseignée avec des exemples abstraits (trier des tableaux d'entiers, chercher dans des arbres équilibrés) puis discrètement abandonnée dès que l'on commenc…
Feature toggles avec une configuration par environnement
La façon la plus simple de livrer une fonctionnalité inachevée en production sans l'exposer est aussi celle qui est le plus souvent réinventée de travers : un booléen lu depuis…
Construire un middleware de limitation de débit dans Express
Un endpoint d'API non protégé est une invitation : un script client qui se comporte mal, une boucle de nouvelles tentatives sans backoff, un scraper, et votre serveur passe tout…
Comprendre la Content Security Policy (CSP)
La Content Security Policy est une fonctionnalité du navigateur qui limite les sources d'où une page peut charger des scripts, des styles, des images et d'autres ressources. C'e…
Construire une file de tâches simple avec Redis
Envoyer un e-mail de bienvenue, redimensionner une image téléversée, générer un rapport PDF : rien de tout cela ne devrait se faire dans la requête HTTP qui l'a déclenché. Une f…
Le patron Repository : avantages, inconvénients et quand s'en passer
Le patron repository est recommandé par défaut dans beaucoup de tutoriels de backend, juste à côté de l'injection de dépendances, comme si s'en passer était manifestement une er…
Transactions de base de données et niveaux d'isolation expliqués
« Enveloppez simplement ça dans une transaction » est un conseil courant, mais une transaction seule ne garantit pas que deux opérations concurrentes ne se marcheront pas dessus…
Stratégies de nouvelle tentative : backoff exponentiel et gigue
Un appel réseau échoue. La solution évidente est « il suffit de réessayer », mais réessayer naïvement transforme un bref accroc en panne complète, car chaque client martèle le s…
Une introduction en douceur aux WebSockets
HTTP fonctionne en requête-réponse : le client demande, le serveur répond, et la connexion a fini son travail. Ce modèle s'effondre dès que le serveur doit dire quelque chose au…
Itérateurs asynchrones et générateurs en JavaScript
Les boucles parcourent les tableaux et autres itérables une valeur à la fois. fait de même quand chaque valeur met du temps à être produite (lecture de résultats d'API paginés,…
La mémoïsation en JavaScript, au-delà de useMemo
La mémoïsation met en cache le résultat d'un appel de fonction en fonction de ses arguments : un nouvel appel avec les mêmes arguments renvoie la valeur en cache au lieu de refa…
Construire un système pub/sub simple avec Node.js
Le publish/subscribe découple le code qui produit un événement de celui qui y réagit : l'éditeur ne sait pas et ne se soucie pas de qui écoute, et les abonnés ne savent pas et n…
Le théorème CAP expliqué par des exemples concrets
Chaque éditeur de base de données distribuée affirme être rapide, cohérent et toujours disponible. Le théorème CAP est la raison pour laquelle vous devriez vous méfier de ce dis…
Guide pratique de l'authentification par JWT
Les JSON Web Tokens sont adoptés par défaut dans beaucoup de nouveaux backends, souvent sans que personne ne vérifie qu'un jeton est réellement le bon choix, ni ce qui se passe…
Event sourcing contre CRUD traditionnel
Une table CRUD traditionnelle vous donne l'état courant d'une ligne et rien sur la façon dont elle y est arrivée. L'event sourcing inverse cela : il stocke chaque changement qui…
Logs structurés : pourquoi le débogage par printf ne passe pas à l'échelle
marche très bien jusqu'au jour où vous avez dix serveurs, mille lignes de log par seconde et un incident pour lequel vous devez retrouver toutes les requêtes d'un client à trave…
Comprendre CORS une bonne fois pour toutes
Les erreurs CORS apparaissent dans la console au pire moment, n'indiquent presque rien d'utile sur la façon de les corriger, et sont « résolues » en copiant-collant depuis Stack…
Algorithmes de limitation de débit : token bucket contre fenêtre glissante
Toute API publique finit par avoir besoin d'une limitation de débit, et l'algorithme que vous choisissez détermine si « 100 requêtes par minute » signifie réellement ce que cela…
Le problème des requêtes N+1 et comment l'éviter
Une page qui liste 50 articles de blog avec le nom de chaque auteur paraît instantanée en développement, avec une poignée de lignes de test, puis s'effondre en production dès qu…
Git Rebase ou Merge : quand utiliser lequel
et amènent tous deux les changements de votre branche de fonctionnalité sur , et cette ressemblance superficielle est précisément la raison pour laquelle on les confond et on fi…
Écrire des migrations de base de données sûres et idempotentes
Une migration qui s'est bien passée en préproduction puis échoue à mi-chemin en production vous place dans la pire situation possible : un schéma qui n'est ni l'ancienne version…
Comment fonctionnent réellement les index de base de données
« Ajoutez simplement un index » est le conseil de base de données le plus courant, et aussi le plus souvent mal appliqué : lancé sur des requêtes lentes sans comprendre ce que f…
Verrouillage optimiste et pessimiste dans les bases de données
Deux requêtes lisent la même ligne, calculent toutes deux une nouvelle valeur à partir de ce qu'elles ont lu, et la réécrivent : la seconde écriture écrase silencieusement la pr…
Le patron Circuit Breaker pour des services résilients
Quand un service en aval commence à échouer, la réponse naïve (réessayer chaque requête à mesure qu'elle arrive) est exactement le mauvais réflexe. Chaque nouvelle tentative est…
Feature flags : un guide pratique
Un feature flag est une condition placée autour d'un morceau de code qui permet d'activer ou de désactiver ce code (pour tout le monde, pour un sous-ensemble d'utilisateurs, ou…
Comprendre les génériques TypeScript
Les génériques sont la fonctionnalité qui fait trébucher juste après qu'on s'est senti à l'aise avec les types TypeScript de base, puis qui, une fois le déclic venu, devient l'u…
Construire un cache LRU à partir de zéro
Un cache LRU (least-recently-used, « le moins récemment utilisé ») conserve un nombre fixe d'éléments et, lorsqu'il est plein et qu'un nouvel élément doit être ajouté, évince ce…
Les clés d'idempotence dans les API REST
Un client envoie une demande de paiement, le réseau expire avant le retour de la réponse, et le client, c'est raisonnable, réessaie. Si votre endpoint se contente de relancer le…
Python 3 : renommer les fichiers aux noms identiques
Si vous voulez déplacer ou copier rapidement et confortablement des fichiers d'un système de fichiers sensible à la casse vers un système qui ne l'est pas, ce script renomme vit…
Gestion des e-mails / protection contre le spam
Je déteste le SPAM. On le voit probablement au nombre d'articles de blog (on pourrait presque croire que tout le blog ne parle que de spam). J'ai toutefois trouvé entre-temps un…
L'importance du web design accessible : une porte vers l'inclusivité et la convivialité
Dans un monde de plus en plus marqué par les technologies numériques, l'accessibilité des sites web et des applications pour tous les utilisateurs est d'une importance décisive.…
La menace invisible : XSRF, quand le web travaille contre vous
Dans un monde où nos informations personnelles et nos activités en ligne gagnent sans cesse en importance, la sécurité dans le cyberespace est d'une importance décisive. Une men…
Détecter les attaques par force brute
Un samedi, dans un café, après que mon hébergeur OVH m'a informé qu'une attaque DDoS visait mon serveur virtuel, j'ai réfléchi à la façon dont on pourrait détecter une attaque p…
React Native : de quoi s'agit-il ?
Avant de vraiment commencer, laissez-moi vous raconter une blague : savez-vous pourquoi les développeurs aiment tant travailler avec React Native ? Parce qu'ils font d'une pierr…
Le mot-clé this en JavaScript
Dans le monde du développement web, JavaScript est l'un des langages de programmation les plus utilisés. Malgré sa popularité, certains concepts délicats donnent du fil à retord…
Injection de dépendances
Dans le monde du développement logiciel, de nombreux concepts sont essentiels pour créer des applications robustes, évolutives et faciles à maintenir. L'un de ces concepts, qui…
La puissance du method chaining en C# : un guide pour un code efficace
Dans le monde du développement logiciel, l'efficacité est un concept clé. Un code efficace est non seulement plus facile à lire et à maintenir, mais il contribue aussi à augment…
Scriptable : vérifier l'état de ses lentilles de contact
Un petit widget Scriptable pour suivre l'état actuel de ses lentilles de contact et de leur boîtier. Comme j'oublie sans cesse de changer mes lentilles après 30 à 40 jours (ou,…
Firmware Marlin pour SKR Mini E3 V3
Certains d'entre vous voudront peut-être s'éviter la peine de compiler et de configurer eux-mêmes la version corrective Marlin 2.1.X pour la Creality Ender 5. Configurer le CR T…
Autosort : trier simplement et rapidement images et vidéos
Ceci est le successeur du script présenté ici : GoPro & Photos : renommer et copier automatiquement
Promises
Un concept difficile à comprendre au début pour beaucoup de développeurs : les Promises.
JavaScript - Les générateurs
Les générateurs JavaScript sont une technique de fonction puissante à la disposition des développeurs JavaScript. Ils permettent d'écrire des fonctions asynchrones de façon plus…
Closures JavaScript
Une closure apparaît lorsqu'une fonction accède à une variable ou à une fonction en dehors de son propre scope. En gros, une closure est une fonction qui se souvient des valeurs…
Renommer et copier automatiquement les photos GoPro
Il existe une version plus récente et meilleure ici : Autosort - Trier simplement et rapidement images et vidéos
Delegates C#
Un delegate est une sorte de pointeur vers une méthode ou un groupe de méthodes qui peuvent être appelées sans que vous ayez besoin de connaître les détails des implémentations…
Sauvegarde automatique vers Amazon S3
Je suis devenu très critique ces derniers temps quant à la sécurité de mes sauvegardes. D'autant que j'expérimente beaucoup avec mon serveur virtuel (sur lequel ce site est nota…
Script d'inscription automatique Udemy pour Tampermonkey
Sur myDealz, on trouve régulièrement des fils de discussion qui listent des cours Udemy gratuits. Une fois inscrit à un cours, on peut le regarder à tout moment, tant qu'il rest…
JavaScript Object Notation avec SQL
Les bases de données conviennent parfaitement au stockage structuré de données. Il arrive toutefois que, pour diverses raisons, cela ne suffise pas et que l'on veuille plutôt st…
L'opérateur null-conditionnel
L'« opérateur null-conditionnel » est une fonctionnalité introduite avec C 6.0 qui permet aux développeurs de manipuler les valeurs null de façon plus sûre. C'est un opérateur s…
Valider des adresses e-mail
Une méthode souvent utilisée (je l'avoue, par moi aussi) pour se protéger du spam par e-mail consiste à ne simplement pas indiquer d'adresse e-mail valide lors d'une inscription…
MySQL : afficher NULL comme 0
Pour un petit projet, je devais additionner les valeurs d'une colonne dans MySQL et trier selon ces sommes. Quelque chose comme
Alpha-Go
Si vous vous intéressez à l'IA et cherchez un « film » facile à digérer sur le sujet, regardez absolument le documentaire sur le match d'AlphaGo. À voir sans hésiter ! Voir la v…
Échecs simultanés
En grand fan d'échecs, je suis bien sûr abonné au GM Huschenbeth. Son spécial 40k, dans lequel il joue simultanément contre plusieurs abonnés, m'a particulièrement plu. Au début…
Visualiser les données d'altitude de la NASA
Un petit snippet pour visualiser les données d'altitude de la NASA. Vous les trouverez ici : https://lpdaac.usgs.gov/products/srtmgl3v003/
youtube-dl : télécharger du MP3 rapidement
J'utilise depuis un moment le merveilleux outil youtube-dl. Pour ceux qui ne le connaissent pas : il permet de télécharger des vidéos, de la musique, etc. depuis de nombreux sit…
Protection contre la force brute
Les attaques par force brute contre les applications web constituent un problème sérieux, en particulier pour les grands sites comptant beaucoup d'utilisateurs. Un attaquant ten…
Un MacBook flambant neuf qui s'éteint tout seul
Une petite histoire sur Apple, ou la pire et la plus frustrante expérience d'achat que j'aie jamais vécue. Peut-être aidera-t-elle l'un ou l'autre utilisateur. Je divise l'incid…
Autopush - Téléverser simplement les fichiers modifiés
Pour simplifier mon flux de travail de web design et de développement web, je me suis écrit un petit script Autopush. Le script surveille un dossier précis et tous ses sous-doss…
CentOS - L'essentiel du serveur
De temps en temps, je dois réinstaller mon serveur CentOS (soit parce que quelque chose a de nouveau mal tourné, soit parce que le sentiment satisfaisant d'un système neuf et pr…
Fire on enter
Un petit snippet JavaScript/jQuery qui déclenche une action dès que la touche Entrée est pressée dans un champ.
« Cette version de l'app “Installer OS X Sierra” ne peut pas être vérifiée »
Aujourd'hui, je voulais donner mon vieux Mac à un ami, et en utilisateur consciencieux, je commence évidemment par tout remettre à zéro. J'ai donc rapidement créé une clé USB am…
Redimensionnement d'images simple + mise en cache
De temps en temps, il arrive qu'une image existante soit nécessaire dans une autre taille. On peut alors soit créer avec Photoshop une version découpée sur mesure pour chaque va…
Simple Template Engine
Pour un projet un peu plus gros, je cherchais un moteur de templates simple. Je ne voulais pas écrire sans cesse le même code à la fois pour mes scripts côté serveur et côté cli…
Convertir des secondes en jours, heures, minutes et secondes
Sur un projet en cours, sur lequel j'étais assis ce matin, j'ai eu un peu mal à la tête pour convertir une valeur en secondes en jours, heures, minutes et secondes. C'est en fai…
Timemachine -5058
Pire scénario : la sauvegarde déraille. Normalement, je sauvegarde mes projets informatiques en double. Mon cron s'exécute automatiquement chaque jour à 24 h 00 et crée une sauv…
Scrollblur
En tant que « fou de design », je cherche bien sûr toujours de l'inspiration, et quoi de mieux que de passer de temps en temps sur les sites des grandes agences ; c'est ainsi qu…
Snippets JavaScript
Je rassemble ici quelques snippets JavaScript. Une liste qui sera certainement complétée avec le temps :)
Snippets Bash
Quelques snippets Bash utiles ou absurdes qui peuvent servir de temps en temps. Amusez-vous bien.
Ne faites confiance à aucun scan que vous n'avez pas falsifié vous-même
Une conférence très intéressante qui met en lumière un bug (assez amusant et dramatique) des photocopieurs Xerox. En bref : les photocopieurs Xerox mettent en cache des zones d'…
Méthodes de protection contre le SPAM n° 2 : tout est une question de timing
Dans le cadre de la série « SPAM protection methods », nous continuons avec la partie 2 et le titre énigmatique « Le timing, c'est tout ». Elle repose sur l'idée que les utilisa…
Méthodes de protection contre le SPAM n° 3 : encore une fois, tout est une question de timing
Pour la navigation entre pages aussi, on peut assez bien exploiter la différence de vitesse entre un bot et un utilisateur réel. Alors qu'un utilisateur reste normalement quelqu…
Traiter une requête HTTP Range avec PHP
Parfois, nous ne voulons pas charger tout le fichier depuis le serveur, mais seulement un certain extrait (Range) du fichier. Nous voulons donc définir un octet de début et un o…
Méthodes de protection contre le SPAM n° 1 : le honeypot
Un sujet pénible depuis les débuts d'Internet est le SPAM (non, pas la viande en conserve, qui existe depuis plus longtemps qu'Internet). Un week-end d'ennui, j'ai réfléchi à la…
Promises JavaScript
Depuis juin 2015, les Promises sont arrivées aussi en JavaScript avec ES6 et peuvent y être utilisées nativement. Peut-être que certains d'entre vous sont comme moi au début et…
Éviter le SPAM avec qmail
Le SPAM. Tout le monde le déteste, personne ne peut (sérieusement) l'éviter. Pour garder la boîte de réception à peu près en ordre, il existe pourtant une solution plutôt confor…
Snippets PHP
Parfois, il faut échanger rapidement plusieurs variables, et je me suis un jour demandé si on pouvait le faire sans variable temporaire. Depuis, c'est ma meilleure pratique :
Les obstacles d'OpenGeoDB
Pour un projet en cours, j'avais besoin d'une liste de tous les codes postaux d'Allemagne avec les noms de villes correspondants. Certes, « plus il y a de données, mieux c'est »…