Tous les articles

Le langage que vous connaissez compte-t-il encore ?

Écouter l'article (expérimental) · 09:13

00:00 / 09:13

Plusieurs flux de code sombres, de formes différentes, coulent vers l'intérieur et convergent vers un seul nœud ambre stable qui reste allumé pendant que les flux changent autour de lui

Vous avez passé des années à devenir bon dans un langage. Vous avez appris ses règles, puis ses habitudes, puis les petites vérités moches qu'on n'obtient qu'en livrant des choses avec lui et en les regardant casser. Et maintenant un modèle écrit ce langage couramment, et tous les autres aussi, dès l'instant où vous le demandez. Alors la question arrive, sous une forme ou une autre : est-ce que je continue avec ce que je connais, ou est-ce que je passe à ce vers quoi tout le monde se dirige ? La peur en dessous est plus simple que la question. Les années viennent-elles de cesser de compter ?

Le langage, c'est deux choses

Il y a le langage comme frappe au clavier : sa syntaxe, la forme d'une boucle, l'endroit où vont les points-virgules. Et il y a tout ce qu'il y a dessous : comment il gère la mémoire, comment il gère deux choses qui arrivent en même temps, les modes de défaillance qui lui appartiennent et à aucun autre, les idiomes qui sont corrects et ceux qui n'en ont que l'air, l'écosystème et les outils qui ont grandi autour de lui. L'IA a rendu la frappe bon marché. Elle a à peine touché le reste, et il y a une raison. Le reste n'est pas vraiment dans le texte. Il vit dans des systèmes qui tournent et dans la mémoire de ce qui a cassé, et un modèle apprend à partir de texte. C'est pourquoi la moitié profonde n'a pas seulement survécu au changement. C'est la moitié que le changement a rendue rare.

Regardez quels bugs sont devenus faciles

Les erreurs contre lesquelles l'aisance superficielle protégeait sont exactement celles que le modèle évite désormais et que le compilateur a toujours attrapées : un mot-clé faux, un bout de syntaxe mal employé, un appel à quelque chose qui n'existe pas. Ce qui reste, ce sont les erreurs que seule la profondeur attrape : la faille de sécurité qui se lit comme du code ordinaire, la décision de conception qui est mauvaise alors que chaque ligne est bonne, le bug de concurrence qu'on ne peut voir sur aucune ligne prise seule. L'IA a nettoyé les erreurs bon marché et laissé les erreurs coûteuses, et les erreurs bon marché étaient les seules que le savoir superficiel ait jamais attrapées.

La profondeur est une alarme qui se déclenche toute seule

Il y a une sensation que tout développeur expérimenté connaît. Dans le langage que vous connaissez en profondeur, le code faux déclenche une alarme avant que vous sachiez dire pourquoi. Quelque chose dans sa forme cloche, alors vous vous arrêtez et vous regardez. Dans un langage que vous ne connaissez qu'à moitié, cette alarme ne se déclenche jamais. Le code a l'air plausible, alors vous l'acceptez. Un modèle produit du code plausible par construction, page après page. Les tests attrapent une partie de ce qui ne va pas, et vous pouvez pointer un deuxième modèle sur le premier, mais une suite de tests ne vérifie que les défaillances que quelqu'un a pensé à écrire, et des modèles entraînés sur le même code partagent les mêmes angles morts. Au bout du compte, ce qui se tient entre plausible et correct, c'est un relecteur dont l'alarme fonctionne encore. Ce relecteur est quelqu'un qui connaît le langage en profondeur. Il n'y a pas de raccourci vers l'alarme.

Changez pour une raison, pas pour une humeur

Les coûts d'un changement se divisent de la même façon que le langage. Vous pouvez écrire du code à l'air plausible dans un nouveau langage l'après-midi même, et cette partie-là prenait des mois. Les idiomes, le runtime, la façon dont ce langage précis échoue, peu de tout cela se transfère entre des langages étrangers l'un à l'autre. Entre proches parents, des langages qui partagent un modèle d'exécution, il en passe davantage, et c'est le seul vrai raccourci qui existe. Le reste doit encore se gagner. Ce qui se transfère entièrement, c'est la partie qui n'a jamais concerné le langage : comment vous décomposez un problème et raisonnez sur un système.

