From a5f9c7c2a1f5b70e49562980d9556cddb5088628 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Sun, 4 Jan 2026 18:30:18 +0100 Subject: [PATCH 01/13] Fix typos in newsletter #5 --- content/newsletter/craft-letter-5.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/content/newsletter/craft-letter-5.md b/content/newsletter/craft-letter-5.md index c5c5c89..fd54d3e 100644 --- a/content/newsletter/craft-letter-5.md +++ b/content/newsletter/craft-letter-5.md @@ -48,7 +48,7 @@ Par exemple, le requêtage des éléments des pages HTML se base essentiellement ## Podcast Code Garage -Le [podcast Code Garage](https://code-garage.com/podcast?tab=classic) 🇫🇷 est celui du site du même nom, qui propose des cours en ligne. +Le [podcast Code Garage](https://code-garage.com/podcast?tab=classic) 🇫🇷 est celui du site du même nom, qui propose des cours en ligne. Dans des épisodes dont la plupart sont courts (moins de quinze minutes en général), Nicolas Brondin-Bernard explique les bases d'une techno, ou son historique. Quelques épisodes plus longs sont consacrés à des interviews. @@ -61,8 +61,7 @@ Plus de 150 épisodes sont disponibles à ce jour. ## Le coût caché des buzzwords dans la tech -Jernej Klancic raconte quelques anecdotes dans lesquelles [l'adoption irréfléchie d'une techno ou d'un principe qui faisait le buzz](https://engineering.leanix.net/blog/trade-offs/) 🇬🇧 lui a jouée de mauvais tours. -Il a établi une liste de questions à se poser avant de prendre une décision de ce type. +Jernej Klancic raconte quelques anecdotes dans lesquelles [l'adoption irréfléchie d'une techno ou d'un principe qui faisait le buzz](https://engineering.leanix.net/blog/trade-offs/) 🇬🇧 lui a jouée de mauvais tours. Il a établi une liste de questions à se poser avant de prendre une décision de ce type. J'ajoute ma propre recommandation : quand ces décisions impactent l'architecture du logiciel que vous développez, je vous invite à les tracer dans un [Architecture Decision Record](https://github.com/joelparkerhenderson/architecture-decision-record?tab=readme-ov-file#what-is-an-architecture-decision-record) (ADR) 🇬🇧, en explicitant les avantages et inconvénients de la techno choisie. C'est un document simple, idéalement au format markdown, qui est suivi sous Git, à côté du code. Dans ce document vous décrivez un problème à résoudre, les solutions que vous avez envisagées, celle que vous avez retenue et pourquoi. Vous notez aussi les conséquences de ce choix, qu'elles soient positives ou négatives. Pourquoi faire ça ? D'une part cela oblige à se poser un minimum de questions lors d'un choix d'architecture, et cela permet de partager ses réflexions avec le reste de l'équipe. D'autre part, cela permet de garder une trace, qui pourra s'avérer utile à l'avenir : quand dans quelques années, quelqu'un se demandera pourquoi telle techno a été choisie, il en trouvera les raisons dans un ADR ; et pourra ainsi juger s'il est pertinent ou pas de remettre en cause ce choix. From c201bd380b759a5f922a92391c26c535f8157e37 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Mon, 5 Jan 2026 19:15:31 +0100 Subject: [PATCH 02/13] Update logo --- content/.DS_Store | Bin 6148 -> 6148 bytes content/images/.DS_Store | Bin 0 -> 6148 bytes content/images/LogoCraftLetter-800px.png | Bin 29125 -> 10975 bytes content/images/craftletter-vertical.png | Bin 0 -> 10482 bytes content/images/craftletter.svg | 227 ++++++++++++++++------- content/images/favicon.svg | 85 +++++++++ logo/craftletter-vertical.psd | Bin 0 -> 128155 bytes logo/craftletter.psd | Bin 0 -> 87762 bytes 8 files changed, 242 insertions(+), 70 deletions(-) create mode 100644 content/images/.DS_Store create mode 100644 content/images/craftletter-vertical.png create mode 100644 content/images/favicon.svg create mode 100644 logo/craftletter-vertical.psd create mode 100644 logo/craftletter.psd diff --git a/content/.DS_Store b/content/.DS_Store index 0538521330fb2eb16a5098aa06c1fbe7341bdfef..c3778004a5cb422c1e9647db236e550f501cf436 100644 GIT binary patch delta 82 zcmZoMXfc=|#>B`mu~2NHo}wrl0|Nsi1A_nqLn=eDXHI@{Qcix-#KPr_Y@7XB)qu~2NHo}wr_0|Nsi1A_nqLkWW}Lk>eKkS^K$ka0PqHAqU3A(^3w zA(0^sSsJLQ2&mYQL60GqA;mK%KRGEUKMANBXbOWP5bI4gV3gP_!?==lGdl-A2hcX4 XiQkzg^NUz=04)O|28PW6B3qaNu{Il! diff --git a/content/images/.DS_Store b/content/images/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..5008ddfcf53c02e82d7eee2e57c38e5672ef89f6 GIT binary patch literal 6148 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 literal 29125 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 literal 0 HcmV?d00001 diff --git a/content/images/craftletter.svg b/content/images/craftletter.svg index 0f300a0..2a71a83 100644 --- a/content/images/craftletter.svg +++ b/content/images/craftletter.svg @@ -1,70 +1,157 @@ - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/content/images/favicon.svg b/content/images/favicon.svg new file mode 100644 index 0000000..2fde9d7 --- /dev/null +++ b/content/images/favicon.svg @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/logo/craftletter-vertical.psd b/logo/craftletter-vertical.psd new file mode 100644 index 0000000000000000000000000000000000000000..a6325897814417116ef1ed911a50482a176e76ce GIT binary patch literal 128155 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 literal 0 HcmV?d00001 diff --git a/logo/craftletter.psd b/logo/craftletter.psd new file mode 100644 index 0000000000000000000000000000000000000000..37684842e784f949fcc89379a52c95e71d024b26 GIT binary patch literal 87762 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 j30zbyrD`eFT3~DiYI`vBi)u-zC862}Lml| Date: Sat, 10 Jan 2026 16:44:30 +0100 Subject: [PATCH 03/13] Add templates and generation script --- scripts/create_newsletter.py | 72 ++++++++++++++++++++++++++++++++++++ template/index.md | 53 ++++++++++++++++++++++++++ template/newsletter.md | 8 ++-- 3 files changed, 128 insertions(+), 5 deletions(-) create mode 100644 scripts/create_newsletter.py create mode 100644 template/index.md diff --git a/scripts/create_newsletter.py b/scripts/create_newsletter.py new file mode 100644 index 0000000..c5837b6 --- /dev/null +++ b/scripts/create_newsletter.py @@ -0,0 +1,72 @@ +import argparse +import locale +from pathlib import Path +from datetime import datetime, timedelta + +MONDAY = 0 # 0 = Monday, 1=Tuesday, 2=Wednesday... + + +def get_next_weekday(d, weekday): + days_ahead = weekday - d.weekday() + if days_ahead <= 0: # Target day already happened this week + days_ahead += 7 + return d + timedelta(days_ahead) + + +def set_publication_date_for_humans(text: str, publication_date: datetime) -> str: + locale.setlocale(locale.LC_TIME, "fr_FR") + date = publication_date.strftime("%d %B %Y") + return text.replace("{DATE}", date) + + +def set_publication_date_for_pelican(text: str, publication_date: datetime) -> str: + date_digits = publication_date.isoformat()[0:10] + return text.replace("{DATE_DIGITS}", date_digits) + + +def set_publication_date_for_seo(text: str, publication_date: datetime) -> str: + locale.setlocale(locale.LC_TIME, "en_US") + date_utc = publication_date.strftime("%a %b %d %Y") + return text.replace("{DATE_UTC}", date_utc) + + +# Parse the command line arguments +parser = argparse.ArgumentParser() +parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter number") +args = parser.parse_args() + +# Load the newsletter template +template = Path("../template/newsletter.md") +content = template.read_text() + + +new_content = content.replace("{LETTER_NUMBER}", str(args.number)) + +today = datetime.today() +next_monday = get_next_weekday(today, MONDAY) + +new_content = set_publication_date_for_humans(new_content, next_monday) + +new_content = set_publication_date_for_pelican(new_content, next_monday) + +new_content = set_publication_date_for_seo(new_content, next_monday) + +# Create the new file +destination = Path(f"../content/newsletter/craft-letter-{args.number}.md") +destination.write_text(new_content) + +# Load the homepage template +template = Path("../template/index.md") +content = template.read_text() + +new_content = set_publication_date_for_pelican(content, next_monday) + +new_content = set_publication_date_for_seo(new_content, next_monday) + +for i in reversed(range(args.number)): + link = f"* [Lettre n°{i + 1}]({{filename}}/newsletter/craft-letter-{i + 1}.md)\n" + new_content += link + +# Update the index page +destination = Path("../content/pages/index.md") +destination.write_text(new_content) diff --git a/template/index.md b/template/index.md new file mode 100644 index 0000000..4bb29e1 --- /dev/null +++ b/template/index.md @@ -0,0 +1,53 @@ +Title: Accueil +Date: {DATE_DIGITS} 09:00 +URL: +save_as: index.html +Category: Home + + + + + +La Craft Letter est une newsletter hebdomadaire dans laquelle je partage des articles +issues de ma veille technologique. Vous y trouverez des articles relatifs au développement logiciel d'une façon générale, qu'il soit front-end, back-end ou autre. Mais aussi des articles consacrés à l'architecture logicielle, la méthodologie, les outils, des projets open source, des conférences... + +Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vous lire l'édito du [premier numéro]({filename}/newsletter/craft-letter-1.md). + + + + +
+ +--- + +# Archives + diff --git a/template/newsletter.md b/template/newsletter.md index 721b199..8ef4f05 100644 --- a/template/newsletter.md +++ b/template/newsletter.md @@ -1,5 +1,5 @@ Title: Lettre n°{LETTER_NUMBER} - {DATE} -Date: {DATETIME} +Date: {DATE_DIGITS} 09:00 Category: Newsletter - - - + \ No newline at end of file From 8dccf165d0e0d61e258a3f089f2be55840d09ee2 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Sat, 10 Jan 2026 16:44:30 +0100 Subject: [PATCH 04/13] Add newsletter #6 --- content/newsletter/craft-letter-6.md | 89 ++++++++++++++++++++++++++++ content/pages/index.md | 5 +- 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 content/newsletter/craft-letter-6.md diff --git a/content/newsletter/craft-letter-6.md b/content/newsletter/craft-letter-6.md new file mode 100644 index 0000000..7a1168b --- /dev/null +++ b/content/newsletter/craft-letter-6.md @@ -0,0 +1,89 @@ +Title: Lettre n°6 - 12 janvier 2026 +Date: 2026-01-12 09:00 +Category: Newsletter + + + +## Édito + + +## Utiliser des graphiques pour tirer un meilleur parti des métriques DORA + +Egor Savochkin explique comment identifier, à l'aide de graphiques, [l'impact des changements de pratiques et d'organisation](https://www.infoq.com/articles/DORA-metrics-PBCs/) 🇬🇧 sur la performance d'une équipe de développement. + +La performance est mesurée par [les métriques DORA](https://blog.stephane-robert.info/docs/devops/dora/) 🇫🇷, telles que décrites dans [Accelerate](https://en.wikipedia.org/wiki/DevOps_Research_and_Assessment) 🇬🇧 : + +* la durée entre la création d'un _commit_ et sa mise en production +* la fréquence de mise en production ; +* le pourcentage des déploiements qui causent un incident en production ; +* le temps requis pour restaurer le service après un incident. + +Suivre l'évolution de ces métriques sur des graphiques "process comportement" (PBC) permet de distinguer les évènements exceptionnels des changements qui ont un impact durable. Cela confirme —ou infirme— l'efficacité des expérimentations menées par les équipes, au lieu de se baser sur des ressentis. + +Il rappelle que les métriques sont un instrument de mesure, pas un objectif. L'absence de récompense liées aux métriques assure qu'il n'y aura pas de tricherie. + +## Langage C3 + +Le [langage C3](https://c3-lang.org/) se base sur le C, et peut être mêlé avec du C, comme le Typescript avec du JavaScript. Il apporte de nombreuses fonctionnalités par rapport à son aîné : génériques, programmation par contrats, type Option pour la gestion de valeurs nulles, etc. + +## Des livres d'intro à Git, Bash, SQL, Docker, Laravel... + + +Bobby Iliev a écrit [une série de livres](https://github.com/bobbyiliev) 🇬🇧, dont certains sont disponibles en open source, au format électronique : + +- 📖   Introduction to Bash Scripting +- 📗   Introduction to Git and GitHub +- 📕   Introduction to SQL +- 🐳   Introduction to Docker +- 💡   Laravel tips and tricks + +Pour les deux premiers, une partie des chapitres est aussi disponible sous forme de vidéo. + +Il a aussi publié des livres qui ne sont pas disponibles gratuitement : + +- 🌍   Introduction to Terraform +- 🐧   Introduction to Linux + + +## Les problèmes posés par la relecture de code + +L'usage des Pull Requests (PR) de Github ou leur équivalent Gitlab, les Merge Requests, est la norme pour la plupart des équipes de développement. Ces pratiques visent à détecter des bugs et à ce que les standards de l'équipe soient respectés. Elles ont pour conséquence une diffusion de la connaissance du code. + +Toutefois elles ne sont pas sans défaut. Un problème fréquent, posé par la dépendance envers les collègues sollicités pour la relecture, est qu'ils/elles mettent parfois plusieurs jours à faire leurs retours. Un autre problème, qui peut être la cause du précédent, c'est la taille trop importante de certaines PR —symptôme révélateur d'une durée de vie trop longue de la branche. Personne n'a envie de relire des PR de plusieurs milliers de lignes. A l'inverse, une PR au contenu trivial ne justifie pas que l'on sollicite des collègues pour une relecture —qui, si elle est rendue obligatoire, n'a pas vraiment de sens dans ce cas. Tous ces problèmes nuisent à la productivité des équipes. + +Une première solution est décrite par MartinFowler dans [Ship / Show / Ask](https://martinfowler.com/articles/ship-show-ask.html) 🇬🇧. Il propose d'adopter des processus différents en fonction de la nature de la PR. + +Une solution plus radicale consiste à passer au [Trunk Based Development](https://thinkinglabs.io/articles/2025/07/21/on-the-benefits-of-trunk-based-development.html) 🇬🇧, dans lequel les branches ont une durée de vie maximale d'une journée, et sont relues, si besoin, après leur fusion dans la branche principale. C'est une des pratiques employées par les équipes les plus performantes, d'après Accelerate. + + +## Les chiffres que devraient connaître les développeurs Python + +Michael Kennedy a effectué une série de benchmarks, dont il livre [les résultats](https://mkennedy.codes/posts/python-numbers-every-programmer-should-know/) 🇬🇧 de façon synthétique. On y découvre que la consommation mémoire d'un processus Python vide est de 16 Mo, tandis qu'importer FastAPI est 500 fois plus long qu'écrire sur disque un fichier d'un Mo. + +## JuJutsu pour les utilisateurs de Git + +JJ, dont je vous ai parlé dans [la lettre n° 4](https://www.craftletter.fr/lettre-ndeg4-29-decembre-2025.html), est une alternative à Git, avec qui il est compatible. +[jj cheatsheet for Git users](https://gist.github.com/elithrar/4a09ef750af5624b729a6f1d87a0431c) 🇬🇧 est un aide mémoire qui m'a été utile ces derniers jours. + +## JuJutsu, pre-commit et Prek + +[pre-commit](https://pre-commit.com/) est un outil qui permet d'exécuter une série de vérifications sur le code avant de le commiter. Les contrôles de base, que vous pouvez choisir d'activer ou pas, sont extensibles au moyen de plugins. Certains peuvent corriger automatiquement les problèmes qu'ils détectent. Il va par exemple vérifier le formatage du code, l'absence d'instructions de debug, le respect de bonnes pratiques du langage, etc. Plus d'une douzaine de langages de programmation sont supportés, ainsi que les Dockerfile. + +Il s'enregistre comme un hook Git, ce qui fait qu'il se déclenche automatiquement quand vous tentez de commiter du code. Si certaines de vérifications ne sont pas satisfaites, le commit échoue. + +JJ n'est pas compatible, pour l'instant, avec pre-commit. Mais il existe une solution : [jj-pre-push](https://pypi.org/project/jj-pre-push/). +pre-commit est écrit en Python. Malgré cela, son exécution est plutôt rapide, car il ne traite, par défaut, que les fichiers que vous avez modifiés. C'est toutefois une bonne idée de l'exécuter dans les pipelines de CI avec pre-commit run --all, de façon à vérifier l'intégralité du code. Non seulement cela garantit que tout votre code respecte les standards que vous avez définis, mais aussi cela permet de pallier au fait que certains développeurs peuvent ne pas l'exécuter sur leur poste. + +Si pre-commit n'est pas assez rapide pour vous, il existe une réécriture en Rust, nommée [Prek](https://prek.j178.dev/). + +## L'open source en danger ? + +Tailwind Labs, malgré le succès croissant de son framework CSS, a vu ses revenus s'effondrer depuis 2 ans. [Les trois quarts des membres de l'équipe technique viennent d'être été licenciés](https://loud-technology.com/blog/tailwind-labs-ia-menace-modele-economique-open-source/) 🇫🇷. En cause : les LLM, qui ont détruit le modèle économique de l'entreprise. Leur usage massif remet en cause la pérennité de nombreux projets open source. + +## Les bases de données en 2025 + +Andy Pavlo publie sa [rétrospective annuelle sur les bases de données](https://www.cs.cmu.edu/~pavlo/blog/2026/01/2025-databases-retrospective.html) 🇬🇧. Il évoque la domination de Postgresql, le procès intenté par MongoDB .inc à l'encontre de Ferret .inc, les formats des fichiers de données... + +## Rétro-ingénierie de jeux vidéo + +Fabien Sanglard a écrit plusieurs livres qui sont devenus des références en matière de rétro-ingénierie de jeux vidéo. [Le premier est consacré à Wolfenstein 3D](https://fabiensanglard.net/gebbwolf3d/) 🇬🇧, l'ancêtre de DOOM. [Le second](https://fabiensanglard.net/gebbdoom/) 🇬🇧 décortique le code et les algorithmes de DOOM, qui était une révolution technique en son temps, ainsi que le matériel sur lequel il tournait dans les années 90 (ordinateurs et consoles). [Le dernier](https://fabiensanglard.net/cpsb/) 🇬🇧 couvre le matériel et le logiciel utilisés par CAPCOM pour faire tourner sur des bornes d'arcade des jeux comme Street Fighter II, Ghouls’n Ghosts, ou Final Fight. diff --git a/content/pages/index.md b/content/pages/index.md index 795effa..9ae3aaa 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -1,5 +1,5 @@ Title: Accueil -Date: 2025-01-05 09:00 +Date: 2026-01-12 09:00 URL: save_as: index.html Category: Home @@ -13,7 +13,7 @@ Category: Home "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], - "datePublished": "Mon Jan 05 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", + "datePublished": "Mon Jan 12 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", @@ -51,6 +51,7 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo # Archives +* [Lettre n°6]({filename}/newsletter/craft-letter-6.md) * [Lettre n°5]({filename}/newsletter/craft-letter-5.md) * [Lettre n°4]({filename}/newsletter/craft-letter-4.md) * [Lettre n°3]({filename}/newsletter/craft-letter-3.md) From 69bff9e86cdfe5f00e7e45c9c369a6c2a4fc6dd8 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Sat, 10 Jan 2026 16:44:30 +0100 Subject: [PATCH 05/13] Delete useless files --- content/newsletter/craft-letter-4.txt | 94 --------------------------- 1 file changed, 94 deletions(-) delete mode 100644 content/newsletter/craft-letter-4.txt diff --git a/content/newsletter/craft-letter-4.txt b/content/newsletter/craft-letter-4.txt deleted file mode 100644 index 4a260d3..0000000 --- a/content/newsletter/craft-letter-4.txt +++ /dev/null @@ -1,94 +0,0 @@ -Title: Lettre n°4 - 29 Décembre 2025 -Date: 2025-12-29 09:00 -Category: Newsletter - -} - -# Craft Letter n°4 - -## Édito - -Cette semaine encore, le contenu de cette newsletter est varié. Je vais en effet vous parler d'outillage, de langages fonctionnels, de recrutement, de sécurité, d'apprentissage ou de révision, et, pour finir, d'architecture basée sur des cellules. Concernant les langages fonctionnels, ceux que j'évoquerai sont mes deux langages favoris : ils associent la simplicité à un système de type qui élimine des classes entières d'erreurs. Le tout accompagné d'une expérience développeur particulièrment agréable. - -Passez de bonnes fêtes de fin d'année, et bonne lecture ! - -## ty - - -Après ruff (https://github.com/astral-sh/ruff) (linter et formateur) et uv (https://github.com/astral-sh/uv) (un gestionnaire de dépendances), Astral (https://astral.sh/) nous propose un troisième outil pour Python : ty (https://docs.astral.sh/ty/), un vérificateur de types (_type checker_) et serveur de langage. Comme ruff et uv, ty est écrit en Rust, et bénéficie de performances bien meilleures que celles des outils concurrents. ruff et uv étant des réussites, ty mérite qu'on le regarde de près. - -## Visualiser des logs avec HL - - - -hl (https://github.com/pamburus/hl?tab=readme-ov-file#performing-complex-queries%5D) est un outil de visualisation de log, écrit en Rust —c'est devenu un argument marketing. Il est capable de capable visualiser, filtrer et requêter rapidement des fichiers de plusieurs gigaoctets. - -## Une liste d'outils autour de Jujutsu - - -Jujutsu (https://www.jj-vcs.dev/) —jj— est une alternative à Git, à la fois plus puissant et plus simple d’utilisation. Il utilise Git comme back-end, ce qui veut dire que vous pouvez l’utiliser de façon transparente sur un projet dont les autres contributeurs utilisent Git. Awesome JJ (https://github.com/Necior/awesome-jj) liste des outils de l’écosystème naissant autour de cet outil. - -J’utilise Jujutsu depuis 8 mois, sur des projets personnels pour l’instant, et je le préfère largement à Git. Le nommage des commandes et options est bien plus clair, ce qui fait qu’on les retient ou retrouve plus facilement. Le workflow est plus simple —car il y a moins de concepts. Malgré cela, il est plus puissant que Git. Par exemple, il ne requiert de résoudre qu'une seule fois les conflits lors d'un rebase, là où Git peut vous demander de les résoudre à plusieurs reprises. - -## Comment trouver des développeurs pour un langage fonctionnel - - -Dans sa keynote lors des Scala Days 2025 🇬🇧 (https://www.youtube.com/watch?v=9OtN4iiFBsQ), Evan Czaplicki explique comment Elm (https://www.youtube.com/watch?v=9OtN4iiFBsQ), le langage qu'il a créé il y a bientôt 14 ans, peut servir de porte d'entrée pour des langages fonctionnels plus complexes, comme Haskell ou Scala. Elm est volontairement simple : les concepts y sont limités au strict minimum. Malgré une syntaxe qui peut intimider au départ, l'apprentissage est rapide, notamment parce que l'expérience développeur est vraiment agréable. Vous trouvez sympathiques les messages d'erreur de Rust ? Ils sont inspirés de ceux de Elm. - -Evan partage dans cette keynote les stratégies de recrutement d'entreprises florissantes qui utilisent Elm. Certaines recrutent les développeurs ou développeuses de modules populaires. D'autres embauchent des débutants et les forment. Les qualités du langage font que ces juniors sont opérationnels et productifs en quelques semaines seulement —n'allez pas croire que c'est exagéré, mon expérience avec Elm me confirme que c'est une réalité. Recruter des débutants disposés à se former est une manière de s'assurer qu'ils ont la culture adéquate : leur volonté d'apprendre sera utile par la suite sur d'autres sujets. Cela répond aussi à l'inquiétude de nombreux managers : comment recruter pour une techno de niche ? - -## Gleam attire l'attention des développeurs - -À propos de langages fonctionnels, Gleam (https://gleam.run/) est le second langage le plus admiré (https://survey.stackoverflow.co/2025/technology#admired-and-desired) par les répondants au dernier sondage de Stack Overflow, juste derrière Rust. Rust truste le sommet de ce classement depuis plusieurs années, ce n'est donc pas une surprise de le retrouver en tête. Gleam, qui est beaucoup plus récent, entre directement à la seconde place de ce sondage, et c'est une vraie surprise pour moi. En effet, je ne m'attendais pas à ce qu'autant de monde connaisse ce langage. Par contre, ses qualités font que je ne suis pas étonné qu'il soit aussi apprécié. Si vous voulez en savoir plus sur Gleam, je vous renvoie vers la conférence que j'ai donnée (https://www.youtube.com/watch?v=nTzNDM-dvRc) 🇫🇷 l'an dernier à ce sujet (27 minutes). - -## Filtrer les candidats en remote - -Jose Zarazua utilise une astuce pour distinguer instantanément les candidats 🇬🇧 (https://josezarazua.com/im-a-former-cto-here-is-the-15-sec-coding-test-i-used-to-instantly-filter-out-50-of-unqualified-applicants) qui réfléchissent et les autres, lors d'un test de recrutement à distance. - -## Des images docker durcies - - - -Des centaines d'images Docker durcies (https://hub.docker.com/hardened-images/catalog), auparavant payantes, sont dorénavant mises à disposition gratuitement (https://www.docker.com/blog/docker-hardened-images-for-every-developer) 🇬🇧 par Docker Inc. Une image durcie est une image dont la sécurité est renforcée, en éliminant tout ce qui n’est pas indispensable, ce qui réduit la surface d’attaque. - -Les images en question sont basées sur Debian et Alpine. Des charts Helm (https://blog.stephane-robert.info/docs/conteneurs/orchestrateurs/outils/helm/) 🇫🇷 sont également disponibles aux mêmes conditions. Un chart Helm décrit le déploiement et la configuration d’une application sous Kubernetes. Les charts, comme les images, sont durcis, et mis à jour en moins d’une semaine quand une faille de sécurité est détectée. Ces images et charts sont sous llicense Apache 2, une license bien connue et très permissive, donc il n'y a pas de mauvaise surprise à attendre de ce côté là. - -## Exposition involontaire de données avec Supabase - -Si vous utilisez Supabase (https://supabase.com/) (Base de données SAAS), vous devriez vérifier que les données des utilisateurs ne sont pas accessibles librement. Supabase ne met pas suffisamment en garde contre ce risque 🇬🇧 (https://skilldeliver.com/your-supabase-is-public). - -Cet article me rappelle des problèmes similaires avec Redis (https://www.tenable.com/plugins/nessus/100634) et MongoDB (https://satoricyber.com/mongodb-security/6-mongodb-authentication-features-you-must-know-about/#how-to-enable-authentication-in-mongodb), pour lesquels l'authentification n'est pas activée par défaut. - -## Apprendre ou réviser une techno en quelques minutes - -Jean-Pierre Liégeois (jeune lecteur du Var) Erwan (https://www.linkedin.com/in/erwannedellec/) m'a rappelé l'existence du site Learn X in Y minutes (https://learnxinyminutes.com). -Plutôt que de s'en servir pour apprendre une nouvelle technologie, il l'utilise pour se rafraichir la mémoire lorsqu'il doit utiliser un langage qu'il n'a pas pratiqué depuis longtemps. - -A cette occasion, j'ai découvert que les fiches proposées par ce site ne se limitent pas à des langages de programmation. Certaines concernent en effet des formats de données (JSON, XML, YAML, Cue...), des langages de balisage légers (Markdown, Restructured Text...), des shells (Bash, Fish), des frameworks et bibliothèques (Jquery, OpenCV...), des outils (Git, Docker), etc. - -## Architecture basée sur des cellules - -Une cellule est un ensemble de microservices et des services dont ils dépendent (cache, base de données, stockage...). Ils forment un ensemble cohérent et (idéalement) autonome —c'est-à-dire qui n'a pas ou peu de dépendances externes. - -Dans une architecture basée sur des cellules (_cell based architecture_), chaque cellule est répliquée à l'identique autant de fois que nécessaire pour supporter la charge (scalabilité). Ces cellules sont déployées dans des régions différentes afin d'assurer la résilience du service. - - Benjamin Cane (https://bencane.com/about) explique dans Cell Boundaries: Defining the Scope of a Cell in Cell-based Architecture (https://itnext.io/cell-boundaries-defining-the-scope-of-a-cell-f76c5c4a52dc) 🇬🇧 comment définir le contenu d'une cellule. - ---- - -Et voilà, c'est tout pour cette semaine ! - - -Retrouvez les numéros précédents sur le site web Craft Letter (https://www.craftletter.fr) 🇫🇷. - - -Si vous n'avez pas reçu cette lettre par email, ou si elle vous a été transmise par un tiers, vous pouvez vous abonner sur le site. - -Pascal Le Merrer - ---- - -Web Version: [webversion] - -Unsubscribe: [unsubscribe] - From 4a46045fb286e6f062a505db9be9bf7f45e7a1ac Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Sat, 10 Jan 2026 23:26:30 +0100 Subject: [PATCH 06/13] Fix JsonLD and RSS feed --- content/newsletter/craft-letter-1.md | 19 +------------------ content/newsletter/craft-letter-2.md | 20 +------------------- content/newsletter/craft-letter-3.md | 19 +------------------ content/newsletter/craft-letter-4.md | 19 +------------------ content/newsletter/craft-letter-5.md | 19 +------------------ content/newsletter/craft-letter-6.md | 1 + content/pages/index.md | 19 +------------------ template/index.md | 19 +------------------ template/newsletter.md | 22 ++-------------------- 9 files changed, 10 insertions(+), 147 deletions(-) diff --git a/content/newsletter/craft-letter-1.md b/content/newsletter/craft-letter-1.md index 6634a78..974bf86 100644 --- a/content/newsletter/craft-letter-1.md +++ b/content/newsletter/craft-letter-1.md @@ -1,24 +1,7 @@ Title: Lettre n°1 - 8 Décembre 2025 Date: 2025-12-08 10:20 Category: Newsletter - - +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°1", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/newsletter/craft-letter-2.md b/content/newsletter/craft-letter-2.md index 509af4d..5531382 100644 --- a/content/newsletter/craft-letter-2.md +++ b/content/newsletter/craft-letter-2.md @@ -1,25 +1,7 @@ Title: Lettre n°2 - 15 Décembre 2025 Date: 2025-12-15 09:00 Category: Newsletter - - - +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°2", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/newsletter/craft-letter-3.md b/content/newsletter/craft-letter-3.md index 17aeb8f..c351d58 100644 --- a/content/newsletter/craft-letter-3.md +++ b/content/newsletter/craft-letter-3.md @@ -1,24 +1,7 @@ Title: Lettre n°3 - 22 Décembre 2025 Date: 2025-12-22 08:20 Category: Newsletter - - +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°3 - 22 Decembre 2025", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 08 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/newsletter/craft-letter-4.md b/content/newsletter/craft-letter-4.md index 1f05eba..dc917ef 100644 --- a/content/newsletter/craft-letter-4.md +++ b/content/newsletter/craft-letter-4.md @@ -1,24 +1,7 @@ Title: Lettre n°4 - 29 Décembre 2025 Date: 2025-12-29 09:00 Category: Newsletter - - +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°4 - 29 Décembre 2025", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Dec 29 2025 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/newsletter/craft-letter-5.md b/content/newsletter/craft-letter-5.md index fd54d3e..64ad813 100644 --- a/content/newsletter/craft-letter-5.md +++ b/content/newsletter/craft-letter-5.md @@ -1,24 +1,7 @@ Title: Lettre n°5 - 5 Janvier 2026 Date: 2026-01-05 09:00 Category: Newsletter - - +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°5 - 5 Janvier 2026", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 05 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/newsletter/craft-letter-6.md b/content/newsletter/craft-letter-6.md index 7a1168b..86296b5 100644 --- a/content/newsletter/craft-letter-6.md +++ b/content/newsletter/craft-letter-6.md @@ -1,6 +1,7 @@ Title: Lettre n°6 - 12 janvier 2026 Date: 2026-01-12 09:00 Category: Newsletter +JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Lettre n°6 - 12 Janvier 2026", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 12 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/content/pages/index.md b/content/pages/index.md index 9ae3aaa..b1c9e60 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -3,24 +3,7 @@ Date: 2026-01-12 09:00 URL: save_as: index.html Category: Home - - +JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 12 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/template/index.md b/template/index.md index 4bb29e1..5953e07 100644 --- a/template/index.md +++ b/template/index.md @@ -3,24 +3,7 @@ Date: {DATE_DIGITS} 09:00 URL: save_as: index.html Category: Home - - +JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "{DATE_UTC} 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } diff --git a/template/newsletter.md b/template/newsletter.md index 8ef4f05..6ea09ad 100644 --- a/template/newsletter.md +++ b/template/newsletter.md @@ -1,23 +1,5 @@ Title: Lettre n°{LETTER_NUMBER} - {DATE} Date: {DATE_DIGITS} 09:00 Category: Newsletter - - - - \ No newline at end of file +JsonLD: + From af4c2d72416b72b0ac4d85fbff856054fd813599 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Fri, 16 Jan 2026 15:16:40 +0100 Subject: [PATCH 07/13] Remove Unnecessary title --- content/newsletter/craft-letter-6.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/content/newsletter/craft-letter-6.md b/content/newsletter/craft-letter-6.md index 86296b5..a11c770 100644 --- a/content/newsletter/craft-letter-6.md +++ b/content/newsletter/craft-letter-6.md @@ -5,8 +5,6 @@ JsonLD: { "@context": "https://schema.org", "@type": "BlogPosting", "name": "Let -## Édito - ## Utiliser des graphiques pour tirer un meilleur parti des métriques DORA From d04d523bdf8e0588289b7f09fe3bc9b0dc8ac817 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Fri, 16 Jan 2026 17:19:41 +0100 Subject: [PATCH 08/13] Replace Make with Just --- Makefile | 79 -------------------- justfile | 59 +++++++++++++++ prepare_email.py => scripts/prepare_email.py | 0 3 files changed, 59 insertions(+), 79 deletions(-) delete mode 100644 Makefile create mode 100644 justfile rename prepare_email.py => scripts/prepare_email.py (100%) diff --git a/Makefile b/Makefile deleted file mode 100644 index 31db304..0000000 --- a/Makefile +++ /dev/null @@ -1,79 +0,0 @@ -PY?= -PELICAN?=pelican -PELICANOPTS= - -BASEDIR=$(CURDIR) -INPUTDIR=$(BASEDIR)/content -OUTPUTDIR=$(BASEDIR)/output -CONFFILE=$(BASEDIR)/pelicanconf.py -PUBLISHCONF=$(BASEDIR)/publishconf.py - - -DEBUG ?= 0 -ifeq ($(DEBUG), 1) - PELICANOPTS += -D -endif - -RELATIVE ?= 0 -ifeq ($(RELATIVE), 1) - PELICANOPTS += --relative-urls -endif - -SERVER ?= "0.0.0.0" - -PORT ?= 0 -ifneq ($(PORT), 0) - PELICANOPTS += -p $(PORT) -endif - - -help: - @echo 'Makefile for a pelican Web site ' - @echo ' ' - @echo 'Usage: ' - @echo ' make html (re)generate the web site ' - @echo ' make clean remove the generated files ' - @echo ' make regenerate regenerate files upon modification ' - @echo ' make publish generate using production settings ' - @echo ' make serve [PORT=8000] serve site at http://localhost:8000' - @echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 ' - @echo ' make devserver [PORT=8000] serve and regenerate together ' - @echo ' make devserver-global regenerate and serve on 0.0.0.0 ' - @echo ' make mail file=FILEPATH generate HTML email ' - @echo ' ' - @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html ' - @echo 'Set the RELATIVE variable to 1 to enable relative urls ' - @echo ' ' - -html: - "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) - -clean: - [ ! -d "$(OUTPUTDIR)" ] || rm -rf "$(OUTPUTDIR)" - -regenerate: - "$(PELICAN)" -r "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) - -serve: - "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) - -serve-global: - "$(PELICAN)" -l "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b $(SERVER) - -devserver: - "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) - -devserver-global: - "$(PELICAN)" -lr "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(CONFFILE)" $(PELICANOPTS) -b 0.0.0.0 - -publish: - "$(PELICAN)" "$(INPUTDIR)" -o "$(OUTPUTDIR)" -s "$(PUBLISHCONF)" $(PELICANOPTS) - rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www - -ssh: - ssh craftletter@ssh-craftletter.alwaysdata.net - -mail: - PYTHONPATH=PWD venv/bin/python ./prepare_email.py $(file) - -.PHONY: html help clean regenerate serve serve-global devserver devserver-global publish mail diff --git a/justfile b/justfile new file mode 100644 index 0000000..797be8b --- /dev/null +++ b/justfile @@ -0,0 +1,59 @@ +CONFFILE := "pelicanconf.py" +PUBLISHCONF := "publishconf.py" +PELICANOPTS := "" +SERVER := "localhost" + +default: + just --list + +help: + @echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html ' + @echo 'Set the RELATIVE variable to 1 to enable relative urls ' + + +# (re)generate the web site +html: + pelican content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} + +# remove the generated files +clean: + [ ! -d "output" ] || rm -rf output + +# regenerate files upon modification +regenerate: + pelican -r content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} + +# serve site at http://localhost:8000 +serve: + pelican -l content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} + +# serve (as root) to {{SERVER}}:80 +serve-global: + pelican -l content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b {{SERVER}} + +# serve and regenerate together +devserver: + pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} + +# regenerate and serve on 0.0.0.0 +devserver-global: + pelican -lr content -o output -s "{{CONFFILE}}" {{PELICANOPTS}} -b 0.0.0.0 + +# generate using production settings +publish: + pelican content -o output -s "{{PUBLISHCONF}}" {{PELICANOPTS}} + rsync -e ssh -av --delete-after /Users/pascal/Documents/craft-letter/output/ craftletter@ssh-craftletter.alwaysdata.net:/home/craftletter/www + +# connect to production server +ssh: + ssh craftletter@ssh-craftletter.alwaysdata.net + +# Create the skeleton for a new issue of the newsletter, and reference it into the home page +new number: + PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py {{number}} + +# generate HTML email +mail file: + echo {{file}} + PYTHONPATH=PWD venv/bin/python ./scripts/prepare_email.py {{file}} + diff --git a/prepare_email.py b/scripts/prepare_email.py similarity index 100% rename from prepare_email.py rename to scripts/prepare_email.py From 36ea0dd3f7cadb0c8767992fe6088b23a2be8e99 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Fri, 16 Jan 2026 17:19:41 +0100 Subject: [PATCH 09/13] Add newsletter #7 --- content/newsletter/craft-letter-7.md | 70 ++++++++++++++++++++++++++++ content/pages/index.md | 5 +- 2 files changed, 73 insertions(+), 2 deletions(-) create mode 100644 content/newsletter/craft-letter-7.md diff --git a/content/newsletter/craft-letter-7.md b/content/newsletter/craft-letter-7.md new file mode 100644 index 0000000..7a22973 --- /dev/null +++ b/content/newsletter/craft-letter-7.md @@ -0,0 +1,70 @@ +Title: Lettre n°7 - 19 janvier 2026 +Date: 2026-01-19 09:00 +Category: Newsletter +JsonLD: + + +# Lettre N°7 + +Voici quelques articles qui m’ont marqué ces derniers jours. + +Bonne lecture ! + +--- + +## DataStar + +Vous avez probablement déjà entendu parler de [HTMX](https://htmx.org/). C’est un framework JS léger, qui vise à fournir une expérience proche de celle des Single Page Applications, mais en écrivant pas ou peu de JavaScript. Les interactions avec l’application déclenchent l’envoi de fragments HTML par le serveur, de façon à mettre à jour la page. Il n’y a pas d’échange de JSON comme avec React, Vue, Angular, Elm ou équivalent. L’état de l’application, et sa logique, sont gérés côté serveur, dans un langage au choix (Java, PHP, Go…) + +[DataStar](https://data-star.dev/) a le même objectif, mais corrige les défauts de HTMX. En effet, ce dernier montre ses limites quand les fonctionnalités des applications s’enrichissent. Il faut ajouter du JavaScript, et la complexité du code HTMX augmente significativement. DataStar résout ces problèmes : le code back-end seul suffit à la réalisation d’applications riches. De plus, en se basant sur les SSE (Server Side Events), il simplifie le développement d’applications collaboratives. Cerise sur le gâteau, il cumule légèreté et performances, ce qui est parfait pour une démarche d’éco-conception et résulte en une bonne expérience utilisateur. + +## Les frameworks Python en production + +Dans [ce podcast](https://talkpython.fm/episodes/show/533/web-frameworks-in-prod-by-their-creators), les créateurs de framerworks Python (Flask, Django, FastAPI, Litestat et Quart) partagent leurs recommandations en terme de stack, de performances, d’asynchronisme, . d’auto-hébergement… Une synthèse écrite est disponible. + +Quelques points en particulier ont retenu mon attention : + +* [uvloop](https://github.com/MagicStack/uvloop) fournit une boucle d’événements deux fois plus rapide que celle d’asyncio ; +* [orjson](https://github.com/ijl/orjson) est plus rapide que le module JSON de la bibliothèque standard de Python, tout en assurant la sérialisation de types non supportés par ce dernier ; +* un unique appel de fonction bloquant suffit à bloquer l’intégralité d’une application pendant son exécution. En pratique, il ne faut déclarer comme asynchrone que les fonctions dont nous sommes certains qu’elles ne comportent que des appels non-bloquants. + +Les participants mentionnent aussi leur intérêt pour certaines technos dont je vous ai parlé récemment : HTMX, DataStar et [Sqlite](https://www.craftletter.fr/lettre-ndeg2-15-decembre-2025.html). + +## SoCraTes Rennes + +*Pour être transparent, je me dois de préciser que je suis organisateur de cet évènement.* + +La sixième édition de [SoCraTes Rennes](https://socrates-rennes.github.io/) aura lieu le 31 mars 2026. Il s’agit de la déclinaison, sur une journée, des non-conférences SoCraTes telles que [SoCraTes France](https://socrates-fr.github.io/). SoCraTes signifie "SOftware Craft and Testing". Le néologisme "non-conférence" retranscrit le fait que ce n’est pas l’équipe d’organisation qui définit le programme. Ce sont les participant·e·s qui ont la possibilité de proposer des sujets, sur place. Ce que j’aime dans ce type d’évènement c’est la richesse des échanges, bien supérieure à celle des conférences traditionnelles. + +Si vous souhaitez donner de la visibilité à votre entreprise, il est encore possible de [sponsoriser cette journée](https://socrates-rennes.frama.space/s/oGgqEkSADLBYaX8). Parlez-en à votre employeur 😉 + +## Comment fonctionne un terminal ? + +Si vous voulez savoir comment fonctionne un terminal, voici [la réponse](https://how-terminals-work.vercel.app/), sous forme interactive. + +## Se lancer dans l’open source + +[Contrib.FYI](https://k-dash.github.io/contrib-fyi/) liste des tâches à réaliser sur des projets open-source Ces tâches sont adaptées à une première contribution. Elles sont affichées par ordre chronologique, dans le but de faciliter des découvertes par sérendipité. + +## L’efficacité du pair-programming + +Thierry De Pauw [débunke un post critique à l’égard du pair-programming](https://thinkinglabs.io/articles/2026/01/13/on-the-effectiveness-of-pair-programming.html). Il explique pourquoi, contrairement à une croyance répandue, il coûte moins cher de travailler à deux plutôt que seul sur les sujets exploratoires. Il évoque aussi des avantages comme la diffusion de la connaissance et l’impact positif sur le moral de l’équipe. Il conclut en mentionnant que le Software Teaming (aussi appelé Mob Programming ou Ensemble Programming) est encore plus efficace que le Pair Programming. + +Ce sujet me parle, puisque j’ai donné [une conférence](https://devconf.net/talk/pair-programming-et-si-on-gagnait-du-temps-pascal-le-merrer) qui développait des arguments similaires. + +## Combien y a-t-il de moteurs JavaScript ? + +Le nombre de [moteurs qui permettent d’exécuter du code JavaScript](https://zoo.js.org/) est étonnant. + +## Stratégie européenne pour un écosystème numérique ouvert + +La Commission Européenne commence enfin à prendre conscience de l’importance de l’Open Source, et de notre dépendance excessive aux solutions États-Uniennes. Si ces sujets vous préoccupent, vous pouvez [donner votre avis](https://ec.europa.eu/info/law/better-regulation/have-your-say/initiatives/16213-Ecosystemes-numeriques-ouverts-europeens_fr), en espérant qu’il sera pris en compte dans de futures lois. + +## Docker veut simplifier les déploiements en production + +Docker Compose est adapté au développement d’applications, pas à leur déploiement en production. Ce dernier passe souvent par des outils complexes, tels que Helm ou Kustomize, configurés à grand renfort de fichiers YAML. +Docker a lancé [un nouvel outil nommé Kanvas](https://www.infoq.com/news/2026/01/docker-kanvas-cloud-deployment/), qui utilise la syntaxe familière de Docker Compose, et revendique une plus grande simplicité que ses concurrents. Il génère aussi une représentation graphique détaillée de l’architecture, qui peut s’avérer utile aussi bien pour communiquer que pour débugger. + +---- + +C’est tout pour cette semaine ! diff --git a/content/pages/index.md b/content/pages/index.md index b1c9e60..087facf 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -1,9 +1,9 @@ Title: Accueil -Date: 2026-01-12 09:00 +Date: 2026-01-19 09:00 URL: save_as: index.html Category: Home -JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 12 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } +JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 19 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } @@ -34,6 +34,7 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo # Archives +* [Lettre n°7]({filename}/newsletter/craft-letter-7.md) * [Lettre n°6]({filename}/newsletter/craft-letter-6.md) * [Lettre n°5]({filename}/newsletter/craft-letter-5.md) * [Lettre n°4]({filename}/newsletter/craft-letter-4.md) From 912993f17d3c261befeb2e682a77bef763f4938e Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Thu, 22 Jan 2026 11:39:31 +0100 Subject: [PATCH 10/13] Fix generation script for invocation from just --- justfile | 2 +- scripts/create_newsletter.py | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index 797be8b..c5fb0f5 100644 --- a/justfile +++ b/justfile @@ -50,7 +50,7 @@ ssh: # Create the skeleton for a new issue of the newsletter, and reference it into the home page new number: - PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py {{number}} + PYTHONPATH=PWD venv/bin/python ./scripts/create_newsletter.py --number={{number}} # generate HTML email mail file: diff --git a/scripts/create_newsletter.py b/scripts/create_newsletter.py index c5837b6..9a8202c 100644 --- a/scripts/create_newsletter.py +++ b/scripts/create_newsletter.py @@ -36,7 +36,7 @@ parser.add_argument("-n", "--number", required=True, type=int, help="Newsletter args = parser.parse_args() # Load the newsletter template -template = Path("../template/newsletter.md") +template = Path("./template/newsletter.md") content = template.read_text() @@ -52,11 +52,11 @@ new_content = set_publication_date_for_pelican(new_content, next_monday) new_content = set_publication_date_for_seo(new_content, next_monday) # Create the new file -destination = Path(f"../content/newsletter/craft-letter-{args.number}.md") +destination = Path(f"./content/newsletter/craft-letter-{args.number}.md") destination.write_text(new_content) # Load the homepage template -template = Path("../template/index.md") +template = Path("./template/index.md") content = template.read_text() new_content = set_publication_date_for_pelican(content, next_monday) @@ -68,5 +68,5 @@ for i in reversed(range(args.number)): new_content += link # Update the index page -destination = Path("../content/pages/index.md") +destination = Path("./content/pages/index.md") destination.write_text(new_content) From 8543589d23f304b88403323079cb509cb7081ca6 Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Thu, 22 Jan 2026 11:39:31 +0100 Subject: [PATCH 11/13] Add newsletter #8 --- content/newsletter/craft-letter-8.md | 74 ++++++++++++++++++++++++++++ content/pages/index.md | 6 ++- mdtosendy_config/styles.css | 5 ++ 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 content/newsletter/craft-letter-8.md diff --git a/content/newsletter/craft-letter-8.md b/content/newsletter/craft-letter-8.md new file mode 100644 index 0000000..5ea7dec --- /dev/null +++ b/content/newsletter/craft-letter-8.md @@ -0,0 +1,74 @@ +Title: Lettre n°8 — 26 janvier 2026 +Date: 2026-01-26 09:00 +Category: Newsletter +JsonLD: + + +# Lettre n° 8 + + +## Tendances de la tech en 2025 + +InfoQ a rassemblé dans un *ebook* leurs articles de synthèse sur [les tendances de la tech 2025](https://www.infoq.com/minibooks/2025-infoq-trends-reports-emag/) 🇬🇧. Ils y détaillent pour 5 domaines leur vision (subjective) de l’adoption de certaines technologies et pratiques : + +* Architecture logicielle et conception ; +* Culture et méthodes ; +* AI, ML et Data Engineering ; +* Cloud et Devops ; +* Java (au sens large : cela inclut divers langages qui fonctionnent sur la JVM, comme Kotlin, Scala, Clojure…). + +À chaque fois, ils positionnent l’adoption de ces technologies et pratiques selon des paliers inspirés de la théorie de la diffusion de l’innovation, d’Everett Rogers : + +* innovateurs, +* primo-adoptants, +* majorité précoce, +* majorité tardive. + +Cette classification est établie et commentée par les rédacteurs qui contribuent à InfoQ tout au long de l’année dans ces différents domaines. + +## Plakar + +Tar est un format d’archivage qui date de 1979. À cette époque, les données étaient enregistrées sur bande magnétique. C’est un format simple, qui se contente de concaténer le contenu de plusieurs fichiers, sans même les compresser. + +[Plakar](https://github.com/PlakarKorp/plakar) 🇬🇧 est un format récent, qui se veut un remplaçant de Tar. Par rapport à ce dernier, il ajoute de la compression, de la déduplication, du chiffrement, du versionnement… De plus, les données sont consultables sans être extraites entièrement, et il est beaucoup plus rapide grâce à la parallélisation. + +## Pourquoi Zig est-il si cool ? + +Nilo Stolte est _très_ expérimenté. Il explique pourquoi [Zig est un langage dont certaines fonctionnalités l’impressionnent](https://nilostolte.github.io/tech/articles/ZigCool.html)🇬🇧. En particulier des fonctionnalités qu’il pensait réservées aux langages interprétés, qu'il présente dans un tutoriel d'introduction au langage. + +## JQuery n’est pas mort ! + +JQuery fête ses vingt ans en publiant une [nouvelle version majeure](https://blog.jquery.com/2026/01/17/jquery-4-0-0/)🇬🇧 ! C’est une surprise, car, avec les *Single Page Applications* et les progrès des navigateurs, il faut avouer que cette bibliothèque omniprésente dans les projets Web du début des années 2000 a pris un gros coup de vieux. + +## Détection de fuite mémoire dans les navigateurs avec Memlab + +Facebook a publié en open source [MemLab](https://github.com/facebook/memlab)🇬🇧, un outil pour détecter les fuites de mémoire causées par du code JavaScript exécuté par un navigateur. Il s’appuie sur Puppeteer, un outil d’automatisation des tests. Il est utilisé ici pour décrire les scénarios à exécuter dans le navigateur, et pour lesquels MemLab va rechercher d’éventuelles fuites de mémoire. + +## Les challenges du Soft Delete + +Au lieu d’effacer des données d’une base, vous pouvez ajouter une colonne qui indique quand elles ont été archivées, afin de pouvoir annuler cet "effacement", ou à des fins de traçabilité. C’est ce qu’on appelle un *soft delete*. Cette approche peut avoir des conséquences gênantes, mais [il existe des alternatives](https://atlas9.dev/blog/soft-delete.html)🇬🇧. + +## Pourquoi est-il difficile d’être fainéant ? + +SpeakEZ Technology explique comment sont gérées, dans différents langages, [les variables ou expressions *lazy*](https://speakez.tech/blog/why-lazy-is-hard/)🇬🇧. *Lazy* signifie ici qu’elles ne sont évaluées que lorsqu’on y accède pour la première fois. Le terme employé en français, *initialisation tardive*, est bien plus clair. + +## Supprimer Rust pour améliorer les performances + +Souvent, pour améliorer les performances, une réécriture de la totalité ou d’une partie du code en Rust est une bonne piste. Mais chez Prisma, qui développe un ORM en TypeScript, c’est l’inverse qui s’est produit : la [réécriture d’un module Rust en TypeScript](https://www.prisma.io/blog/announcing-prisma-orm-7-0-0#moving-away-from-rust)🇬🇧 a rendu les requêtes trois fois plus rapides ! + +## Serendipitech + +Anne-Laure Gros vient de lancer [Serendipitech](https://www.serendipitech.fr/)🇫🇷, un site qui recense des conférences Agiles, Craft et Tech, et vous informe des ouvertures / fermetures de CFP. + +## Le CFP du Breizhcamp est ouvert + +Le [CFP du Breizhcamp](https://sessionize.com/breizhcamp-2026)🇫🇷, la conférence tech Rennaise qui aura lieu du 24 au 26 juin prochains, est ouvert. + +## Rennes Tech + +Pour continuer dans l’actualité tech Rennaise, le site [Rennes Tech](https://rennes.tech/)🇫🇷, qui recense l’actualité des communautés techniques de la ville, renait de ses cendres. + + +---- + +C’est tout pour cette semaine ! diff --git a/content/pages/index.md b/content/pages/index.md index 087facf..b3b53c7 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -1,9 +1,9 @@ Title: Accueil -Date: 2026-01-19 09:00 +Date: 2026-02-02 09:00 URL: save_as: index.html Category: Home -JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Jan 19 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } +JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 02 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } @@ -34,6 +34,8 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo # Archives +* [Lettre n°9]({filename}/newsletter/craft-letter-9.md) +* [Lettre n°8]({filename}/newsletter/craft-letter-8.md) * [Lettre n°7]({filename}/newsletter/craft-letter-7.md) * [Lettre n°6]({filename}/newsletter/craft-letter-6.md) * [Lettre n°5]({filename}/newsletter/craft-letter-5.md) diff --git a/mdtosendy_config/styles.css b/mdtosendy_config/styles.css index c8e62f9..248ca40 100644 --- a/mdtosendy_config/styles.css +++ b/mdtosendy_config/styles.css @@ -238,3 +238,8 @@ i { display: block; } +hr { + color: #CCCCCC; + margin-top: 40px; + margin-bottom: 40px; +} From 8697e27cb31a0959b9006c4fff206a92192ca3ef Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Thu, 22 Jan 2026 11:39:31 +0100 Subject: [PATCH 12/13] Add newsletter #9 --- content/newsletter/craft-letter-9.md | 72 ++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 content/newsletter/craft-letter-9.md diff --git a/content/newsletter/craft-letter-9.md b/content/newsletter/craft-letter-9.md new file mode 100644 index 0000000..f9a237e --- /dev/null +++ b/content/newsletter/craft-letter-9.md @@ -0,0 +1,72 @@ +Title: Lettre n°9 - 02 février 2026 +Date: 2026-02-02 09:00 +Category: Newsletter +JsonLD: + + +## Écoute le vieux sage… + +Addy Osmany n’est pas si vieux, mais partage sa sagesse à travers [des leçons qu’il a tirées de son expérience chez Google](https://addyosmani.com/blog/21-lessons/)🇬🇧. Elles me paraissent pertinentes, même si bien entendu tout n’est pas nouveau dans ce qu’il écrit. Comme la [loi de Goodhart](https://fr.wikipedia.org/wiki/Loi_de_Goodhart)🇫🇷, qu’il cite sans la nommer. + +## Choisir des icônes + +Stéphanie Walter donne une série de recommandations sur la façon de [choisir des icônes](https://stephaniewalter.design/blog/tips-on-how-to-pick-the-right-icons-for-your-website-with-icons8) 🇫🇷. Elle s’adresse à des personnes qui n’ont pas ou peu de notions de design. + +## Git bisect + +Si je devais classer les commandes Git par utilité, [git bisect](https://engineering.leanix.net/blog/git-bisect/)🇬🇧 serait probablement dans le trio de tête. Elle permet de retrouver rapidement le commit à l’origine d’un bug. Mais pour qu’elle soit efficace, il est indispensable de faire de petits commits. Savoir qu’un problème a été introduit par une modification de mille lignes de code ne serait pas très utile. + +## Outils de développement et tests d’API + +Vous connaissez probablement [Postman](https://www.postman.com/), un outil pour stocker et jouer des requêtes HTTP, très utile quand on développe une API. Cet outil open source populaire [s’est dégradé](https://readmedium.com/enshittification-of-a-beloved-open-source-tool-postman-24e0837bcff7)🇬🇧 au fil du temps. Le stockage des requêtes, depuis qu’il se fait sur les serveurs de l’entreprise derrière Postman, pose des problèmes de confidentialité. + +J’ai utilisé [Bruno](https://www.usebruno.com/), un outil similaire. Je viens de découvrir qu’il était maintenant au centre d’une offre payante. Je n’ai rien contre le principe, il me parait normal d’essayer de vivre de son travail. J’espère juste que cela ne se traduira pas par une évolution comparable à celle de Postman —ce n’est pas le cas pour l’instant. + +[Posting](https://posting.sh/) : qui propose des fonctionnalités similaires, mais dans le terminal. La roadmap, définie par la communauté, est toutefois un peu surprenante : avoir un fond de fenêtre transparent y est plus urgent que pouvoir modifier les paramètres ou en-têtes des requêtes 🤔 + +Il existe d’autres outils de ce type, comme [Hoppscotch](https://docs.hoppscotch.io/), qui est proposé en SAAS, mais aussi en auto-hébergement. + +## {JSON} Placeholder + +[{JSON} Placeholder](https://jsonplaceholder.typicode.com/) expose une API que vous pouvez utiliser quand vous avez besoin d’une API rapidement, mais qui n’a finalement que peu d’importance pour vous. Elle peut servir dans le cadre d’une formation, d’un kata de code, d’une démo, d’une présentation… Elle expose des endpoints pour gérer des posts, des commentaires, des albums, des photos, des listes de tâches, et des utilisateurs. + +## Les logs, ça craint + +Beaucoup de logs sont inutiles, parce qu’ils manquent de contexte. Le problème n’est pas nouveau, loin de là, mais il est encore d’actualité. De plus, rechercher l’origine d’un bug dans les logs d’un site à fort trafic s’apparente à chercher une aiguille dans une botte de foin. Boris Tane explique [comment les Wide Events aident à résoudre ces problèmes](https://loggingsucks.com/). + +## Un livre gratuit sur l’accessibilité + +[Accessibility for Everyone](https://accessibilityforeveryone.site/) de Laura Kalbag n’est pas récent, il date de 2017, mais n’est pas complètement obsolète non plus. Si les outils ont changé, les principes qu’il décrit restent valides. Il est dorénavant disponible gratuitement. + +## Forum Ruby + +Un nouveau [forum](https://www.rubyforum.org)🇬🇧 pour la communauté Ruby est en ligne. Il est dédié aux échanges entre développeurs/développeuses, quel que soit leur niveau ; de façon surprenante pour moi, les offres d’emploi n’y sont pas les bienvenues. + +## Comment les LLM sabotent les pratiques de programmation en privatisant un bien public + +Michiel Buddingh explique comment les entreprises qui créent des LLM sont en train de nous faire [revenir à la situation qui prévalait avant l’avènement du Web](https://michiel.buddingh.eu/enclosure-feedback-loop)🇬🇧 : l’accès à la connaissance était payant. + +## Quand refactorer votre code ? + +Nick Cosentino liste des signes révélateurs de la [nécessité de refactorer votre code](https://www.devleader.ca/2023/11/24/when-to-refactor-code-how-to-maximize-efficiency-and-minimizing-tech-debt/)🇬🇧. +Il cite aussi quelques techniques de refactoring. J’ai regretté, à la lecture de cet article, qu’il recommande de définir des métriques pour mesurer l’efficacité du refactoring, sans en mentionner. + +## Créer des applications Python pour le terminal + +[Rich](https://rich.readthedocs.io/en/stable/introduction.html) est une bibliothèque bien connue du monde Python, pour améliorer l’affichage des données dans le terminal. [Textual](https://www.textualize.io/) va plus loin, car il s’agit d’un framework pour créer de véritables applications. [Typer](https://typer.tiangolo.com/), bien qu’il se présente comme un équivalent, me semble moins riche fonctionnellement. Par contre son haut niveau d’abstraction fait qu’il peut être intéressant pour ce qui est de parser les arguments de la ligne de commande. + + +## Elm serait-il un bon choix pour votre équipe ? + +Brian Dukes détaille les raisons qui font qu’une techno de niche comme Elm peut [être, ou ne pas être, un bon choix](https://engagesoftware.com/posts/is-elm-the-right-choice-for-your-team/)🇬🇧 pour votre équipe. Elm est un langage fonctionnel dédié à la création de *Single Page Applications*. + +## Alpes Craft 2026 + +[Alpes Craft](https://www.alpescraft.fr/)🇫🇷 aura lieu les 4 et 5 juin prochain. Cet évènement cumule une conférence classique, le premier jour, avec une non-conférence, le lendemain. Si vous ne connaissez pas les non-conférences, je vous invite à relire la courte description que j’en ai faite dans [la lettre N°7](https://www.craftletter.fr/lettre-ndeg7-19-janvier-2026.html)🇫🇷, dans la partie consacrée à [SoCraTes Rennes](https://socrates-rennes.github.io/)🇫🇷. + +Comme l’indique son nom, Alpes Craft est consacré à la tech, mais pas à une technologie particulière. + +--- + +C’est tout pour cette semaine ! + From 19ea597528d412408ea175952fb7a3d2f66e86cf Mon Sep 17 00:00:00 2001 From: Pascal Le Merrer Date: Thu, 22 Jan 2026 11:39:31 +0100 Subject: [PATCH 13/13] Add newsletter #10 --- content/newsletter/craft-letter-10.md | 66 +++++++++++++++++++++++++++ content/pages/index.md | 5 +- 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 content/newsletter/craft-letter-10.md diff --git a/content/newsletter/craft-letter-10.md b/content/newsletter/craft-letter-10.md new file mode 100644 index 0000000..d6ed7d1 --- /dev/null +++ b/content/newsletter/craft-letter-10.md @@ -0,0 +1,66 @@ +Title: Lettre n°10 — 09 février 2026 +Date: 2026-02-09 09:00 +Category: Newsletter +JsonLD: + + + +## Swift n’est pas le langage que vous croyez + +Dans un article qui date de 2023, Naman Goel compare [Swift et Rust](https://nmn.sh/blog/2023-10-02-swift-is-the-more-convenient-rust) 🇬🇧. Selon lui on retrouve des concepts de Rust dans Swift, comme le pattern matching ou la gestion des valeurs nulles, avec une syntaxe plus familière. Les [énumérations en Swift ](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/enumerations)🇬🇧 sont des [types algébriques](https://fr-academic.com/dic.nsf/frwiki/1669687) 🇫🇷, c’est-à-dire qu’ils combinent plusieurs autres types, pas seulement des constantes. C’est un autre concept issu de la programmation fonctionnelle. + +Swift est un langage multi paradigme : impératif, orienté objet et fonctionnel. La gestion de la mémoire est basée sur le [comptage de références](https://fr.wikipedia.org/wiki/Comptage_de_r%C3%A9f%C3%A9rences)🇫🇷. Il n’utilise pas de ramasse-miettes (*garbage collector*) pour libérer la mémoire, ce qui évite les pauses dans l’exécution du code. Il est compilé en code machine à l’aide de LLVM, ce qui lui permet de générer des applications pour toutes les plateformes supportées par ce dernier. + +L’affirmation selon laquelle Swift serait un Rust plus simple ne me convainc pas —il y a bien des points communs entre ces langages, mais aussi pas mal de différences. Ce qui m’a plus intéressé, et que j’ai découvert grâce à cet article, c’est que Swift n’est plus limité à l’écosystème Apple. En effet, depuis 2020. Il peut générer des programmes pour Windows ou Linux, et la génération d’application d’Android est sur le point d’arriver. + +D’ailleurs, [Apple veut étendre son utilisation au cloud](https://www.infoq.com/presentations/swift-apps-services/) 🇬🇧. + +## JQ Quest + +Jq est un outil bien connu pour manipuler du JSON en ligne de commande. Il peut vous éviter d’écrire un script qui doit transformer ou filtrer des données. [JQ Quest](https://codeberg.org/gturri/jq-quest) 🇬🇧 est une série d’exercice pour apprendre à vous servir de JQ. + +## State Of Js 2025 + +Si vous vous êtes curieux·se de connaître les outils à la mode dans l’écosystème JavaScript, +vous pouvez consulter les résultats du sondage [State of JS 2025](https://2025.stateofjs.com/en-US) 🇬🇧. Ils sont en ligne —même si la page d’accueil ne l’indique pas encore à l’heure où je rédige cette neswletter... Oups. + +Quelques points qui m’ont interpelés : + +* Angular est toujours aussi peu apprécié : plus d’une personne sur deux qui l’a essayé n’a pas aimé l’expérience. +* Le taux de satisfaction des utilisateurs de HTMX est en baisse (de 84% en 2016 à 69% en 2025) ; je soupçonne que cela correspond à la découverte des limitations de ce framework quand les applications deviennent plus complexes. Datastar, dont je vous parlais dans [la lettre n°7](http://127.0.0.1:8000/lettre-ndeg7-19-janvier-2026.html), n’apparait pas dans ce sondage, c’est dommage, car j’aurais bien aimé découvrir les retours d’expérience à son sujet. +* La satisfaction des utilisateurs de React est également en baisse régulière (de 92% en 2016 à 72% en 2025). +* Cypress (Tests End-to-end), autrefois très populaire, a perdu de sa superbe, puisque à peine plus de la moitié des utilisateurs ont envie de le réutiliser. +* À l’inverse, Playwright (tests End-to-end), Vitest (tests unitaires), Vite (build), Astro (framework pour créer des sites de contenu), Bun (alternative à NodeJs), Hono et Fastify (frameworks Web) sont appréciés par une large majorité de ceux qui les ont utilisés. +* Solid (Framework Front-end) maintient depuis 2021 un taux de satisfaction autour de 90% ; il mériterait sans doute plus d’attention. + +## ReliCSS : un outil pour faire de l’archéologie dans le Front-End + +[ReliCSS](https://www.alwaystwisted.com/articles/introducing-relicss-a-tool-for-front-end-archaeology)🇬🇧 est un nouvel outil qui identifie les directives obsolètes dans les feuilles de style CSS ❤️. Il n’est disponible que sous la forme d’une application Web pour l’instant, mais une version en ligne de commande est prévue. + +## Réviser les concepts des API REST + +Datacamp a publié une [synthèse sur les API REST](https://www.datacamp.com/blog/rest-api-interview-questions) 🇬🇧. Simple et efficace, j’aime beaucoup la forme ! +## Turso : une réécriture de SQLite en Rust + +[Turso](https://kerkour.com/turso-sqlite)🇬🇧 est une réécriture de SqLite en Rust, mais pas seulement. +En plus des spécificités de Rust, qui devraient permettre d’éviter les bugs liés à la gestion de la mémoire qui affectent certaines versions de SqlLite, Turso apporte de nouvelles fonctionnalités : le support des connexions via le réseau et les accès concurrents, comme Postgresql. +## Performances de NodeJS + +Les [performances de NodeJs](https://www.repoflow.io/blog/node-js-16-to-25-benchmarks-how-performance-evolved-over-time)🇬🇧 ont été améliorées régulièrement de la version 16 à la version 25. Si vous n’utilisez pas encore la dernière version, la mettre à jour serait un moyen pas trop coûteux de faire un peu d’écoconception. +## Oubliez la dette technique + +Derrière un titre un brin provocateur, Uwe Friedrichsen déroule [une réflexion intéressante sur la dette technique](https://www.ufried.com/blog/forget_technical_debt/)🇬🇧. Il en donne sa propre définition, qui n’est pas celle de Ward Cunningham (l’inventeur du concept) : pour lui c’est tout ce qui augmente la charge cognitive des développeurs. Il essaie d’identifier les causes de cette dette, qui sont d’après lui plus souvent organisationnelles que techniques. Il en mentionne aussi ses conséquences : le développement des fonctionnalités est ralenti, et les problèmes en production sont plus nombreux. +Selon lui, réduire la dette sans s’attaquer à ses causes racines serait insuffisant, car elle s’accumule plus vite qu’on ne peut la réduire. + +À propos de dette technique, je vous suggère de (ré)écouter la conférence d’Arnaud Lemaire "[Dette technique et entropie du logiciel](https://www.youtube.com/watch?v=VKe9EE4MUxk)"🇫🇷. Il commence par expliquer la notion de dette technique telle que Ward Cunningham l’a définie, avant d’en venir à ce que désigne plus communément par ce terme, et qu’il appelle "pourriture logicielle". Ce talk, qui ensuite aborde bien d’autres sujets, reste toujours pertinent et intéressant, malgré son ton provocateur. + +## Images docker durcies (bis) + +Docker n’est pas le seul à proposer des images durcies : le [projet minimal](https://github.com/rtvkiz/minimal) le fait aussi (à une moins grande échelle). Une image durcie est une image Docker dans laquelle tout ce qui n’est pas indispensable a été supprimé, dans le but de réduire la surface d’attaque (autrement dit les failles de sécurité potentielles). +## Devoxx France 2026 + +La plus grosse conférence Française consacrée au développement logiciel sera de retour du 22 au 24 Avril. [La billetterie est ouverte](https://reg.devoxx.fr/#w). Conseil d’ami : n’y allez pas pour la nourriture, vous seriez déçu·e 😉. + +-------- + +Voilà, c’est toute pour cette semaine ! diff --git a/content/pages/index.md b/content/pages/index.md index b3b53c7..662a13b 100644 --- a/content/pages/index.md +++ b/content/pages/index.md @@ -1,9 +1,9 @@ Title: Accueil -Date: 2026-02-02 09:00 +Date: 2026-02-09 09:00 URL: save_as: index.html Category: Home -JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 02 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } +JsonLD: { "@context": "https://schema.org", "@type": "WebPage", "name": "Accueil", "description": "Lettre de veille technologique en développement logiciel", "image": [ "https://www.craftletter.fr/images/craftletter.svg" ], "datePublished": "Mon Feb 09 2026 09:00:00 GMT+0200 (Coordinated Universal Time)", "author": { "@type": "Person", "name": "Pascal Le Merrer", "url": "https://www.linkedin.com/in/pascal-le-merrer/" } } @@ -34,6 +34,7 @@ Pour savoir qui je suis, ou pourquoi j'écris cette lettre, je vous invite à vo # Archives +* [Lettre n°10]({filename}/newsletter/craft-letter-10.md) * [Lettre n°9]({filename}/newsletter/craft-letter-9.md) * [Lettre n°8]({filename}/newsletter/craft-letter-8.md) * [Lettre n°7]({filename}/newsletter/craft-letter-7.md)