10 points par GN⁺ 4 시간 전 | 1 commentaires | Partager sur WhatsApp
  • La conception logicielle s’apprend plus profondément dans de vrais projets, quand on porte une responsabilité et que les problèmes deviennent les siens, que dans des cours magistraux
  • La loi de Conway est l’idée que le logiciel reproduit la structure sociale de l’organisation, et que la différence entre code scientifique et code industriel peut aussi venir des systèmes d’incitation
  • rust-analyzer permet aux contributeurs à fort rendement de se concentrer plus facilement grâce à des builds rapides, la prise en charge de stable, l’absence de dépendances C et des tests qui s’exécutent en quelques secondes
  • rust-analyzer protège les fonctionnalités indépendantes avec catch_unwind et a abaissé les critères pour les PR, tout en appliquant des exigences de qualité bien plus strictes à la colonne vertébrale centrale
  • Une structure expérimentale peut devenir une réalité de long terme, et rust-analyzer est lui aussi passé d’un prototype d’architecture LSP à l’entretien d’un compilateur supplémentaire

La conception logicielle s’apprend surtout sur le terrain

  • La conception logicielle s’apprend mieux en prenant des responsabilités dans un vrai projet et en résolvant directement les problèmes qu’au travers d’un enseignement formel
  • Plus que lorsque l’auteur avait le rôle d’« architecte » dans des cours universitaires de conception et des projets de cursus, c’est dans son deuxième vrai projet, IntelliJ Rust, que l’apprentissage a vraiment commencé, lorsque les problèmes de conception sont devenus son affaire
  • Il y a eu quelques erreurs dans IntelliJ Rust, mais rien de fatal, et cela a permis d’apprendre énormément au passage
  • Le génie logiciel a aussi un côté suffisamment simple pour qu’une personne curieuse puisse l’apprendre en réfléchissant aux principes et en lisant divers textes

Structures d’incitation et loi de Conway

  • La loi de Conway est l’idée que le logiciel reproduit la structure sociale de l’organisation qui le crée
  • La différence entre logiciel industriel et code scientifique peut provenir moins de la connaissance nécessaire pour construire du logiciel que des structures d’incitation qui poussent les gens à en produire
  • Une situation comme « un doctorant qui doit publier un article en trois mois » peut être un facteur majeur dans la forme que prend le code scientifique
  • Il existe globalement deux manières de réagir à une structure d’incitation
  • Concevoir ou faire évoluer les incitations d’un projet

    • Il est rare d’avoir l’occasion de concevoir ou d’ajuster la structure d’incitation d’un projet, mais lorsque cela arrive, l’impact peut être considérable
    • L’essentiel de TIGER_STYLE ne réside pas dans la liste de règles elle-même, mais dans le contexte social qui fait de ces règles de bons choix
  • S’adapter aux contraintes si on ne peut pas les changer

    • Les structures d’incitation sont rarement données comme on le souhaiterait, et si elles ne peuvent pas être modifiées, il faut s’y adapter
    • Même dans les projets logiciels industriels, on a rarement « le temps de bien faire », et il faut faire du mieux possible dans les contraintes imposées