Alors changez quand il y a une vraie raison, un domaine qui l'exige, un poste que vous voulez, un problème pour lequel le langage a été conçu, et pas parce que le bruit est devenu fort. Certains domaines décident du langage à votre place. Le temps réel et l'embarqué ne peuvent pas se permettre un garbage collector qui fait une pause au mauvais moment, donc les langages système possèdent ce terrain, et le navigateur est le navigateur ; dans les deux cas, le langage tient lieu d'un modèle d'exécution que vous devez garder en tête, et aucune aisance venue d'un modèle ne change ce que fera le matériel. Le machine learning appartient à Python pour une autre raison, l'écosystème, et l'effet est le même.

Prenez le choix précis sur lequel les gens se torturent : rester en C++ ou se mettre à Rust. Posé comme la question de savoir quel langage gagne, il n'a pas de réponse nette et le débat ne finit jamais. Vu à travers la profondeur, il y a moins à débattre. Si vous connaissez bien C++, l'essentiel de ce que Rust vous demande, réfléchir sérieusement à l'ownership et aux lifetimes, est un poids que vous portiez déjà, sauf que maintenant le compilateur le porte avec vous. C'est plus proche d'une montée en niveau que d'un départ à zéro. Et la version adulte de ce choix n'est généralement pas une bascule nette, mais en connaître assez de chacun pour travailler là où chacun a sa place. L'erreur était d'en faire un choix binaire.

Le marché a son mot à dire

Il y a une raison de plus de changer, et c'est la moins romantique : la porte. Le poids de l'étiquette posée sur votre expérience dépend de la façon dont vous gagnez votre vie. Construisez votre propre produit et personne parmi ceux qui l'achètent ne demande en quoi il est écrit. Aidez les autres à construire le leur, conseil, freelance, travail en agence, et vous travaillez dans leur stack, donc la vôtre doit être assez proche pour qu'on vous engage. Et dans l'embauche classique, l'étiquette peut tout décider avant qu'un humain lise votre nom. Le filtre de CV veut des années d'un framework précis, et la profondeur dans un langage voisin ne vous obtient pas l'entretien.

Le marché a aussi ses saisons. La demande pour les langages enfle et rétrécit selon des cycles qui ont peu à voir avec le mérite, et une stack qui a rempli dix ans d'offres d'emploi peut s'éteindre pendant qu'une autre, que vous n'avez jamais touchée, apparaît sur chaque annonce. Ce n'est pas une raison pour courir après chaque saison. C'est une raison pour savoir à quel jeu vous jouez. Si vos revenus passent par les stacks des autres, gardez au moins un langage que le marché veut cette saison, et servez-vous de la machine pour ce qu'elle sait désormais bien faire, vous amener vite au plausible dans une nouvelle stack, pendant que vous faites la part qu'elle ne peut pas faire : construire assez de profondeur pour défendre le code en entretien et une fois embauché. La case cochée ouvre la porte, et la profondeur est ce qui vous garde à l'intérieur.

Où la profondeur paie, et où elle ne paie pas

Rien de tout cela ne rend l'étendue sans valeur. Un deuxième langage, surtout un qui pense autrement que votre premier, aiguise la façon dont vous voyez le premier, et l'IA rend le picorage bon marché, donc vagabonder ne coûte presque plus rien. Ce qui a perdu de la valeur, c'est l'étendue comme pile de syntaxes, cinq langages que vous savez taper et aucun que vous savez défendre.

La profondeur ne paie pas partout non plus. Pour un script jetable, un peu de glu, un prototype que vous supprimerez vendredi, le modèle égalise le terrain et le langage compte à peine. La profondeur gagne sa place dans le code qui vit : le système mûr où la performance ou la sécurité compte vraiment, le code que vous maintiendrez encore dans trois ans.

