- L’expérience de réécrire en un mois le cœur d’un programme utilisé et ajusté directement pendant deux ans a ébranlé mes convictions sur les tests et le contrôle de version
- En 2015, je voyais les tests et les versions comme le cœur d’un logiciel durable, plus que les mauvaises abstractions, mais en passant par Mu puis Freewheeling Apps, ma manière réelle de travailler a progressivement changé
- Je pense que les programmes durables doivent être conçus non pas pour beaucoup de monde, mais dans le cadre de personnes, de contextes et de fonctionnalités bien connus, en acceptant des limites réalistes comme le nombre de Dunbar
- Les types, abstractions, tests, versions, machines à états, l’immutabilité et l’analyse formelle sont utiles en terrain inconnu, mais, à l’excès, ils deviennent une dette technique qui masque une complexité inutile
- Une fois la compréhension du contexte stabilisée, il vaut la peine de jeter de grandes parties et de les refaire, après avoir chargé d’un seul coup dans sa tête les scénarios nécessaires afin de composer l’ensemble en une seule fois
Évolution de ma réflexion sur les tests et le contrôle de version
- Je continue à me confronter au problème de choisir et de construire des programmes sur lesquels on peut compter longtemps, sans pour autant avoir le sentiment d’y être particulièrement bon
- Durant le mois écoulé, j’ai réécrit le cœur d’un programme que j’utilise et modifie progressivement depuis deux ans
- Les jours suivants ont été consacrés à mettre au clair ce que j’avais appris et où aller ensuite
- Ce travail a aussi commencé à faire apparaître des changements plus larges dans ma trajectoire de vie
- En 2015, je me méfiais des abstractions et accordais beaucoup d’importance aux tests et au contrôle de version
- Je considérais que le code regorgeait de mauvaises abstractions, et que les tests ainsi que les versions constituaient les avancées majeures des années 2000
- J’attribuais les causes des problèmes à de mauvaises incitations, à un excès d’abstraction, et à un manque de tests et de versions
- Mu1 était une tentative de concevoir une plateforme en prenant les tests et les layers comme contraintes fondamentales
- En 2017, j’ai commencé à retravailler Mu1 pour en faire le Mu actuel
- Au début, j’utilisais toutes mes nouvelles idées sur les tests et les couches
- Avec le temps, j’ai de moins en moins utilisé ces idées
- Le Mu actuel contient encore beaucoup de tests, mais ce sont surtout des tests classiques, et je n’ai pas réussi à porter l’infrastructure des couches
- En 2022, j’ai commencé à créer Freewheeling Apps
- Au départ, il n’y avait pas de tests, puis j’ai écrit des tests approfondis pour l’éditeur de texte, qui en est un composant central
- J’ai eu du mal à trouver comment tester le reste, mais le projet a suffisamment avancé sans tests
- En 2024, j’ai supprimé tous les tests
- J’ai commencé à refondre en profondeur l’éditeur de texte, et cette approche pouvait faire craindre des conflits de fusion avec les autres Freewheeling Apps
- Au final, j’ai aussi cessé de penser au contrôle de version
- En renonçant aux tests et aux versions tout en obtenant un meilleur programme, il est devenu difficile d’ignorer plus longtemps la dissonance cognitive avec mes anciennes convictions
Ma synthèse actuelle sur les programmes durables
- Faire quelque chose qui dure pour beaucoup de gens me paraît trop difficile, donc il vaut mieux ne pas essayer ainsi dès le départ
- Il faut se laisser gouverner par ce qu’on connaît bien, par les personnes qu’on connaît bien, et par le nombre de Dunbar
- J’ai l’impression que l’essentiel du logiciel existant est contaminé par des incitations à servir beaucoup de monde à court terme
- Je me concentre autant que possible sur des logiciels dont le site web n’affiche pas une profusion de logos
- Je préfère les logiciels faciles à construire, avec peu de dépendances, et sans mises à jour automatiques
- Si l’on applique ce filtre, la quantité de logiciels durables que l’humanité a produits jusqu’ici est très faible
- De petits changements de contexte — les personnes, les lieux, les fonctionnalités à prendre en charge — peuvent transformer fortement l’adéquation d’un programme à ce contexte
- Dans un environnement dominé par le court-termisme, il est difficile de se préparer à cette réalité
- Comme la quantité de travail passé est faible et que le champ d’application propre à chaque programme reste limité, tout nouveau programme risque d’entrer d’une façon ou d’une autre en territoire inconnu
- Même en essayant d’ajouter des « drawing lines » spécifiques à un éditeur de texte, une série de questions apparaît
- Le curseur peut-il se trouver sur le dessin ?
- Peut-on dessiner sur une ligne quand le curseur se trouve sur une autre ligne ?
- Le dessin est plus haut qu’une ligne de texte : peut-il n’être visible que partiellement en haut de l’écran ?
- Peut-on dessiner sur une image seulement partiellement visible ?
- Comme les réponses optimales à ces questions ne se sont pas imposées pendant longtemps, des rustines se sont empilées sur d’autres rustines
- Même en essayant d’ajouter des « drawing lines » spécifiques à un éditeur de texte, une série de questions apparaît
Des outils nécessaires, mais qui deviennent de la dette technique quand on en abuse
- Les types, abstractions, tests, versions, machines à états, immutabilité et analyse formelle sont des outils utilisables en terrain inconnu
- Il suffit de les utiliser selon ses préférences, à la hauteur du besoin
- On a facilement tendance à abuser des outils qui nous attirent
- À mes yeux, la quantité idéale d’usage de ces outils est très faible
- Bien plus faible que ce que suggère l’intuition acquise dans un environnement dominé par le court terme
- Lorsqu’on en fait un usage excessif, ils deviennent de la dette technique
- Il devient difficile de remarquer qu’un programme est inutilement complexe
- Le programme dure moins longtemps qu’il ne pourrait
- Quand le contexte change, il devient plus difficile de faire évoluer le programme
Réécriture et « tout construire d’un seul coup »
- Une fois la compréhension du contexte stabilisée, il y a de la valeur à jeter de grandes parties d’un programme et à repartir de zéro
- Avant de réécrire, il faut faire venir d’un seul coup à l’esprit tout ce que l’on veut du programme et tous les scénarios auxquels il faut répondre
- C’est difficile, mais le but est d’atteindre un état où tout peut être construit en une seule fois
- La forme finale consiste à tout construire d’un seul coup
- Dans cette expérience, les tests et les versions ont au contraire gêné l’arrivée au terme de cette évolution
- Les tests font oublier les problèmes dont il faudrait se soucier
- Le contrôle de version maintient une attache permanente au passé
- Les deux ont eu un effet contre-productif, et il a fallu un grand changement de direction pour s’en défaire
- Je pense que tous les logiciels que j’ai créés jusqu’ici, ainsi que Freewheeling Apps, se situent à la sixième étape de cette trajectoire
- Seul le résultat du mois écoulé est peut-être arrivé à la neuvième étape
- Mais cela reste encore à vérifier
Limites de la complexité et conception orientée données
- Si un programme devient trop complexe, il peut devenir impossible de le charger en entier dans sa tête à l’étape 8
- Cela concerne selon moi la plupart des logiciels produits jusqu’ici, en particulier ceux écrits par plus de deux ou trois personnes
- Même un petit éditeur de texte m’a paru intimidant, au point que j’ai passé une bonne partie du mois à me préparer à affronter cette peur
- Tous les logiciels n’ont pas forcément besoin d’aller jusqu’à l’étape 9
- Beaucoup de Freewheeling Apps sont assez simples et évoluent lentement
- Je pense qu’un logiciel utilisé par peu de personnes peut se stabiliser sans bugs, indépendamment des choix initiaux de conception
- En particulier, je sais désormais comment simplifier un morceau complexe du cœur du système
- Malgré tout, il est utile de savoir comment l’améliorer si le besoin ou la valeur apparaissent
- Parmi les approches qui me semblent clairement utiles pour atteindre l’étape 9, je citerais le data-oriented design
- Ce n’est pas un outil à appliquer aveuglément, mais une manière de considérer d’ensemble la façon dont un programme accède à ses données
- Il faut éviter que des outils comme ECS ne masquent le travail intellectuel essentiel
- Il est possible que cette distinction en étapes ne soit pas tout à fait juste
- Il se peut que je sous-estime des outils avec lesquels j’ai moins d’expérience
- Et ce qu’il y a au-delà de ces étapes reste aussi une question ouverte
- On peut déjà voir les traces de cette évolution de pensée depuis un texte écrit en 2019 sur ma façon de programmer
1 commentaires
Avis de Hacker News
Sans tests, on ne voit pas les échecs de tests ; le problème donne donc seulement l’impression d’avoir disparu
Je n’ai jamais testé quelque chose sans trouver de bug, et la plupart des choses que j’ai testées étaient déjà, à mon avis, prêtes à être publiées
Si l’on supprime les tests, il est très probable qu’au final la seule personne que l’on trompe soit soi-même. À lire l’article, on a l’impression que l’auteur est surtout épuisé par la gestion des variantes/configurations plutôt que par les tests eux-mêmes, et c’est tout à fait compréhensible. Mais il faut des utilisateurs pour gagner de l’argent, et si c’était un problème facile, le marché serait déjà saturé de solutions universelles
Si l’UI ou les workflows changent trop vite, on évite d’écrire des tests parce qu’on sait qu’ils seront inutiles à l’itération suivante ; à l’inverse, s’ils changent trop lentement, on ne retouchera plus vraiment à cette partie, donc il y a aussi peu de risques d’introduire de nouveaux bugs via un refactoring. Les tests et les types ne sont pas un Saint Graal universel, ce sont des outils adaptés à une tâche. Je n’ai jamais vu de base de code où, malgré une bonne couverture de tests, les bugs ne soient pas découverts par des tests manuels ou par l’usage réel. En exagérant un peu : si vous êtes assez bon pour écrire des tests parfaits, autant écrire directement du code parfait. Et si vous ne pouvez pas écrire des tests parfaits, comment savoir que ces tests sont complets, sans bugs et réellement utiles ?
Tous les quelques mois, je trouvais un nouveau bug et j’ajoutais consciencieusement un test, mais quelques mois plus tard, quelqu’un qui l’utilisait dix minutes pour la première fois découvrait encore un nouveau bug. Il y aura sûrement encore des bugs à trouver dans la nouvelle version, mais grâce aux structures de données choisies, une bonne partie des anciens tests me semble structurellement inutile désormais. J’espère qu’au moins pour un usage léger, il suffira de corriger quelques bugs de plus pour que ce soit assez stable. Les tests sont extrêmement précieux quand une grande équipe modifie en permanence une base de code, mais ici il s’agit de construire quelque chose avec un ensemble de fonctionnalités fixe
Elle contient beaucoup de conseils utiles, mais je veux surtout mentionner qu’on peut tester en prenant comme référence une implémentation plus simple, par exemple une implémentation par force brute. Il y a là une sagesse plus profonde. L’utilité d’un test dépend du degré auquel son implémentation est plus simple que celle du code testé. Pour le dire plus fortement, un test n’est utile que lorsqu’il est plus simple que ce qu’il teste. Même si l’on écrit beaucoup de tests, il faut toujours raisonner sur le code, et le simple fait qu’une chose soit un « test » ne la rend pas utile. C’est pour cela, je pense, que beaucoup de programmeurs se méfient du fait de découper les fonctions en morceaux qui ne sont pas des interfaces utiles juste pour faciliter les tests, de tester de simples helpers ou de petites requêtes uniquement pour la couverture, ou d’introduire de l’inversion de dépendances et du mocking seulement pour les tests. Bien sûr, chacun de ces choix peut avoir ses raisons, mais il est important de ne pas perdre de vue l’essentiel
En général, je ne pratique pas vraiment le développement piloté par les tests, qui consiste à écrire d’abord un test qui échoue, même si cela m’arrive parfois. Ces tests ciblent donc le plus souvent du code que je pensais déjà fonctionner. Cela dit, je préfère généralement un harnais de test aux tests unitaires[0]. Je trouve toujours des bugs, mais le flux est moins linéaire. Cela m’amène à tester davantage pendant le développement et à corriger les bugs sur-le-champ
[0] https://littlegreenviper.com/testing-harness-vs-unit/
Par exemple, le noyau Linux n’avait pas beaucoup de tests autrefois, et il semble en avoir davantage aujourd’hui. Unix non plus n’avait probablement pas beaucoup de « tests ». Les compilateurs avaient plutôt des tests, mais les systèmes d’exploitation moins, et il est probable que des jeux comme Doom n’en aient pas eu beaucoup non plus. Au final, il faut trouver un point d’équilibre. On sait que les tests automatisés — unitaires, d’intégration et de bout en bout — aident à produire des logiciels de qualité. En même temps, de bons tests ne sont pas toujours faciles à écrire, de mauvais tests rendent le refactoring plus difficile, et les tests instables consomment beaucoup de temps dans les grands projets. Cela dit, surtout si l’on développe seul, il est intéressant d’essayer différentes approches et de trouver celle qui nous convient
Le passage disant que « renoncer aux tests et aux versions a donné un bien meilleur programme » est difficile à comprendre. Je ne vois pas qui, en 2024, voudrait volontairement programmer sans gestion du code source.
Même pour un projet solo, la possibilité de travailler sur plusieurs machines, de consulter l’historique, de revenir en arrière et d’utiliser des branches apporte une valeur énorme pour un coût quasi nul. Peut-être que j’ai mal compris ce que l’auteur entendait par « versions ».
Il est juste de dire que cette approche ne convient pas à la plupart des programmes que les gens créent aujourd’hui, c’est-à-dire avec de grandes équipes et des exigences qui évoluent en permanence. Mais il utilise toujours la gestion de code source. Comme le dit le texte original, il a simplement cessé de s’inquiéter des conflits de fusion avec d’autres forks. Il y a maintenant plus de 24 forks, avec davantage de détails dans le lien ci-dessus. Il utilise le contrôle de version pour les usages de base comme les sauvegardes, « qu’est-ce que je viens de changer ? », ou l’installation du logiciel sur une nouvelle machine. Simplement, pour ce programme précis, il ne voit plus le contrôle de version comme un moyen de comprendre et de suivre ce qui a changé. Il y a plus de détails ici : https://akkartik.name/post/wart-layers. Par exemple, il fait moins attention à l’hygiène des messages de commit. Le contrôle de version existe, mais dans ce contexte étroit où il veut produire un artefact durable, avec un ensemble de fonctionnalités figé et destiné à durer des décennies, il est passé au second plan comme « bonne pratique de programmation ».
Il ne semble pas non plus travailler sur un grand système ni dans un contexte de travail d’équipe critique. Dans ces conditions, les outils peuvent ne pas apporter une grande valeur. Le flûtiste d’un grand orchestre jouant une symphonie complexe a besoin d’une partition et d’un chef d’orchestre, mais si l’on joue seul avec une boîte à rythmes ou que l’on fait du free jazz, la partition est moins nécessaire et peut même devenir gênante.
Mais quand il y a en permanence 1 000 options faciles, choisir la bonne impose une forte charge cognitive. C’est aussi l’une des raisons pour lesquelles l’industrie sacralise toutes sortes de bonnes pratiques et exerce une pression sociale sur ceux qui ne les suivent pas. Une mauvaise architecture et un code spaghetti atroce rendent le travail très difficile, mais remettre en question des choses qui semblent évidemment justes et explorer un environnement de développement strict, avec moins d’options et d’outils, peut aider à se concentrer davantage sur le problème final. Le contrôle de version aussi pousse, via les branches, à découper un programme en « fonctionnalités indépendantes » ; l’historique conduit à réutiliser aveuglément des unités fonctionnelles qui peuvent être obsolètes ; et la collaboration fige généralement dans l’architecture du code des frontières organisationnelles sans rapport. Cela rejoint aussi ce que disait Mel Conway. Les bénéfices du contrôle de version relèvent du bon sens, mais au niveau « résoudre le problème métier X », il existe de vrais compromis. Le fait que ces compromis soient presque invisibles à l’échelle de l’industrie est révélateur.
Au début, je pensais que l’auteur avait complètement tort, mais il y a tout de même quelques bonnes intuitions.
Ce flux de travail lui convient très bien. La plupart d’entre nous peuvent aussi se rappeler des moments où Git ou les tests automatisés nous ont frustrés ou ont réduit notre productivité. Il existe aussi des solutions plus simples et moins intrusives, comme sauvegarder le code via Dropbox, FTP, etc. Si l’approche ci-dessus fonctionne bien, c’est parce que l’auteur optimise sa propre productivité sur un projet personnel de cœur, en collaboration avec un petit nombre de personnes. Les tests automatisés sont utiles, mais l’auteur semble aimer créer des programmes suffisamment petits pour que leur valeur soit moins évidente. Même dans ce contexte, je pense que les tests automatisés ont une valeur, mais tout le monde peut s’accorder à dire qu’ils ralentissent. Bien sûr, beaucoup diront que cela paie plus tard. Le contrôle de version et les tests automatisés résolvent de vrais problèmes. Aujourd’hui, démarrer un projet sans contrôle de version n’a pas de sens, et il y a une raison pour laquelle les tests automatisés sont une bonne pratique. Cela dit, dans le cas d’usage précis de l’auteur, cela paraît raisonnable. Si l’on met de côté les parties controversées sur le contrôle de version et les tests, les points 7/8/9 capturent parfaitement ma façon de penser quand j’écris et refactore de gros programmes. Écrire, jeter, réécrire.
Les gens font des erreurs, et sur un projet de plus de 100 000 lignes, savoir ce qui a changé au cours des trois dernières semaines est d’une grande aide. C’est utile pour trouver et corriger les problèmes. Mieux encore, les branches permettent d’essayer ce que l’on veut tout en conservant un moyen de revenir à un état stable précédent. Je pense qu’on peut se passer de tests automatisés.
.gitignoreet lancergit init,git add -A,git commit -a -m "before I changed the foo function to use bar", afin de pouvoir revenir à une révision précédente, en vaut largement la peine.Il n’est pas nécessaire de maîtriser Git, mais le simple fait d’avoir des messages de commit et une version à laquelle revenir m’a sauvé un nombre incalculable de fois. Sans parler des fonctionnalités plus avancées.
C’est un texte assez confus. Je me demande vraiment ce qui l’a fait monter jusqu’à la première place.
La principale motivation pour disposer d’un ensemble de tests raisonnable est de réduire la frustration. Un ensemble de tests donne aux développeurs la confiance nécessaire pour faire évoluer le système
S’il est bien conçu, on en vient souvent à penser quelque chose comme : « il était difficile de trouver un moyen de tester le reste, et de toute façon on s’en est plutôt bien sorti ». À mesure que la complexité fonctionnelle augmente, tester un composant ou le système entier peut devenir d’une difficulté ingérable. Mais la philosophie selon laquelle renoncer aux tests et à la gestion de versions aurait produit un meilleur programme ne passe pas à l’échelle au-delà d’une seule personne. Et encore, seulement si cette personne connaît toutes les décisions actuelles et passées contenues dans le code source comme des souvenirs récents et familiers. En plus, si l’on connaît l’implémentation en profondeur, toute validation de changement doit, par définition, être effectuée manuellement
S’il n’était pas dans un état fusionnable à la fin de la journée, cela voulait dire qu’il n’avait pas suffisamment compris le problème pour l’exprimer en une journée, et il réessayait donc à neuf le lendemain matin. Je ne sais pas si quelqu’un s’en souvient, ou si je confonds avec un autre site ou une anecdote différente
La documentation, les tests et la gestion de versions réduisent la quantité de contexte de code que je dois garder en mémoire. Je dois me souvenir des détails du code devant moi, mais si je documente, teste et enregistre avec un bon message de commit le pourquoi et le comment d’un changement, je peux libérer ce code de mon esprit et passer à la tâche suivante
Un bon exemple du point 3, selon lequel « un petit changement de contexte — les personnes, lieux ou fonctionnalités que l’on veut prendre en charge — modifie radicalement l’adéquation d’un programme à ce contexte », est K9 Mail. Il est désormais en train de devenir la version Android de Thunderbird
K9 Mail a commencé avec une UI non traditionnelle qui affichait la liste des comptes e-mail sur l’écran d’accueil, avec le nombre de messages non lus et le nombre total de messages pour chaque compte. Il existait une boîte de réception unifiée, mais elle n’était pas imposée à l’utilisateur. Je me souviens avoir explicitement choisi cette application parce que je voulais garder séparés un compte personnel, un compte professionnel et plusieurs comptes professionnels fournis par des clients. Beaucoup d’utilisateurs de K9 ont probablement choisi cette application pour la même raison. C’est aussi pour cela qu’il y a eu beaucoup de mécontentement quand le développeur est passé à une UI Android plus traditionnelle, où la liste des comptes glisse depuis la gauche et où il faut un tap de plus pour passer d’un compte à l’autre. Si nous avions aimé ce type d’UI, il est probable que nous n’aurions pas choisi K9 au départ. Ainsi, un petit changement — même s’il a sans doute représenté beaucoup de code — a ruiné l’adéquation de l’application aux besoins de ses utilisateurs. Je continue d’utiliser 5.600, la dernière version avec l’ancienne UI, et je la sideloade à chaque nouvel appareil. Plus particulier encore, je n’utilise que POP3 pour accéder aux comptes. Mon flux consiste à prévisualiser sur le téléphone, supprimer ce qui doit l’être, éventuellement répondre en me mettant en Cci, puis finalement télécharger sur l’ordinateur portable ; K9 convenait parfaitement à ce workflow. Je n’ai pas besoin de quelque chose de sophistiqué : une application des années 90 me suffit largement
https://news.ycombinator.com/favorites?id=akkartik&comments=t
Je continue moi aussi de me demander où ce chemin va mener. Une chose est claire : créer du logiciel seul est une activité complètement différente de le créer en équipe
À propos des tests, les tests ne sont pas une fin mais un moyen. Ce que nous recherchons, je pense, c’est la confiance. Quand on a confiance dans l’implémentation, on teste moins. À l’inverse, s’il y a quelque chose qui doit absolument continuer à fonctionner, on ajoute quelques tests d’intégration à la frontière externe, moins affectée par les refactorings et donc moins susceptible de ralentir le rythme. C’est une façon de sonder un backend web depuis l’extérieur plutôt que de tester ses entrailles. Les tests unitaires sont utiles pour concrétiser la conception d’une nouvelle API, mais une fois la direction trouvée, ces tests deviennent presque inutiles
Figer temporairement une condition
ifavec quelque chose commetrue ||pour aller directement à la fonctionnalité en cours prend du temps et devra être retiré plus tard. Il suffit plutôt de créer et d’exécuter un test, que l’on peut conserver comme test de régression. Si l’on déploie une grosse application ou une application lente — parfois le simple fait d’utiliser Qt rend la compilation ou l’exécution longue — un test isolé se charge et s’exécute plus vite. Si reproduire un bug prend 45 secondes, mieux vaut écrire un test. On automatise la partie la plus ennuyeuse du travail, on garde le flow, on peut vérifier l’état du bug aussi souvent qu’on le souhaite sans se demander à chaque fois si cela vaut la peine, et on peut aussi le conserver comme test de régressionJ’aime vraiment beaucoup cet auteur, et Mu est l’un de mes projets préférés. C’est un projet amusant, une sorte de machine Lisp moderne, qui tourne en plus dans QEMU
J’aime la phrase : « la plupart des logiciels sont irrémédiablement infectés par l’incitation à servir beaucoup de monde à court terme ». Elle fonctionne tout aussi bien si l’on remplace logiciel par « business »
Nous sommes tous, dans une certaine mesure, dépassés par la complexité du génie logiciel. Parfois, cette complexité est accidentelle.
Mais je ne suis pas d’accord avec l’idée que la solution serait de rejeter toutes les idées produites au fil des décennies. À l’inverse, il ne faut pas non plus prendre toutes les solutions au pied de la lettre, ni les utiliser « trop ». Être dépassé, par définition, arrive quand on utilise quelque chose à l’excès. Écrivez des tests, utilisez un système de gestion de versions, utilisez des abstractions, mais sachez pourquoi vous les utilisez. Si ce « pourquoi » ne tient plus, il faut réévaluer
C’est l’une des pires incantations, ou presque, du développement logiciel. Pire encore, ces choses sont enseignées presque comme une religion. Ce qui est étrange, c’est que la façon dont les professionnels écrivent du logiciel a beaucoup évolué ces dernières années. Comme je l’ai dit, les abstractions ne sont pas intrinsèquement mauvaises pour tout. Il est même difficile d’imaginer ne pas avoir une classe de base contenant des champs comme
updatedetupdated_bypour des données typiques stockées dans une base SQL. Mais, en général, on utilise très peu d’abstractions, sauf quand elles s’imposent vraiment. Or, dans le monde académique, on enseigne encore exactement le même programme que celui que j’ai appris il y a 25 ans. C’est vraiment étrange de noter des étudiants sur leur capacité à produire de superbes abstractions énormes en UML, puis à les implémenter en code. 90 % d’entre eux ne reverront probablement jamais un seul diagramme UML. Du moins dans le petit domaine où j’évolue. Mais la réalité reste la réalitéJ’aimerais qu’il existe, pour tout, une couche « porcelain » au niveau de la ligne de commande. Avec une sortie standard
--help=uiet une interface de styledialog, on pourrait sans doute automatiser cela. Ce n’est pas tant que je sois dépassé par la complexité ; c’est plutôt qu’il y a une limite à la quantité de mémoire musculaire active qu’on peut mobiliser, et qu’il faut bien faire des coupes quelque part