Comment rust-analyzer a aligné sa structure sur ses participants

  • rust-analyzer est un projet qui a à la fois de la profondeur et de l’ampleur
  • Sur le plan de la profondeur, sa nature de compilateur lui permet d’attirer des contributeurs excellents et très investis
  • Sur le plan de l’ampleur, un IDE classique comporte de nombreuses fonctionnalités spécialisées, ce qui convient bien à des personnes qui apprennent Rust ou à des contributeurs occasionnels du week-end souhaitant passer une heure ou deux à corriger une gêne qui les touche
  • Si rust-analyzer a tenu à ne pas exiger une build de rustc, à se compiler sur stable, à ne pas avoir de dépendances C et à faire tourner toute la suite de tests en quelques secondes, c’était pour attirer des contributeurs à fort rendement
  • L’idée était de peaufiner le système de build pour que les gens puissent se concentrer sur le borrow checker sans se soucier du reste
  • Pour attirer des contributeurs du week-end, l’intérieur de rust-analyzer a été découpé en plusieurs fonctionnalités indépendantes, chacune protégée à l’exécution par catch_unwind
  • Le seuil d’acceptation des PR de fonctionnalité a été abaissé à « le happy path fonctionne et il y a des tests », en considérant acceptable que ce code plante
  • Mais deux conditions étaient nécessaires
    • Les problèmes de qualité devaient rester isolés à une fonctionnalité individuelle et ne pas se propager ailleurs
    • Les plantages à l’exécution ne devaient pas être visibles par l’utilisateur ; pour cela, les fonctionnalités de rust-analyzer devaient fonctionner sur des snapshots immuables et ne pas pouvoir corrompre les données
  • À l’inverse, des critères de qualité beaucoup plus stricts étaient appliqués à la colonne vertébrale centrale qui soutient les fonctionnalités

Le risque qu’une structure expérimentale devienne une réalité durable

  • Quand on s’adapte à une structure d’incitation au lieu de la corriger, il faut garder à l’esprit que l’avenir est incertain et qu’il peut, en général, se concrétiser de la manière la plus inconfortable possible
  • La motivation initiale de rust-analyzer était d’éviter d’écrire un compilateur parallèle de plus au sein d’IntelliJ Rust, et de valider au moyen d’un prototype une meilleure architecture pour le LSP afin de réinjecter ensuite ces apprentissages dans rustc
  • C’est pourquoi le code, y compris son noyau, était très expérimental
  • Au final, cela a conduit à maintenir un compilateur supplémentaire
  • De manière similaire, le projet uutils a commencé comme une destination principale pour les personnes apprenant Rust, avant de devenir l’implémentation de coreutils dans Ubuntu

Ressources et livres à consulter

  • Il n’existe pas de livre unique contenant la bonne réponse, et la pratique semble être un élément indispensable
  • Boundaries by Gary Bernhardt
    • Une ressource aux conseils concrets solides, qui a déclenché une exploration à un niveau plus élevé
  • How to Test
    • L’importance des tests a été comprise immédiatement, mais il a fallu longtemps pour admettre qu’une grande partie des conseils sur les tests largement cités n’étaient pas très pratiques, puis conceptualiser ce qui fonctionne réellement
  • Le guide ∅MQ et les écrits de Pieter Hintjens
    • Ce sont les ressources qui ont fait découvrir une manière de penser à la Conway’s Law
    • L’architecture de développement des fonctionnalités de rust-analyzer est une application de l’optimistic merging
  • Reflections on a decade of coding by Jamii
    • Le texte traite de sujets très méta et est suffisamment excellent pour être placé en première position dans cette liste de liens
  • Le blog de Ted Kaminski
    • Sous la forme de notes pour un livre qui n’existe pas, c’est ce qui se rapproche le plus d’une théorie cohérente du développement logiciel
  • Software Engineering at Google et The Philosophy of Software Design d’Ousterhout

