Un projet en architecture SOA. Plusieurs services backend en C# avec Entity Framework. L’application fonctionne en développement. En production, c’est une autre histoire. Les temps de réponse explosent. L’interface rame. Les utilisateurs se plaignent. Personne ne comprend.
L’équipe cherche du côté applicatif. Le code est “propre” – les principes SOLID sont respectés, les couches sont bien séparées, les services sont découplés. Sur le papier, tout est correct.
Sauf qu’en ouvrant un profiler réseau, la réalité est là : les requêtes Entity Framework ramènent des tables entières en mémoire. Pas des lignes ciblées – des tables complètes qui transitent sur le réseau, se chargent dans le heap du service, pour qu’ensuite le code filtre côté application ce qui aurait dû être filtré côté base de données. Des SELECT * déguisés derrière du LINQ qui a l’air propre à l’écran mais qui génère des requêtes monstrueuses en coulisses.
Les développeurs connaissaient la syntaxe d’Entity Framework. Ils savaient écrire un DbContext, déclarer des DbSet, appeler .Include() et .Where(). Mais personne dans l’équipe ne comprenait ce que l’ORM faisait réellement avec ces appels. Personne ne savait qu’un .ToList() mal placé force l’évaluation de la requête et ramène tout en mémoire avant de filtrer. Personne n’avait ouvert SQL Server Profiler pour voir les requêtes générées. Le framework s’occupait de tout, n’est-ce pas ?
Sur un autre projet, j’ai vu un serveur physique rendre l’âme pour de bon. Grillé. Et je ne parle même pas des NullReferenceException qui parsèment le quotidien de chaque projet C# parce que personne ne gère les types nullable correctement. Ni des race conditions silencieuses dans du code multi-thread. Ni des crashes aléatoires de CefSharp parce que le cycle de vie du browser embarqué n’est pas compris par ceux qui l’utilisent.
À chaque fois, le même schéma. Et à chaque fois, la même précision importante : ces développeurs n’étaient pas mauvais. Certains avaient dix, quinze ans d’expérience. Ils avaient livré des projets, encadré des juniors, survécu à des mises en production le vendredi soir. Ils connaissaient leur framework sur le bout des doigts.
Mais quinze ans d’expérience dans un écosystème, ce n’est pas quinze ans de compréhension de l’informatique. C’est quinze ans à traduire des besoins fonctionnels en code, à naviguer entre les réunions d’architecture, les arbitrages du product owner et les choix imposés par un management qui ne sait pas toujours ce qu’est un thread. Quinze ans où chaque journée est découpée en sprints, en estimations, en négociations – et où le temps de descendre d’une couche pour comprendre ce qui se passe en dessous n’existe tout simplement pas.
Ce n’est pas de l’incompétence. C’est de l’usure. Le système ne punit pas l’ignorance des fondamentaux – il la récompense, parce que le développeur qui ne pose pas de questions livre plus vite que celui qui veut comprendre avant d’écrire.
C’est à force de vivre ces situations, projet après projet, année après année, que j’ai commencé à voir un problème plus large. Un problème que tout le monde connaît mais que personne ne formule clairement. Ce texte est une tentative de le formuler.
Le catéchisme du développeur moderne
À un moment donné dans la carrière de chaque développeur, quelqu’un lui met un exemplaire de Clean Code entre les mains. C’est un bon livre. Les principes qu’il défend – lisibilité, nommage clair, fonctions courtes, responsabilité unique – sont sensés. Le problème, c’est ce qui se passe ensuite.
Ces principes deviennent des règles absolues. SOLID n’est plus un ensemble d’heuristiques utiles dans certains contextes, c’est un dogme. DRY n’est plus “évite les duplications qui coûtent cher à maintenir”, c’est “si tu as deux lignes de code qui se ressemblent, tu dois absolument les factoriser dans une abstraction”. Clean Architecture n’est plus une réflexion sur la séparation des préoccupations, c’est un template qu’on applique à chaque projet, qu’il ait 500 lignes ou 500 000.
J’ai vu des code reviews où du code fonctionnel, testé et lisible était rejeté parce qu’il “ne respectait pas le Single Responsibility Principle”. Quand tu demandes au reviewer d’expliquer pourquoi ce principe s’applique ici, dans ce contexte précis, la réponse est souvent un silence gêné. Ou pire : “c’est la bonne pratique.”
C’est la bonne pratique. Point. Pas de discussion. Pas de contexte. Pas de nuance.
Ce n’est pas un phénomène nouveau. Dès 1988, Dijkstra posait la question dans “On the Cruelty of Really Teaching Computing Science” : l’informatique est-elle une discipline que l’on enseigne par la compréhension profonde, ou que l’on réduit à un ensemble de recettes applicables ? Quarante ans plus tard, l’industrie a répondu sans ambiguïté en faveur des recettes. On n’enseigne plus les principes comme des outils de réflexion à comprendre et à contextualiser. On les enseigne comme des vérités révélées. On récite le catéchisme sans comprendre la théologie.
La machine à réunions
Le même phénomène s’est produit avec les méthodologies de travail.
Scrum était à l’origine une idée simple : travailler en cycles courts, s’adapter souvent, livrer régulièrement. Vingt ans plus tard, c’est devenu une bureaucratie. Le daily standup – censé durer 15 minutes – est devenu un rapport de surveillance quotidien. Le sprint planning est devenu un exercice de fiction où on estime en story points, une unité de mesure inventée pour éviter de dire la vérité : “on ne sait pas combien de temps ça prendra.”
Les rétrospectives sont devenues des cérémonies où tout le monde dit que ça va, parce que les vrais problèmes sont politiques et qu’un post-it sur un tableau blanc ne changera rien. Le Scrum Master – un rôle qui n’existait pas il y a vingt ans – est souvent quelqu’un qui n’a jamais écrit une ligne de code et qui t’explique comment organiser ton travail de développeur.
Fred Brooks l’avait compris dès 1975 dans The Mythical Man-Month : ajouter des gens et des process à un projet en retard ne le fait pas avancer plus vite. Ça le ralentit. Cinquante ans plus tard, on fait exactement ce qu’il déconseillait, mais avec des certifications Scrum et des dashboards Jira.
Je ne dis pas que la collaboration structurée est inutile. Je dis que quand le process prend plus de temps que le travail, quelque chose a dérapé. Et dans beaucoup d’entreprises, c’est exactement ce qui s’est passé. On passe plus de temps à parler du travail qu’à faire le travail.
Le développeur est devenu un opérateur de process. On ne lui demande pas de réfléchir – on lui demande de suivre la procédure.
Le process formate le travail. Mais il y a un deuxième niveau de formatage, plus profond, qui s’attaque directement aux profils eux-mêmes.
L’endoctrinement par langage
L’industrie du logiciel ne recrute plus des développeurs. Elle recrute des “développeurs React”, des “développeurs Angular”, des “développeurs Java Spring Boot”.
Le framework est devenu l’identité professionnelle. Regarde les offres d’emploi : 15 technologies listées comme prérequis, et pas une seule mention de “comprendre comment fonctionne un système d’exploitation” ou “savoir lire un core dump”. On ne te demande pas de comprendre l’informatique. On te demande de maîtriser un outil.
Ça arrange tout le monde. L’entreprise recrute vite : elle cherche quelqu’un qui connaît sa stack, pas quelqu’un qui comprend les fondements. Le candidat s’y retrouve : il apprend un framework, il coche les cases, il décroche le poste. L’écosystème du framework s’y retrouve : plus d’utilisateurs, plus de conférences, plus de certifications payantes, plus de consultants. Tout le monde gagne.
Et je ne jette la pierre à personne. Le système est conçu comme ça. Les bootcamps formatent des profils opérationnels en quelques mois – c’est leur raison d’être, et pour beaucoup de gens c’est une porte d’entrée précieuse dans le métier. Les formations universitaires sérieuses enseignent encore les systèmes d’exploitation, l’architecture des machines et l’algorithmique. Mais le marché pousse les étudiants à ignorer ces cours au profit de ce qui “se met sur le CV”. Le problème n’est pas dans les salles de classe – il est dans le signal que le marché envoie.
Le résultat est là quand même. Des développeurs qui n’ont jamais alloué un octet de mémoire manuellement et qui ne savent pas ce qu’est un descripteur de fichier. Qui seraient incapables d’expliquer ce que fait fork() ou de lire un core dump. Pas par manque d’intelligence – par manque d’exposition. On ne leur a jamais donné l’occasion de descendre en dessous de la couche d’abstraction dans laquelle ils travaillent.
On ne forme pas des ingénieurs. On forme des opérateurs de frameworks. Des gens capables de brancher des briques ensemble, mais qui n’ont jamais eu à en construire une. Quand ton premier emploi te met devant React et que ton manager te dit “livre cette feature avant vendredi”, tu n’as ni le temps ni l’incitation d’aller lire comment le kernel gère la mémoire. Tu fais ce qu’on te demande. Et cinq ans plus tard, tu es un expert React qui ne sait toujours pas ce qui se passe quand ton navigateur ouvre une connexion TCP. Ce n’est la faute de personne en particulier. C’est le système.
La promesse du langage qui pense pour toi
Il y a une variante plus subtile de cet endoctrinement, et elle ne vient pas des entreprises. Elle vient des langages eux-mêmes.
Chaque nouveau langage arrive avec la même promesse : tu n’as plus besoin de comprendre ce qui se passe en dessous, on s’en occupe. Java et C# ont promis que le garbage collector gérerait la mémoire à ta place. Python a promis que n’importe qui pouvait coder sans se soucier des types, des pointeurs ou de la performance. JavaScript a promis qu’un seul langage suffirait partout – navigateur, serveur, mobile, desktop. Go a promis la concurrence sans prise de tête. Et Rust, plus récemment, a promis la sécurité mémoire par le compilateur : tu ne peux plus faire d’erreur, le borrow checker veille.
Ce sont de vrais langages, avec de vraies qualités. Rust est un outil remarquable – son système de types encode des invariants de propriété mémoire au niveau du compilateur, et c’est une avancée réelle en matière de sécurité logicielle. Python est extraordinairement productif pour le prototypage et la data science. Go est simple et efficace pour les services réseau. Je ne suis pas là pour les dénigrer.
Mais la promesse marketing qui accompagne chacun d’entre eux – “tu n’as plus besoin de savoir” – est un mensonge. Et c’est un mensonge qui se paie cher.
Le développeur Java qui ne comprend pas le garbage collector se retrouve avec des pauses GC de 200 millisecondes en production et n’a aucune idée de pourquoi. Le développeur Python qui n’a jamais pensé à la mémoire découvre que son script de traitement de données consomme 16 Go de RAM pour un fichier de 500 Mo. Et le développeur Rust qui ne comprend pas ce qu’est un lifetime – pas la syntaxe, le concept sous-jacent de propriété et de durée de vie d’une ressource – passe des heures à se battre contre le compilateur sans comprendre ce qu’il essaie de lui dire. Rust ne remplace pas la compréhension de la mémoire. Il l’exige, juste sous une forme différente.
Et puis il y a l’orienté objet. Pendant vingt ans, l’OOP a été enseignée comme le paradigme universel de la programmation. Pas comme un outil parmi d’autres – comme la manière de penser le logiciel. Le résultat : des architectures où chaque problème est résolu par un nouveau niveau d’indirection. Pas parce que le problème l’exige, mais parce que le paradigme le prescrit. Des classes qui n’existent que pour satisfaire un diagramme UML dessiné en amont par quelqu’un qui ne lira jamais le code. Des hiérarchies d’héritage profondes qui rendent le moindre changement imprévisible.
Le paradigme n’est pas le problème. L’orienté objet a des usages légitimes, et la composition d’objets reste un outil puissant pour modéliser certains domaines. Le problème, c’est quand le paradigme devient une religion et que remettre en question l’héritage de classes ou proposer une approche procédurale te fait passer pour un hérétique. Niklaus Wirth – le créateur de Pascal – l’écrivait noir sur blanc dans “A Plea for Lean Software” (IEEE Computer, 1995) : la complexité logicielle croissante n’est pas une fatalité, c’est un choix de conception. On a choisi de ne pas l’écouter.
Chaque couche d’abstraction qui te “protège” est aussi une couche qui t’aveugle. Tant que tout fonctionne, tu ne le vois pas. Mais le jour où ça casse en dessous de ta couche – et ça finit toujours par casser – tu es seul face à un système que tu n’as jamais pris le temps de comprendre.
Pourquoi ça marche (pour l’instant)
Je vais être honnête, et c’est important de l’être : ce système fonctionne.
Les entreprises recrutent vite, forment vite, livrent vite. Un junior qui connaît React est productif en quelques semaines. Le code n’est pas toujours propre, la dette technique s’accumule, mais le produit sort. Et dans un marché où la vélocité prime sur la qualité, c’est suffisant. C’est même rationnel.
Et il faut le dire clairement : les frameworks qui rendent ça possible ne sont pas le problème. C’est grâce à Entity Framework qu’une équipe de cinq personnes peut livrer un back-office fonctionnel en trois mois. C’est grâce à React qu’un seul front-end developer peut construire une interface utilisée par des milliers de personnes. Ces outils ont démocratisé la production logicielle, et c’est une bonne chose.
Le problème, c’est ce qui se passe après la démo. Le POC qui impressionne le comité de direction en deux semaines devient le produit. La maquette devient la production. Personne ne revient en arrière pour comprendre ce qui se passe sous le capot, parce que la roadmap est déjà remplie pour les dix-huit prochains mois. Le code de la démo, écrit en urgence pour convaincre, devient le socle sur lequel on empile des features pendant trois ans. Le problème n’est jamais l’outil. C’est de confondre la facilité d’utilisation avec la compréhension de ce qu’on utilise.
Ce modèle fonctionne parce qu’il repose sur un postulat : la main-d’œuvre développeur est le goulot d’étranglement. Il faut beaucoup de gens pour produire beaucoup de code. Donc on standardise les profils, on standardise les outils, on standardise les process. On transforme le développement logiciel en ligne de production. Et comme toute ligne de production, elle a besoin d’opérateurs interchangeables, pas d’artisans irremplaçables.
Il faut reconnaître que ce modèle a produit des résultats. Des millions d’applications fonctionnent, des milliards d’utilisateurs sont servis, des industries entières ont été transformées par le logiciel. Dire que le système est cassé serait malhonnête. Il fonctionne – dans les limites du postulat sur lequel il repose.
Mais ce postulat est en train de changer.
L’IA change les règles
L’arrivée des modèles de langage dans le développement logiciel n’est pas une amélioration incrémentale. C’est un changement de nature.
Un développeur avec un copilote IA écrit du code à une vitesse qu’aucun sprint planning n’avait prévue. Pas du code parfait – du code fonctionnel, livrable, testable. Le genre de code que l’industrie considère comme “suffisant” depuis des années. Sauf qu’au lieu de prendre trois jours, il prend trois heures.
Ce qui va se passer n’est pas difficile à deviner. Les premières études (GitHub, Microsoft) mesurent des gains de productivité de 30 à 55% sur certaines tâches de développement. Et ce n’est que le début. La tendance est claire : là où il fallait trois développeurs, il en faudra bientôt un seul, mieux outillé, peut-être mieux payé, mais un seul.
Le développeur dont toute la valeur repose sur sa connaissance d’un framework va se retrouver face à un problème simple : la machine connaît le même framework, mieux que lui, et elle ne dort pas. Elle ne prend pas de pauses café. Elle n’a pas besoin de daily standup.
Le code généré par l’IA va exploser en volume. Et tout ce code, il faudra le lire, le comprendre, le corriger, le maintenir. Pas avec un copilote – avec une vraie compréhension de ce que fait le programme. Quand l’IA génère un appel à mmap et que ça plante en production, il faudra quelqu’un qui sait ce que mmap fait. Pas quelqu’un qui sait prompter l’IA pour qu’elle corrige son propre code.
La question qui va se poser à chaque développeur dans les cinq prochaines années est brutale : qu’est-ce qui te rend irremplaçable quand la machine sait écrire du CRUD mieux que toi ?
Ce qu’on ne dit pas sur la cadence
Il y a un sujet dont l’industrie ne parle pas assez : le coût humain de tout ça.
La productivité augmente, mais la charge de travail aussi. Les entreprises ne vont pas réduire les objectifs parce que l’IA accélère la production. Elles vont augmenter les attentes. “Tu livres plus vite maintenant ? Parfait. Livre plus.” C’est mécanique. C’est déjà en train d’arriver.
Le burnout des développeurs n’est pas un accident. C’est le fonctionnement normal du système. L’industrie consomme des gens. Trois à cinq ans sur un poste, épuisement, turnover, on recommence avec quelqu’un de frais. Les sprints qui n’en finissent jamais, les deadlines qui ne reculent jamais, la dette technique qu’on n’a jamais le temps de rembourser, les on-call rotations qui massacrent le sommeil.
Et ce n’est pas limité aux startups qui font n’importe quoi. C’est partout. Dans les grandes entreprises, dans les ESN, dans les cabinets de conseil. Le rythme est devenu la norme, et celui qui dit “c’est trop” passe pour quelqu’un qui n’est pas assez engagé.
L’IA va amplifier cette pression. Pas parce que la technologie est mauvaise – elle est remarquable. Mais parce que les organisations vont l’utiliser pour extraire plus de travail, pas pour donner plus de temps. C’est ce qu’elles ont toujours fait avec chaque gain de productivité.
Le développeur qui n’a pas de socle solide – qui n’a que ses compétences framework et sa capacité à suivre un process – va se retrouver coincé entre deux étaux. Trop lent pour rivaliser avec l’IA sur la production de code routine. Trop superficiel pour résoudre les problèmes que l’IA ne sait pas encore résoudre. Et trop épuisé pour prendre du recul et investir dans autre chose.
Comprendre les fondamentaux, c’est aussi reprendre le contrôle sur son propre métier. Savoir ce que tu fais et pourquoi tu le fais, c’est un antidote au sentiment d’impuissance qui pousse à l’épuisement. On ne s’épuise pas seulement parce qu’on travaille trop. On s’épuise parce qu’on a l’impression de courir sans jamais avancer, de produire sans jamais comprendre, d’être remplaçable sans savoir comment devenir indispensable.
Ce qui ne change pas
Pendant que les frameworks se succèdent et que les LLM progressent de mois en mois, il y a des choses qui ne bougent pas.
Quand je parle de fondamentaux, je parle de quelque chose de précis : les concepts et les mécanismes qui restent vrais indépendamment du langage, du framework ou de l’époque. La manière dont un système d’exploitation gère la mémoire. Les protocoles par lesquels deux machines communiquent sur un réseau. La façon dont un processeur exécute des instructions. La logique binaire sur laquelle tout le reste est construit. Ce sont des connaissances qui étaient vraies il y a trente ans et qui le seront encore dans trente ans, parce qu’elles décrivent le fonctionnement de la machine elle-même, pas les outils qu’on pose dessus.
L’interface de malloc n’a pas changé depuis sa standardisation en C89, il y a plus de trente-cinq ans. Les implémentations sous le capot ont évolué considérablement – ptmalloc2, jemalloc, tcmalloc, mimalloc ont chacune optimisé la gestion du heap de manières très différentes. Mais le contrat fondamental reste le même : tu demandes de la mémoire, le système te la donne, et c’est à toi de la rendre. Le protocole TCP n’a pas été remplacé par un framework JavaScript. Le kernel Linux exécute des appels système selon les mêmes principes depuis trente ans. La mémoire est toujours découpée en pages. Les processus communiquent toujours par pipes, sockets et signaux.
Chaque framework, chaque langage, chaque outil finit par faire des appels système au kernel. Et le kernel, lui, n’a pas changé de paradigme tous les trois ans.
Le développeur qui comprend ces invariants possède quelque chose que ni les cycles technologiques ni l’intelligence artificielle ne peuvent lui retirer : la capacité de raisonner sur un système depuis ses fondations. Quand tout change autour de lui, il reste debout. Pas parce qu’il est plus malin que les autres, mais parce qu’il a investi dans ce qui dure.
Ce que je propose
Je ne vais pas te dire de quitter ton CDI ou d’arrêter le React. Ce serait irresponsable. Ton framework te nourrit. Ton CDI paie ton loyer. La réalité économique existe, et je la respecte.
Ce que je propose, c’est d’investir une partie de ton temps – même modeste, même une heure par semaine – dans des connaissances qui ne périment pas.
Comprendre ce que fait ton programme quand il tourne, pas seulement ce qu’il fait quand tu le codes. Savoir ce qui se passe entre le moment où tu cliques sur “Run” et le moment où un résultat apparaît à l’écran. Lire un chapitre sur la gestion mémoire au lieu d’apprendre une énième API. Écrire un petit programme en C pour sentir ce que ça fait de gérer chaque octet soi-même.
Ce n’est pas un investissement qui paie demain matin. Tu ne vas pas coder plus vite lundi parce que tu as compris les pages mémoire ce weekend. Mais dans cinq ans, dans dix ans, quand le paysage aura changé encore trois fois, tu seras toujours debout. Pas parce que tu auras couru après chaque nouvelle tendance, mais parce que tu auras compris ce qui ne bouge pas.
Je sais ce qu’on peut objecter : si le système est aussi puissant que je le décris, une heure par semaine ne suffit pas à s’en libérer. C’est vrai. Une heure par semaine ne transformera pas un opérateur de frameworks en expert système en six mois. Mais elle ouvrira une brèche. Elle changera la manière dont tu lis un message d’erreur, dont tu abordes un bug incompréhensible, dont tu évalues une solution proposée par un collègue ou par une IA. Le système ne changera pas parce que tu lis un chapitre sur la mémoire virtuelle. Mais toi, si.
Et il y a une raison plus profonde que la survie professionnelle. Comprendre comment fonctionne une machine – vraiment comprendre, depuis les transistors jusqu’aux appels système – procure quelque chose que le nième tutoriel React ne donnera jamais : le sentiment de maîtriser son propre métier. De ne pas être un passager dans un véhicule que quelqu’un d’autre a construit et que personne ne sait réparer. La compréhension n’est pas qu’un avantage concurrentiel. C’est une forme de liberté.
Ce que ce site va publier
Des articles sur le C, Linux, la mémoire, les appels système, l’architecture des machines. Du code open source testé, benchmarké, lisible.
Le tout en français, parce que ce contenu manque cruellement dans notre langue.
Ce site ne publiera jamais de tutoriel “apprendre X en 30 jours”, de comparatif de frameworks, de liste d’outils à la mode, de contenu sponsorisé déguisé en article, ni de conseil de carrière générique.
Chaque texte publié ici part du même principe : le lecteur est un adulte qui réfléchit. Il mérite qu’on lui parle sérieusement, qu’on lui montre le code, et qu’on lui explique le pourquoi autant que le comment.
Si ça te parle, tu es au bon endroit. Commence par explorer les projets open source pour voir la thèse en action, ou parcours le blog pour les articles techniques.
Ce que l’industrie appelle “progrès”, c’est souvent une couche de plus entre toi et la machine. Ce que j’appelle progrès, c’est une couche de moins.
Lis. Comprends. Maîtrise. Recommence.