La partie inconfortable, c'est que les répétitions qui construisaient la profondeur venaient gratuitement avec le métier, et ce n'est plus le cas. Vous écriviez les boucles vous-même, vous tombiez sur les bugs bon marché, vous les corrigiez, et la profondeur s'accumulait comme un effet secondaire. La machine fait cette partie maintenant, donc les répétitions doivent être choisies exprès. Déboguez le code généré au lieu de le régénérer. Lisez le diff comme le ferait un relecteur. Cassez quelque chose délibérément pour voir comment ça échoue. La profondeur vous arrivait ; désormais elle doit être une décision.

C'est un point plus ancien qui refait surface : la production mécanique de code n'a jamais été ce pour quoi on vous payait, et c'est désormais la partie qu'une machine fait. Ce qui reste, c'est le jugement, et le jugement en programmation n'est pas indépendant du langage comme nous aimons le prétendre. Une grande part vit à l'intérieur d'un runtime, apprise lentement, en construisant des choses dedans et en étant là quand elles ont échoué.

Donc les années ont compté. La partie qui a perdu sa valeur n'a jamais été celle qui faisait le compte. La syntaxe que vous avez mémorisée vaut moins aujourd'hui, et elle n'a jamais valu grand-chose. Le modèle du langage que vous avez construit en dessous, assez profond pour savoir quand le code généré vous ment, vaut plus qu'il n'a jamais valu. Apprenez un langage assez bien pour en relire le code.

Les questions auxquelles cet article répond

  • Faut-il rester sur le langage que je connais ou passer à celui vers lequel tout le monde se dirige ?

    Changez quand il y a une vraie raison, un domaine qui l'exige, un poste que vous voulez, un problème pour lequel le langage a été conçu, et pas parce que le bruit est devenu fort. Certains domaines décident à votre place : le temps réel et l'embarqué ne peuvent pas se permettre un garbage collector qui fait une pause au mauvais moment, le navigateur est le navigateur, et le machine learning appartient à Python pour son écosystème. Si vos revenus passent par les stacks des autres, conseil ou embauche classique, gardez au moins un langage que le marché veut cette saison, parce que l'étiquette peut tout décider avant qu'un humain lise votre nom.

  • Pourquoi ne pas faire relire le code d'un modèle par un autre modèle ?

    Parce que des modèles entraînés sur le même code partagent les mêmes angles morts, et qu'une suite de tests ne vérifie que les défaillances que quelqu'un a pensé à écrire. Un modèle produit du code plausible par construction, page après page, et ce qui se tient entre plausible et correct, c'est un relecteur dont l'alarme se déclenche encore quand la forme du code cloche. Ce relecteur est quelqu'un qui connaît le langage en profondeur, et il n'y a pas de raccourci vers l'alarme.

  • Je connais bien C++. Me mettre à Rust, est-ce repartir de zéro ?

    C'est plus proche d'une montée en niveau que d'un départ à zéro. L'essentiel de ce que Rust vous demande, réfléchir sérieusement à l'ownership et aux lifetimes, est un poids qu'un développeur C++ portait déjà, sauf que maintenant le compilateur le porte avec vous. La version adulte de ce choix n'est généralement pas une bascule nette, mais en connaître assez de chacun pour travailler là où chacun a sa place, et l'erreur est d'en faire un choix binaire.

  • Comment construire de la profondeur maintenant que la machine écrit le code de routine ?

    En choisissant les répétitions exprès, parce qu'elles ne viennent plus gratuitement avec le métier. Vous écriviez les boucles vous-même, vous tombiez sur les bugs bon marché, vous les corrigiez, et la profondeur s'accumulait comme un effet secondaire. Déboguez le code généré au lieu de le régénérer, lisez le diff comme le ferait un relecteur, et cassez quelque chose délibérément pour voir comment ça échoue.