1 commentaires

 
GN⁺ 4 시간 전
Commentaires Hacker News
  • En résumé façon aide-mémoire, une bonne conception doit reposer sur une idée unique qui imprègne l’ensemble et aller dans le sens de la surprise minimale
    Si le système le permet, les gens finiront par l’utiliser ainsi, et une solution qui commence par « si seulement tout le monde faisait simplement X » n’est pas une solution
    Il faut séparer la partie qui transforme les données de celle qui les utilise, les modèles de données vivent plus longtemps que le code, et le couplage est à la racine de nombreux problèmes
    La gestion de versions est inévitable, l’état doit être rendu explicite, et chaque information doit avoir une source unique de vérité
    Il faut passer plus de temps à nommer les choses, si c’est difficile à tester c’est que la conception est mauvaise, et les décisions non documentées finissent par se regretter
    La communication a un coût, donc il faut la justifier avant de le payer, et le travail de l’ingénieur consiste à résoudre des problèmes avec des heuristiques dans un contexte d’information incomplète

    • La plupart de ces points ne semblent en fait pas avoir grand-chose à voir avec la software architecture en tant que telle, à part peut-être l’idée d’« isoler certaines parties du système »
      Le texte lui-même n’était pas très cohérent du point de vue de l’architecture logicielle
      La vue architecturale 4+1 reste, même sans UML, un bon cadre conceptuel pour penser la vue d’ensemble, et la série Pattern-Oriented Software Architecture organise bien les différentes architectures auxquelles les gens aboutissent
      Grady Booch travaillait aussi à un handbook de software architecture, mais cela semble aujourd’hui presque à l’arrêt, et à l’époque la mailing list documentait les grandes architectures de systèmes d’entreprises ou de gros projets open source
      En creusant ce type de ressources, on voit que les architectures sont construites selon des priorités différentes — échelle, sécurité, performance, interopérabilité, fail-safe — et que chaque objectif implique des compromis réalistes
    • Je ne suis pas d’accord avec tout, mais j’ajouterais quelques points : l’objectif principal d’un logiciel est de résoudre le problème immédiat, et l’objectif secondaire est de résoudre avec un effort minimal les problèmes futurs les plus probables
      Si c’est meilleur selon ce critère, alors même ce qui ressemble à une mauvaise conception peut en réalité être une bonne conception
      Les interfaces doivent être faciles à utiliser correctement et difficiles à utiliser de travers, et il faut réfléchir à la manière dont quelqu’un qui ne connaît pas le projet va s’en servir
      Le bon code doit être facile à écrire, le code suspect doit se remarquer, et les bugs doivent être déplacés le plus possible vers la gauche
      Il vaut mieux éliminer une classe de bugs que corriger un seul bug, et comme une interface est plus difficile à changer qu’une implémentation, une implémentation laide est acceptable si l’interface est la bonne
      Les commentaires et la documentation doivent expliquer pourquoi le code a cette forme, et même s’il semble exister une méthode plus simple, si certaines contraintes l’empêchent il faut le noter
      Du point de vue des données, il ne faut pas se répéter : si le même fait est stocké à plusieurs endroits, cela finira par diverger et produire des bugs
      Sortir du chemin balisé a un coût ; cela peut en valoir la peine, mais il ne faut pas sous-estimer ce coût
      Une technologie ennuyeuse qui semble moins bonne est souvent une meilleure technologie, et il faut évaluer la valeur attendue non pas avec « est-ce que ça vaut le coup ? », mais avec « est-ce que ça vaut le coup par rapport aux autres choses qu’on pourrait faire ? »
      Même si l’on se croit plus intelligent que les autres, certains problèmes ne se résolvent pas par la seule intelligence ; certains ne peuvent être découverts qu’une fois qu’ils explosent réellement, donc il faut apprendre des erreurs des autres
      Les frictions sont des tueurs silencieux
    • Les migrations de données sont inévitables, donc il faut les planifier à l’avance, et c’est une conséquence logique de la gestion de versions
      Planifier est bien, mais parfois il faut aussi essayer directement, et tout coûte de l’argent
      Concevoir sans tenir compte des coûts force plus tard à faire des choix difficiles
    • Après plus d’un an à créer un jeu vidéo, je construis un moteur durable avec un pipeline de données séparé, une couche de rendu/gestion des ressources totalement découplée, et une méthode explicite de transition d’état, et presque toute cette liste s’applique telle quelle
      Même pour un projet solo, les contraintes du moteur servent de guide du type « ajoute cette nouvelle fonctionnalité bizarre découverte pendant les tests de cette façon »
      Plus besoin de trimballer à chaque fois une énorme documentation du genre « pour créer un nouvel effet sonore exécuté plusieurs fois dans une transition d’état donnée, fais comme ceci »
    • Je travaille dans ce domaine, et chez nous c’est moins abstrait que dans d’autres secteurs parce qu’on modélise l’industrie de la santé
      Le concepteur système doit comprendre le secteur ; il n’a pas besoin d’adopter entièrement sa terminologie ni ses habitudes de modélisation, mais il doit comprendre pourquoi et selon quel point de vue les jeux de données sont regardés
      Nous avons parfois simplifié volontairement la complexité du marché de la santé pour supprimer des surdéfinitions inutiles et proposer un modèle plus intégré, mais nous n’avons pu faire ces changements avec assurance que parce que nous comprenions suffisamment le domaine du problème
      En particulier, les noms ne meurent presque jamais
      Il arrive parfois qu’ils meurent, mais changer un nom demande un effort extrême ; il vaut donc vraiment la peine de consacrer beaucoup de temps à faire relire les propositions de nommage par des experts métier afin de vérifier qu’il ne manque rien
      On peut parfois imposer certaines notions, mais les fonctions business comme les ventes ou le marketing continueront de réclamer la terminologie du secteur et pousseront à aligner le modèle sur la vision actuelle de l’industrie
      Si l’on décide de rompre avec ce courant, cette rupture doit être intentionnelle et avoir un objectif clair
      En logiciel, la propriété à mettre le plus en avant est la maintenabilité
      Le coût de construction compte, bien sûr, mais le coût d’exploitation a un impact bien plus grand, car il inclut non seulement l’infrastructure, mais aussi l’accumulation des demandes de fonctionnalités, le refactoring du code et le maintien des versions de logiciels tiers
  • Les listes de recommandations sont souvent bonnes, comme A Philosophy of Software Design d’Ousterhout, mais dans l’ensemble on est plus proche de la théorie générale du développement logiciel que de la software architecture elle-même
    Pour l’architecture, je recommanderais des classiques comme Software Architecture: Perspectives on an Emerging Discipline de Shaw/Garlan, ainsi que les écrits de Mary Shaw
    Des articles plus récents qui explorent pourquoi le domaine de la software architecture n’a pas évolué comme prévu sont aussi intéressants, par exemple Myths and Mythconceptions: What Does It Mean to Be a Programming Language, Anyhow? ou Revisiting Abstractions for Software Architecture and Tools to Support Them
    D’un point de vue pratique, il est utile de regarder pourquoi les Unix pipes and filters et REST ont réussi, et où et pourquoi ils échouent ; l’architecture hexagonale est aussi essentielle
    Personnellement, j’aime aussi Beyond Procedure Calls as Component Glue: Connectors Deserve Metaclass Status, qui relie software architecture et protocoles méta-objets pour les envisager comme une nouvelle base pour les langages et la programmation
    C’est une réponse au texte de Mary Shaw Procedure Calls Are the Assembly Language of Software Interconnection: Connectors Deserve First-Class Status, qui pose la question suivante : si les appels de procédure sont de l’assembleur, à quoi ressemblerait alors un langage de haut niveau ?
    Peut-être que la software architecture a encore un avenir plus lumineux et plus pratique

    • C’est quoi, l’architecture hexagonale ?
    • La question « si les appels de procédure sont de l’assembleur, à quoi ressemblerait un langage de haut niveau ? » me fait penser, même si je ne suis pas très versé en théorie des langages de programmation ni en outils de génie logiciel, que c’est un peu l’idée de base du lambda-calcul, de LISP, d’APL, de Clojure, de TCL, etc.
      Il suffit de quelques structures de données et types, avec un petit ensemble de fonctions de base, puis on les compose
      Une chose que j’aime dans Lisp, c’est que les types plus complexes, en particulier ceux qui viennent d’une FFI, restent toujours opaques
      J’aimerais voir une implémentation CLOS où définir une structure dans un langage proche du C donne automatiquement un ensemble standard de fonctions
  • La meilleure manière d’apprendre l’architecture n’est pas de construire un projet assez grand, mais d’en faire la maintenance
    Et il faut le faire sur au moins deux ou trois projets
    Si le projet est trop petit, n’importe quelle architecture fonctionne, et pour juger si un projet est « grand », il vaut mieux regarder le nombre de personnes qui ont travaillé dessus, ou mieux encore le nombre d’équipes, que le nombre de lignes de code
    Il faut au moins deux projets différents pour pouvoir comparer, et j’ai vu des gens rester enfermés des décennies sur un seul projet sans connaître les approches modernes de résolution de problèmes
    Mais en pratique, c’est souvent la personne qui a créé le projet qui est promue architecte, rarement celle qui en a assuré la maintenance
    Chez Google c’est encore plus visible : il faut surtout lancer de nouveaux produits pour être promu, la maintenance n’est pas valorisée, et il est préférable de partir juste après un lancement si possible
    Paradoxalement, la personne la mieux placée pour devenir architecte est peut-être le prestataire externe qu’on affecte à la maintenance des vieux projets internes dont personne ne veut
    Ces gens doivent préserver l’architecture et passent d’un projet à l’autre, donc ils peuvent comparer
    En revanche, s’ils facturent à l’heure, il existe aussi un risque qu’ils complexifient excessivement l’architecture pour pouvoir facturer davantage de temps

  • Dans ce contexte, je recommande vraiment Architecture of Open Source Applications
    C’est une série de livres dont chaque chapitre est écrit par le mainteneur du projet concerné, ce qui permet d’apprendre l’architecture par l’exemple
    On y découvre non seulement ce qu’est l’architecture, mais aussi les contraintes qui l’ont façonnée, souvent l’histoire du projet et l’évolution de sa vision
    Comme souvent dans les ouvrages collectifs, tous les chapitres ne se valent pas et tous ne sont pas aussi intéressants, et ils ont tous vieilli, mais cela reste une lecture qui vaut le détour
    http://aosabook.org/

  • J’aimerais passer plus de temps à acquérir un meilleur modèle mental du projet sur lequel je travaille, mais selon les projets, quand je commence à détester le langage de programmation ou certains choix d’architecture, ou des parties devenues si complexes qu’elles semblent ne plus mériter le temps qu’on y passe, ma motivation chute fortement
    Cela dépend du projet, mais travailler comme « full-stack developer » donne parfois l’impression d’enlever tout le plaisir de la programmation
    Je passe déjà 40 heures par semaine à regarder le projet le plus ennuyeux qu’on puisse imaginer

    • Le mieux est simplement de lâcher prise
      Il n’existe pas un seul projet sans défaut
      Et si le langage de programmation est un problème à ce point, mieux vaut changer de bateau
      Je pense que tout le monde devrait savoir travailler avec plusieurs langages, mais au final le choix t’appartient
    • La paralysie de l’analyse est toujours un danger, donc il faut viser la flexibilité plutôt que la perfection
      Il faut vérifier si les décisions auxquelles on consacre le plus de temps sont vraiment les plus importantes
      Des structures de données bien conçues ont bien plus d’impact sur la performance et la maintenabilité qu’un framework, un langage ou une plateforme
      Personnellement, je travaille chaque jour avec mon TDAH, donc je dois continuer à pousser pour que les choses avancent, ce qui signifie sélectionner les décisions sans importance, les clôturer, puis me concentrer sur l’espace de problèmes restant qui exige une réflexion attentive
    • On dirait plutôt une situation où il faudrait mieux gérer ses émotions
  • Des expressions comme « clean code » ou « beautiful code » n’aident pas beaucoup les juniors à apprendre les bonnes pratiques de software architecture
    Quand un junior demande pourquoi on utilise un ORM et qu’un senior répond « parce que c’est plus propre », il ne lui reste qu’un gros point d’interrogation
    Mieux vaut définir une liste claire d’objectifs
    Maintenabilité, performance et scalabilité, efficacité, résilience, observabilité, testabilité et couverture de test, sécurité, facilité de lecture pour un nouveau développeur : ce sont des critères qu’il faut mettre en balance
    Plus on ajoute de critères, plus il devient facile de faire de meilleurs choix quand on hésite, et cela a aussi du sens pour les personnes hors de l’équipe de développement, ce qui permet de s’accorder avec le client sur ce pour quoi il paie
    Un projet passe l’essentiel de sa vie en mode maintenance, ce qui est une bonne chose car cela signifie que le projet a réussi ; on peut donc aussi définir la maintenabilité
    Une bonne base consiste à pouvoir ajouter de nouvelles fonctionnalités sans casser l’architecture, voire sans casser la signature d’une seule méthode
    Il faut être très prudent avec l’abstraction
    La formule « les abstractions cachent souvent à quel point ce que l’on veut est simple » est juste, et les ORM en sont un bon exemple
    Dans la plupart des cas, les données doivent être traitées comme des citoyens de première classe, et cela améliore aussi la collaboration avec les DBA
    Il est aussi difficile d’éviter l’optimisation prématurée tout en réfléchissant à ce qui se passe en dehors du happy path, mais cela aide à éviter de foncer tête baissée dans l’implémentation d’une bonne idée sans en examiner les avantages et les inconvénients
    Imaginer que la personne qui lira mon code passe une très mauvaise journée m’aide à le rendre plus agréable à lire
    Cela concerne les commentaires disséminés, les variables locales qu’on pourrait omettre mais qu’on garde, les noms de variables, etc.
    Les frameworks doivent être choisis avec soin : bons serviteurs, mauvais maîtres
    La formule de l’article « ne sois pas un frameworker, sois un ingénieur » est juste

    • Comparés aux frameworks modulaires, les « frameworks à opinions fortes » valent de l’or
      Je n’ai rien contre les opinions fortes en soi, et pour une bibliothèque ou un outil cela peut même être une excellente qualité
      Cela signifie souvent que cette bibliothèque ou cet outil embarque une vraie expertise métier sur son domaine
      Mais dans un framework, des opinions fortes dérivent facilement vers le syndrome « quand on a un marteau, tout ressemble à un clou »
      Ce n’est pas toujours le cas, ni toujours un problème, mais lorsqu’on applique largement une orthodoxie issue d’un domaine précis, la justification qui valait dans ce domaine risque de se briser dans un contexte plus large
      C’est pourquoi je préfère les frameworks modulaires où l’on peut brancher un autre ORM ou une autre couche d’intégration de persistance, remplacer le routeur, le validateur ou d’autres composants mal adaptés au problème
      C’est particulièrement précieux quand l’écosystème du framework propose plusieurs alternatives relevant de paradigmes différents
      On peut alors choisir un outil prêt à l’emploi qui convient presque, dont les défauts sont clairs, et qu’on peut compléter si nécessaire
      Pour la maintenabilité, il est très important de lutter contre le syndrome NIH
      C’est un risque permanent qui absorbe les ressources à une vitesse étonnante
      En même temps, certains composants peuvent offrir de vrais bénéfices quand on les ajuste soi-même ou qu’on les maîtrise entièrement ; la difficulté consiste à déterminer lesquels relèvent de quel camp
      Je suis profondément d’accord avec le fait de placer la maintenabilité tout en haut de la liste
  • Du point de vue de l’ingénierie système, la software architecture ressemble à la conception de la plomberie
    C’est très important, mais on ne vit pas dans la plomberie, on vit dans la maison qui la contient
    Si la plomberie ne tient pas compte du reste de la maison, la réparer peut coûter extrêmement cher

  • Bon article
    « Apprendre la software architecture », c’est comprendre qu’il n’existe pas une seule bonne réponse
    C’est à la fois un art et une science
    Côté lecture, je recommande Simplify IT - The art and science towards simpler IT solution
    https://nocomplexity.com/documents/reports/SimplifyIT.pdf

  • Les talks de Gary Bernhardt sont vraiment à part
    Ils contiennent beaucoup d’idées qui mènent vers d’autres pistes intéressantes