Si l'intelligence artificielle finit par écrire, comprendre et maintenir nos logiciels, que restera-t-il de notre rapport au code ?
Pendant des décennies, nous avons soigné la lisibilité de nos programmes. Des noms explicites, des structures reconnaissables, des conventions partagées : nous cherchions ainsi à transmettre nos intentions à ceux qui viendraient après nous.
Cet effort a façonné une grande partie de notre culture d'ingénierie logicielle. Clean Code, SOLID, refactoring, architectures en couches : autant de pratiques qui répondent, chacune à leur manière, à une même réalité. Un logiciel n'est jamais terminé. Il doit être compris, corrigé, adapté.
Et si cette réalité ne disparaissait pas, mais que celui qui lit et modifie le code changeait ?
Nous avons appris à écrire pour être lus
La lisibilité n'est pas un luxe esthétique. Quand une règle métier se retrouve enfouie dans des milliers de lignes, le problème n'est pas seulement que le code soit désagréable à parcourir. Il devient coûteux de comprendre ce qu'il fait, pourquoi il le fait et ce qu'une modification risque de provoquer.
C'est pourquoi nous cherchons à faire apparaître les concepts métier, à isoler les responsabilités et à contenir les dépendances. Nous voulons qu'un développeur puisse retrouver une intention sans devoir reconstituer l'ensemble du système.
Ces préoccupations ne sont pas nouvelles. Dès 1972, David Parnas expliquait dans On the Criteria To Be Used in Decomposing Systems into Modules que la qualité d'un découpage dépendait davantage des décisions de conception et de ce que les modules devaient dissimuler que d'une simple répartition des fonctionnalités.
Plus de cinquante ans après, nous rencontrons toujours des problèmes d'encapsulation, de responsabilités mal définies et de dépendances difficiles à maîtriser.
Dans un précédent article, je défendais l'idée que le logiciel constituait un outil de capitalisation des connaissances de l'entreprise. Une règle de tarification inscrite dans le système ne se contente pas de documenter une politique commerciale : elle contribue à déterminer ce qui se passe réellement lorsque cette politique est appliquée.
Cette idée reste importante. Si deux interlocuteurs ne s'accordent plus sur le calcul d'une remise, le comportement du logiciel en production constitue une réalité opérationnelle, qu'il corresponde ou non à l'intention d'origine. Le code exécuté, associé à sa configuration et aux données concernées, incarne les règles effectivement appliquées.
Nous avons longtemps cherché à rendre cette connaissance lisible directement dans le code. Mais cette lisibilité est-elle nécessairement une propriété de l'implémentation elle-même ?
Et si le principal lecteur n'était plus humain ?
Les assistants de développement ne se contentent déjà plus de suggérer quelques lignes. Ils explorent des dépôts, proposent des modifications, produisent des tests et expliquent des comportements existants. Leurs capacités et leur fiabilité restent imparfaites, notamment lorsqu'une modification traverse plusieurs systèmes. Mais imaginons qu'elles continuent de progresser.
Un agent pourrait retrouver une règle métier dispersée dans une procédure stockée interminable, suivre ses dépendances, modifier son comportement et vérifier les conséquences de son intervention. Il pourrait entretenir un programme qu'aucun développeur n'aurait envie de lire.
Dans ces conditions, certaines conventions destinées à faciliter la lecture humaine pourraient perdre de leur importance.
Pourquoi exiger de petites méthodes, un nommage soigneusement choisi ou une organisation familière si une machine peut analyser une implémentation opaque à moindre coût ? Pourquoi refactorer pour rendre un système plus compréhensible si sa compréhension n'est plus le principal obstacle à son évolution ?
Cela ne signifie pas que tous les principes de conception deviendraient inutiles. Un couplage fort, une frontière transactionnelle mal choisie ou une faille de sécurité ne s'évaporent pas parce qu'un agent sait les expliquer. La performance, la fiabilité et la maîtrise des effets de bord demeurent des propriétés du logiciel, et non de son lecteur.
Les agents actuels profitent eux aussi de noms et de structures lisibles. Et en cas d'incident ou d'audit, nous devons toujours pouvoir expliquer le comportement du système.
En revanche, la valeur de certaines pratiques pourrait changer. Ce qui était indispensable à la compréhension humaine pourrait devenir facultatif. Ce qui protège effectivement les comportements du système conserverait sa raison d'être.
Et cette remise en question pourrait aller bien au-delà du Clean Code.
Pourquoi continuer à écrire en C# ?
C#, Java, Go ou Python ne servent évidemment pas qu'à rendre les programmes lisibles. Ils définissent des règles d'exécution, des systèmes de types, des contraintes et des abstractions. Leurs compilateurs et leurs écosystèmes apportent des garanties que nous aurions tort de négliger.
Mais rien n'impose que ces garanties soient exprimées dans des langages conçus aussi pour être écrits et compris par des humains.
Si les machines deviennent les principaux auteurs et lecteurs du code, pourquoi conserver les mêmes syntaxes, les mêmes constructions, voire les mêmes représentations du programme ?
Certains outils laissent déjà entrevoir d'autres voies. Avec Dafny, on peut vérifier des programmes par rapport à des contrats formels. Lean permet de construire et de vérifier des preuves.
De son côté, MLIR manipule des représentations intermédiaires : des formes de programme utilisées par les compilateurs entre le code source et l'exécutable. Elles n'ont pas besoin d'être conçues pour être écrites par des développeurs.
Ces outils ne constituent pas, à eux seuls, une solution à la génération autonome de logiciels métier. Ils montrent néanmoins que les garanties offertes par un programme ne sont pas indissociables de la syntaxe de C# ou de Java. Des recherches publiées en 2025 explorent d'ailleurs des moyens de vérifier que les transformations appliquées à ces représentations préservent certaines propriétés.
On pourrait alors imaginer des agents produisant une représentation structurée, peu lisible pour un humain, que des outils indépendants vérifieraient avant de la transformer en exécutable.
L'idée d'associer des garanties vérifiables à un programme ne date d'ailleurs pas de l'IA générative. Dès 1997, George Necula présentait le Proof-Carrying Code : un programme provenant d'une source non fiable peut être accompagné d'une preuve de certaines propriétés, que son destinataire vérifie plutôt que de faire confiance à son auteur.
La question ne serait plus de savoir si le code est élégant, mais s'il respecte des contraintes vérifiables.
Le code comme résultat, et non comme patrimoine
Imaginons un autre fonctionnement. L'entreprise décrit les comportements attendus, les contraintes à respecter et les propriétés qu'elle veut préserver. Des agents construisent une implémentation, la vérifient, l'optimisent et la remplacent lorsqu'une nouvelle version devient nécessaire.
La synthèse de programmes guidée par la syntaxe, ou SyGuS explorait déjà, en 2013, la recherche automatique d'une implémentation satisfaisant une spécification logique. Plus récemment, AlphaVerus a étudié la production de code vérifié à l'aide de modèles de langage et des retours d'un vérificateur.
En septembre 2026, d'autres chercheurs ont exploré une piste voisine : demander à une IA de produire des preuves que certaines optimisations préservent le comportement d'un programme, puis confier leur vérification à un outil indépendant.
Ces travaux restent limités à des classes de problèmes et des cadres expérimentaux précis : ils n'établissent pas que l'on sache déjà construire ainsi des applications métier entières.
Le code source n'est plus nécessairement le lieu où l'on conserve durablement la connaissance. Il devient une représentation technique produite à partir d'autre chose, éventuellement régénérée plutôt que maintenue.
L'artefact peut changer de forme, de langage ou de structure sans que cela constitue une transformation métier. Ce qui importe est de conserver le comportement voulu, pas l'organisation particulière des fichiers qui l'ont réalisé hier.
Cette ambition n'est d'ailleurs pas nouvelle. Des langages de quatrième génération aux plateformes low-code, en passant par le Model-Driven Development, l'industrie a déjà tenté à plusieurs reprises d'éloigner la production du logiciel de son implémentation technique.
Au début des années 2000, l'Object Management Group proposait ainsi la Model Driven Architecture (MDA) : décrire un système au moyen de modèles indépendants des technologies, puis en dériver des implémentations adaptées aux plateformes cibles.
L'IA générative introduit toutefois une différence importante. Là où les approches précédentes exigeaient généralement des représentations structurées et des transformations prédéfinies, une IA peut désormais travailler à partir de documents, de conversations et d'exemples. Elle peut même contribuer à élaborer le modèle à partir duquel le logiciel sera produit.
Nous pourrions alors consacrer moins de temps aux conventions de code et davantage aux résultats attendus, aux invariants et aux critères de vérification.
La promesse est séduisante : déplacer l'effort de l'implémentation vers la compréhension du problème, et peut-être nous libérer de préoccupations héritées d'une époque où écrire le programme était une activité essentiellement humaine.
Il suffirait, en somme, de demander précisément ce que nous voulons.
Mais précisément, savons-nous le faire ?
Le problème n'a jamais été seulement d'écrire le code
Nous imaginons remplacer le code par des spécifications, comme si les deux étaient des supports interchangeables de la même connaissance.
Les règles syntaxiques et sémantiques des langages de programmation sont plus précisément définies que celles du langage naturel. Cela ne rend pas tous les programmes déterministes ni tous les comportements définis, mais leur exécution ne dépend pas de l'interprétation libre d'une phrase.
C'est comme si nous essayions d'écrire des preuves mathématiques en prose, sans disposer du langage mathématique.
Dès 1978, Edsger Dijkstra rédigeait On the foolishness of "natural language programming", publié l'année suivante. Il contestait l'idée selon laquelle programmer en langage naturel simplifierait nécessairement le travail.
Son argument dépassait la seule difficulté des machines à interpréter notre langue. Les formalismes sont également des instruments de raisonnement pour les humains. L'histoire des mathématiques montre combien ils permettent d'exprimer et de manipuler des concepts avec une rigueur que le langage courant atteint difficilement.
Ce n'est donc pas simplement la machine qui a besoin d'un langage formel. Nous en avons aussi besoin pour penser.
Prenons une règle apparemment simple : « Une commande peut être annulée tant qu'elle n'a pas été préparée. »
De quoi parlons-nous exactement ? D'une préparation qui n'a pas commencé, qui n'est pas terminée, ou dont aucun article n'a encore été traité ? Qu'advient-il d'une commande préparée partiellement ? Et si sa préparation est confiée à un partenaire externe ?
Il ne s'agit pas de chercher artificiellement des cas limites. Ces questions révèlent que la phrase initiale ne définit pas encore un comportement unique.
Deux agents peuvent en proposer des interprétations différentes, produire chacun une implémentation cohérente et écrire des tests qui passent. Ils pourraient même établir, avec les outils appropriés, que leurs programmes respectent rigoureusement les règles qu'ils ont eux-mêmes formalisées.
Les deux solutions seraient pourtant susceptibles de se contredire.
L'ambiguïté n'a pas attendu l'IA : un développeur peut aussi trancher seul. Mais écrire le code imposait parfois une friction salutaire : s'arrêter, préciser « préparation », demander au métier ce qu'il entendait par là.
Un agent peut lui aussi poser ces questions, à condition de repérer l'ambiguïté et d'être encouragé à s'arrêter plutôt qu'à choisir une interprétation plausible. La génération risque de rendre les arbitrages plus rapides, mais aussi moins visibles.
Le développement n'est pas seulement une traduction d'exigences préexistantes vers un langage exécutable. Ces discussions contribuent à faire émerger les exigences elles-mêmes.
Le risque n'est pas que l'IA crée l'ambiguïté, mais qu'elle la transforme en logiciel avant même que nous l'ayons remarquée.
Prouver un programme, mais par rapport à quoi ?
La vérification formelle apporte une réponse puissante à une question précise : un programme satisfait-il les propriétés exprimées dans une spécification donnée ?
Elle ne répond pas automatiquement à une autre : cette spécification représente-t-elle correctement ce que l'entreprise voulait ?
Nous retrouvons ici la distinction classique entre vérification et validation, notamment développée par Barry Boehm dans ses travaux sur l'ingénierie logicielle : construire correctement le produit ne signifie pas nécessairement construire le bon produit.
Une IA peut formaliser une interprétation, en déduire une implémentation et produire les éléments nécessaires à sa vérification. Si l'interprétation initiale est erronée, la rigueur de tout ce qui suit n'y change rien.
C'est même une perspective troublante : nous pourrions disposer de systèmes extrêmement bien vérifiés, construits à partir de malentendus que personne n'aurait pris le temps d'identifier.
Produire plus vite, comprendre mieux ?
En 1986, Frederick Brooks abordait déjà une distinction fondamentale dans No Silver Bullet : celle entre la complexité accidentelle, liée aux moyens techniques utilisés pour construire un logiciel, et la complexité essentielle, inhérente au problème que nous cherchons à résoudre.
Les langages, les frameworks, les compilateurs et les outils de développement peuvent réduire considérablement la première. Ils ne font cependant pas disparaître la seconde.
Depuis cinquante ans, nous avons considérablement amélioré notre capacité à produire des logiciels, sans progresser dans les mêmes proportions dans notre capacité à les concevoir.
Nous n'avons pourtant pas cessé de progresser en modélisation, en tests ou en architecture. Les responsabilités et les frontières dont parlait déjà Parnas restent néanmoins difficiles à choisir : elles dépendent de notre compréhension du domaine.
Nous pourrions bientôt disposer de machines capables de générer en quelques minutes ce que nous mettions des semaines à programmer. Mais si elles produisent des modèles conceptuellement erronés, nous aurons simplement accéléré la production de logiciels mal conçus.
Brooks ne s'arrêtait pas à son diagnostic. Pour lui, décider précisément quoi construire constituait la partie la plus difficile du développement logiciel. Il défendait notamment le prototypage et le développement incrémental, parce que les besoins se découvrent et s'affinent aussi par l'expérimentation.
L'IA pourrait justement accélérer ce processus : proposer plusieurs prototypes, montrer au métier différentes interprétations d'une règle, puis corriger le modèle avec lui.
Encore faut-il que quelqu'un examine les résultats et arbitre entre les comportements possibles. Accélérer l'exploration ne garantit pas que l'on prendra les bonnes décisions.
Le langage que nous pensions pouvoir éviter
Le Domain-Driven Design apporte ici un éclairage particulier avec son Ubiquitous Language, ou langage ubiquitaire : un vocabulaire construit et partagé entre ceux qui connaissent le métier et ceux qui conçoivent le logiciel.
Sur le papier, l'idée est simple. Dans les faits, elle compte parmi les ambitions les plus difficiles à tenir.
Un même mot peut désigner des réalités différentes selon les équipes. Deux expressions distinctes peuvent recouvrir le même concept. Certaines règles paraissent évidentes jusqu'au jour où il faut préciser leurs conditions d'application. Et les modèles doivent évoluer lorsque la compréhension du domaine progresse.
Mais le langage ubiquitaire ne se limite pas à reprendre les mots que le métier utilise déjà. La modélisation fait parfois émerger des concepts qui existent bel et bien dans le domaine, mais qui n'ont pas de nom précis dans le vocabulaire quotidien. Il faut alors introduire de nouveaux termes pour désigner ces concepts, puis les faire adopter par tous.
Pourquoi des experts métier adopteraient-ils un mot nouveau pour désigner une réalité qu'ils connaissent depuis longtemps ? Il ne s'agit pourtant pas de leur imposer un jargon de développeur, mais de nommer des distinctions que l'usage courant laissait implicites.
Un glossaire ne suffit pas à régler cela. Le langage commun se construit par la confrontation des points de vue, l'exploration des cas concrets et les décisions prises ensemble.
Même lorsqu'il fonctionne, ce langage partagé ne garantit pas une spécification formelle. Il aide à stabiliser le sens des concepts, mais ne suffit pas toujours à décrire sans ambiguïté leurs états, leurs transitions et leurs invariants.
Il n'est pas nécessaire pour autant de tout formaliser avant d'expérimenter. Des exemples concrets, discutés avec le métier, peuvent faire apparaître et résoudre certaines ambiguïtés. C'est notamment l'esprit de la spécification par l'exemple décrite par Gojko Adzic. Mais quelques exemples ne suffisent pas toujours à caractériser une règle dans toutes les situations.
Pour produire des logiciels dont la conformité serait vérifiable, il faudrait donc aller plus loin : exprimer certaines règles dans une représentation plus rigoureuse, avec une sémantique suffisamment précise pour être contrôlée.
Des modèles formels, des contrats, des types, des machines à états, peut-être des langages dédiés au domaine…
À force de chercher à nous passer du code, ne serions-nous pas simplement en train de réinventer une autre forme de programmation ?
Une programmation plus proche du métier, peut-être. Plus déclarative, certainement dans certains cas. Mais une activité qui exigerait toujours de choisir des concepts, de définir des règles et d'assumer des décisions que le langage naturel laisse volontiers implicites.
L'IA pourrait accompagner cette formalisation : proposer des définitions, détecter des contradictions, rechercher les cas manquants ou rendre les modèles plus accessibles.
Mais elle ne saurait décider à la place de l'entreprise de ce que ses règles doivent être lorsque plusieurs interprétations sont légitimes.
Sommes-nous prêts à changer de langage ?
Il serait tentant de conclure que l'avenir appartient aux spécifications formelles et qu'il suffirait désormais d'y former les experts métier. Ce serait oublier pourquoi nous éprouvons déjà tant de difficultés à construire un langage partagé.
La difficulté n'est pas simplement technique, et elle n'incombe pas aux seuls métiers. Elle tient à la diversité des connaissances, aux responsabilités, aux désaccords, à l'histoire des organisations et au caractère mouvant des règles que nous essayons de modéliser.
Tout ne nécessite d'ailleurs pas le même degré de formalisation. On ne décrit pas une règle critique de paiement comme on décrit le contenu éditorial d'une page. Et la rigueur d'une spécification n'a de valeur que si nous savons ce qu'il est pertinent d'y garantir.
Comme la MDA avant elle, l'IA pourrait déplacer la capitalisation des connaissances vers des modèles, tout en contribuant à leur construction par le dialogue et les prototypes. Le langage partagé et les décisions validées deviendraient alors un patrimoine essentiel, sans retirer au logiciel exécuté son statut de réalité opérationnelle.
Je ne doute pas que l'IA continuera de transformer notre rapport au code. Je peux imaginer des systèmes dans lesquels les langages actuels disparaissent de la chaîne de production et où les implémentations sont générées, vérifiées et remplacées sans que personne ne les lise directement.
Mais ce scénario déplace une responsabilité considérable vers notre capacité collective à expliciter la connaissance métier. Or nous peinons déjà, bien souvent, à nous accorder sur la signification des mots que nous utilisons chaque jour.
Nous avons passé des décennies à apprendre aux développeurs à parler le langage du métier. Si le code devient demain un simple artefact, sommes-nous prêts, ensemble, à construire un langage suffisamment précis pour que les machines puissent en dériver nos logiciels ?
Références
- David L. Parnas, On the Criteria To Be Used in Decomposing Systems into Modules, Communications of the ACM, 1972 — modularité, encapsulation et critères de décomposition.
- Le logiciel : outil de capitalisation des connaissances de l'entreprise — article précédent sur le code comme incarnation des connaissances métier.
- Dafny — Programming and Verification Language — programmation avec spécifications et vérification statique.
- Lean — langage et assistant de preuve.
- MLIR — Multi-Level Intermediate Representation — infrastructure de représentations intermédiaires extensibles.
- Mathieu Fehr et al., First-Class Verification Dialects for MLIR, PLDI 2025 — vérification de représentations intermédiaires.
- George C. Necula, Proof-Carrying Code, POPL 1997 — programmes accompagnés de preuves vérifiables de certaines propriétés.
- Rajeev Alur et al., Syntax-Guided Synthesis, FMCAD 2013 — synthèse automatique sous contraintes logiques et syntaxiques.
- Pranjal Aggarwal, Bryan Parno et Sean Welleck, AlphaVerus: Bootstrapping Formally Verified Code Generation through Self-Improving Translation and Treefinement, prépublication arXiv, 2024 — génération de code et retours d'un vérificateur formel.
- Chunhao Liao et al., LLVM Translation Validation Automated with Large Language Models and Lean, prépublication arXiv, septembre 2026 — vérification que certaines optimisations d'un programme préservent son comportement.
- Object Management Group, Model Driven Architecture — Executive Overview, MDA introduite en 2001 — génération d'implémentations à partir de modèles indépendants des plateformes.
- Edsger W. Dijkstra, On the foolishness of "natural language programming", EWD 667 (1978), publié dans Program Construction, LNCS 69, Springer, 1979 — intérêt des formalismes et limites de la programmation en langage naturel.
- Barry W. Boehm, Verifying and Validating Software Requirements and Design Specifications, IEEE Software, 1984 — distinction entre vérification et validation.
- Frederick P. Brooks, No Silver Bullet: Essence and Accidents of Software Engineering, conférence de 1986, publiée dans IEEE Computer en 1987 — complexité essentielle, prototypage et développement incrémental.
- Eric Evans, DDD Reference — concepts du Domain-Driven Design, notamment le langage ubiquitaire.
- Gojko Adzic, Specification by Example, Manning, 2011 — clarification collaborative des exigences par des exemples concrets.