À propos de CppNorth 2023

Quelques raccourcis :

Notez que le contenu de cette page est en chantier, en particulier sur le plan du formatage, car je suis débordé. Je retravaillerai le tout dès que possible, promis.

Grâce à l'Université de Sherbrooke, j'ai le privilège de participer (en personne!) à CppNorth 2023. Nous sommes de retour au même endroit que celui où s'est tenu CppNorth 2022 et qui nous avait si bien accueilli. Encore une fois, je suis venu en train est c'est vraiment une expérience très agréable.

Ce qui suit est une sorte de journal de voyage (sans la partie voyage!), avec éléments humains et éléments techniques. Au besoin, référez-vous à ce glossaire : ../../Lexique/lexique-wg21.html

Notez que c'est pour moi une semaine très, très occupée, et que j'ai assurément oublié de mentionner plusieurs rencontres. Si je ne vous ai pas mentionné, ça en dit plus sur ma mémoire défaillante que sur l'intérêt que je vous ai porté.

Pour un peu de bagage supplémentaire sur l'événement, voir :

Pour les journaux de « voyage » d'autres participant(e)s, voir : https://cppnorth.ca/trip-reports.html

Début du contenu technique

Je vais mettre le contenu technique dans des blocs les mettant comme celui-ci. Si vous ça ne tombe pas dans vos cordes, passez par-dessus.

Fin du contenu technique

Les jours entourant l'événement

J'ai la chance cette année d'être accompagné de mon amoureuse Za, qui peut travailler à distance dans le cadre de mon emploi et qui pourra profiter d'un changement d'air temporaire (la chambre d'hôtel est le même prix que je sois seul ou que nous soyons deux), ce qui rend le voyage beaucoup plus agréable.

Je devais donner une classe de maître les 15 et 16 juillet, mais (inflation aidant?) toutes les classes de maîtres ont été annulées à la dernière minute (pas assez d'inscriptions). C'est triste (j'aime bien faire cela!), mais bon. Ça m'a permis de fignoler un peu ma présentation du jour 0, et ce fut doublement utile car j'ai appris (le jour juste avant la conférence!) qu'on aimerait que je donne une présentation supplémentaire pour compenser l'absence d'un autre présentateur, alors j'ai dû préparer une deuxième présentation, impromptue celle-là.

Jour 0 17 juillet

Petit déjeuner avec mon amoureuse Za de même que quelques habitués des conférences (Kate Gregory, Ben Deane, Miro Knejp, Peter Sommerlad et René Ferdinand Rivera). J'essaie d'aller faire des tests pour ma présentation par la suite mais l'équipe technique n'est pas disponible dans l'immédiat.

Après avoir cherché (et trouvé) les coordonnées du Wi-Fi, je me prépare un peu (quelques retouches à mes diapos, ajustements en lien avec ma présentation imprévue de demain). J'en profite pour saluer Andreas Weis qui doit co-écrire quelque chose avec moi sous peu. Il n'y a pas de courant électrique à notre disposition dans la salle des Keynotes.

Mike Daum prend la parole. Il fait son habituelle reconnaissance des terres non-cédées sur lesquelles la conférence se tient, nous explique que ce fut une année difficile pour organiser l'événement. Il cite Mr Rogers (Za serait contente!) à titre de remerciement pour les gens qui l'ont aidé, et présente les commanditaires. Il explique les commodités mises à la disposition des gens (salle de prière, salle pour les parents qui en ont besoin, ce genre de truc). Il invite les gens qui n'ont jamais présenté à une conférence à offrir un Lightning Talk, et rappelle le code de conduite (Code of Conduct, CoC).

Il finit en présentant formellement Kate Gregory. En la présentant, il mentionne qu'elle est d'avis que le logiciel devrait simplifier la vie des gens (hilarité générale!).

Vidéo : https://www.youtube.com/watch?v=W_xT8Jc7GRA

Kate Gregory – Steps to Wisdom for a C++ Programmer

Kate Gregory dit qu'elle parlera de ses trajets, du chemin qui l'a mené là où elle est désormais. Elle parle des outils, des amis, des guides... De ce qui nous rappelle ce qui compte vraiment (elle dit avoir défendu sa thèse de doctorat avec une vitamine prénatale dans sa poche, à titre de rappel).

Kate Gregory parle de la sagesse comme des heuristiques qui aident à prendre de meilleures décisions (« meilleur » dépendant du regard des gens qui observent). Elle parle aussi de la sagesse comme ce  qui permet de traverser les moments plus difficiles.

Kate Gregory mentionne l'impact des erreurs et l'importance d'apprendre de celles-ci (elle distingue dix ans d'expérience et dix fois un an d'expérience). Une vie trop facile ne simplifie pas l'acquisition de sagesse. La confiance envers des gens qui en valent la peine peut être source de sagesse par contre.

Kate Gregory mentionne quelques trucs, rien de secret, des trucs évidents mais utiles : Be Nice, Trust, ce genre de truc. L'un des premiers trucs est This Should Work : avec expérience, on sait que c'est supposé fonctionner, et on comprend mieux par où passer pour le faire fonctionner. « Try it Now ». « If all else fails, read the instructions ». « You're not an imposter, you're a learner » (si tu ne sais pas comment le faire aujourd'hui, tu vas apprendre comment y arriver).

Kate Gregory continue : You Have to Actually Do the Work. Faut se retrousser les manches et prendre le temps de le faire.

Kate Gregory ajoute Somebody Should. Savoir identifier le fait que quelqu'un doive faire quelque chose est une aptitude utile. Faire la chose est une aptitude utile mais différente. Si on est une personne qui peut identifier le travàil à faire, c'est mieux d'être capable de le faire aussi (quand bien même ce ne serait que pour la crédibilité) et d'offrir aide et directions au besoin.

Kate Gregory : Make sure it's the right work. Savoir qui faire et quoi ne pas faire a de la valeur. Elle parle de son expérience à titre de consultante, et rappelle qu'appeler des inconnus pour du travail qualifié, ça fonctionne rarement.

Kate Gregory : Observe and Remember. Prendre des notes dans les rencontres. Prendre des notes aide à mémoriser le contenu des échanges. Rester dans la zone aide aussi (faire autre chose que participer à la rencontre, c'est nuisible). Avoir des notes, ça fait de nous une forme d'autorité. Noter ce qui compte pour nous aide quand les autres n'ont pas pris de notes car ce qui compte pour nous est plus concret. Elle recommande de prendre des notes écrites même quand on travaille seuls; ça peut sauver du temps quand on corrige des bogues. Elle recommande aussi de ne pas détruire ce qu'on a écrit, et de préférer un dépôt pour conservations des idées et utilisation future. Ça peut même servivr de base pour écrire des guides ou des manuels! Elle donne des utilisations possibles pour ces notes, incluant se souvenir de ce qui existait par le passé ou pouvoir expliquer pour quelle raison le travail a pris autant de temps (ça peut aider devant des avocats!).

Kate Gregory parle ensuite de Connections and Patterns. En particulier les connexions entre humains. Est-ce que les collègues sont des alliés? Elle parle d'une autre conférence qu'elle a donné (un Keynote à ACCU) où elle décrivait les choses qu'on aime faire dans un jeu mais qu'on ne fait pas dans la vraie vie (p. ex. : partager les ressources pour avoir une meilleure équipe!). On veut avoir confiance envers ces gens, pouvoir demander conseil, savoir qu'on ne fera pas rire de nous. L'amitié enrichit la vie, et aider les autres est valorisant.

Kate Gregory parle en bien de Sean Parent, de son extraordinaire présentation de 2013 à C++ Seasoning bien sûr, mais aussi de Generic Programming à Pacific C++ 2018 qu'elle présente comme une leçon d'histoire d'une grande valeur. Elle dit que ça vaut la peine de regarder cela deux fois.

Kate Gregory poursuit avec les connexions, et parle de connexions entre incidents. Les trucs qui sont récurrents, qui nous rappellent un incident du passé. Des cas de « This is just like X, except with Y ». Porter attention, prendre des notes. S'envoyer des courriels à soi-même (ou à son / sa partenaire de vie, comme Za le fait souvent avec moi). Mais elle avertir de ne pas « sur-généraliser ». Parfois, les gens réagissent... et ce n'est pas notre faute. Ils ont peut-être eu une mauvaise journée. Ce qui était causé par une fuite de mémoire autrefois peut ne pas l'être aujourd'hui.

Kate Gregory : Ask the Right Questions. Elle parle de projets qu'elle a réchappé du désastre en arrivant (à leur demande) de nulle part et en posant des questions que les gens en place ne pensaient plus à poser. « Someday, I just want to... » peut être suivi par « And what would be different if you did? » car les gens ne veulent probablement pas tout changer, et veulent sans doute un effet qu'elles ou ils ne voient plus comment obtenir. « Who is supposed to make sure this happens? » (c'est pas la même chose que « Do this »). « What do you think that would fix? » ce qui peut être utile quand quelqu'un fait une bêtise (on veut régler le problème après tout). « What's the worst that could happen? », puis « What needs to change to prevent that? ».

Kate Gregory parle d'autres questions clés : ceci nous coûte-t-il de l'argent? Si oui, combien? (remplacer l'argent par du temps, des ressources, etc.). Qu'est-ce qui nous empêche d'avancer? Si on n'a pas les réponses, comment pourrais-je les trouver? « Are you Ok? » peut être important parfois.

Kate Gregory dit que pour vraiment profiter de ces questions, il faut être capable de se les poser à soi-même. Elle font ressortir des connaissances cachées ou perdues. Se répondre à voix haute peut aider aussi.

Kate Gregory parle de la sagesse de connaître ses forces, ce à qu'on est bons. Ce qu'on aime faire. Quand un projet ou une tâche tombe dans nos cordes, le dire ouvertement (mais avec courtoisie). Savoir quelle est la valeur que l'on apporte à notre équipe. Accepter les tâches avec confiance et enthousiasme. Et connaître ses faiblesses : pas besoin de les dire aux autres, mais c'est bien de les connaître. On peut travailler là-dessus, s'améliorer, mais on n'est pas obligés. Si notre emploi nous impose de faire des tâches qui ne sont pas pour nous, on peut chercher un autre emploi; on peut aussi décliner avec élégance. Et si on ne peut pas s'en sortir, on peut demander de l'aide.

Kate Gregory revient sur l'importance d'avoir des buts, des objectifs. Une mission. Connaître ses objectifs augmente les probabilités de les atteindre, et facilite la prise de décisions, comprendre les enjeux, évaluer le poids relatif des pour et des contre. Les objectifs aident à établir des priorités, à savoir ce qui peut être ignoré ou mis de côté. Ce qui compte pour un projet ou une partie d'un projet peut ne pas être pertinent pour un autre projet ou une autre partie. Ça aide aussi à être confortables avec les choix que l'on fait. Elle suggère de garder une image de nos objectifs, p. ex. : si on vise un chalet sur le bord d'un lac, avoir un fond d'écran avec un canard sur un plan d'eau.

Kate Gregory cite un tweet d'Adam Grant qui met de l'avant que ce qui est le plus important est de ne pas confondre ses rêves pour ceux des autres. Elle suggère d'essayer d'écrire sa propre eulogie, comme si on avait 95 ans : où est-on décédé? Quels étaient nos loisirs? De quoi se souviendra-t-on en pensant de nous?

Kate Gregory parle du plaisir d'apprendre. Elle parle de son expérience avec C++23 et dit qu'elle était grognone en examinant ce qu'elle devrait enseigner... puis après avoir joué avec ces trucs, et fait sa liste des trucs amusants (les mêmes trucs!), avoir pris du plaisir à penser aux mêmes mécanismes. Elle dit que la seule chose préférable à apprendre de ses propres erreurs est d'apprendre des erreurs des autres (vive les parents!). On peut apprendre des autres, des expertes et des experts des domaines qui nous intéressent. On peut apprendre. On est plus sages qu'on le pense.

Kate Gregory parle un peu des titres, des phrases qui aident à se souvenir (Naming is Hard (Let's do Better)... Better Safe than Sorry... ou encore This is a Rotate).

Kate Gregory fait un retour sur la présentation (elle est très bonne pour conclure). C'est bien ficelé.

Victor Ciura : comment éviter de se retrouver coincé dans les mêmes tâches encore et encore?

Kate Gregory parle d'une dame qui était capable de faire de la magie avec .xlst (même de l'arithmétique!) mais c'était très focalisé. Il est souvent sage de se diversifier un peu.

Q : ma seule compétence réelle est la paresse...

Kate Gregory quand j'étais jeune, je pensais finir professeur de mathématiques. Mes parents étaient des professeurs. En fait, je me suis aperçu que j'ai fait comme eux : j'aide des gens, je voyage, je le fais différemment. Ça m'a pris des décennies avant de m'apercevoir que j'avais atteint mes objectifs par des chemins détournés.

Mike Daum reprend la parole et remercie Kate Gregory pour son excellente prestation, qu'il qualifie de mémorable. Il dit qu'elle a défini le ton de l'événement, et que tout le monde ici sortira de la salle en étant une meilleure personne. Il donne une couverture à Kate Gregory (faite à Vancouver). Mike Daum souhaite un bon événement à tout le monde.

Vidéo : https://youtu.be/odUwnew6Axc

Patrice Roy – Moving an Existing Project to C++20 for Fun, Beauty... and Results!

Je ne prends évidemment pas de notes, car je présente. C'est une relecture d'une présentation donnée pour une chouette boîte de Québec, Innovmetric (bonjour à vous si vous lisez ceci!) en novembre 2022 puis retouchée pour le C++ Users Group de Montréal en juin 2023, et retravaillée pour tenir compte des remarques des gens qui y ont assisté (merci en particulier à Francis Lemaire pour m'avoir donné les impressions de la salle!).

Je pense m'en être tiré pas si mal malgré quelques incidents techniques (un fil près de mes pieds faisait disparaître l'affichage quand je bougeais, mais on a fini par régler cet irritant). J'ai fini à 11 h 59 soit une minute avant l'échéance (j'ai quand même pris quelques questions).

Bref dîner, accompagné brièvement par mon amoureuse Za qui a dû retourner travailler à la chambre. J'ai bavardé un peu avec Conor Hoekstra, puis j'ai trouvé une source de courant électrique pour survivre à l'après-midi et je suis allé voir Ben Deane (qui a gracieusement accepté de déplacer sa présentation aujourd'hui car Tony Van Eerd, qui devait présenter, est malade). J'ai parlé un peu de SG14 et de SG15 avec René Ferdinand Rivera, puis Ben Deane a commencé.

Vidéo : https://www.youtube.com/watch?v=Bzafsr6ifWw

Ben Deane – Calendrical C++: std::chrono, History, Mathematics and the Computus

Ben Deane commence en nous expliquant qu'il a écrit cette présentation sans aide d'une intelligence artificielle :) Il recommande aussi une présentation de Cassio Neri sur l'accélération des algorithmes de calendrier.

Ben Deane présente ensuite un algo (horrible, en C) de 1996 qui a permis (sa faute!) d'avoir des phases de la lune dans DungeonKeeper et que ça y influence certains niveaux. Il présente les types de std::chrono, mentionnant que std::chrono::month est une étrangeté (c'est un « mois moyen », utile pour des calculs financiers).

Ben Deane recommande les temps typés, c'est tellement mieux que les temps qui ne le sont pas! Il recommande des conversions faites sur les frontières des API. Il parle de l'utilité d'écrire sa propre horloge parfois (il a fait un server_clock côté client pour certains jeux dans le but d'aider à la synchronisation). Il recommande aussi de réfléchir le temps en tics, et de faire une durée sur cette base à même std::chrono. Ensuite, il présente des applications pour définir nos propres unités de temps.

Ben Deane recommande ensuite de ne pas utiliser std::chrono::high_resolution_clock qui est sous-spécifié selon lui. Il recommande system_clock pour le Human Time et l'horloge monotone pour les minuteries (il recommande des horloges maison pour la haute précision)

Ben Deane présente ensuite chrono, les nouvelles horloges de C++20, et les types pour les dates. Il mentionne l'intérêt de sys_date pour les calculs.

Ben Deane va ensuite s'amuser avec l'histoire des calendriers du monde occidental. Regardez la présentation, c'est intéressant. Les mois alternaient entre 29 et 31 jours (les nombres impairs étaient de meilleur augure que les nombres pairs). pour une année de 355 jours ajustée de temps en temps par le Pontifex Maximus (p. ex. : César) quand il s'en préoccupait, sinon ça pouvait dériver longtemps. C'est plein d'information amusantes (les calendriers, c'est spectaculairement compliqué).

Ben Deane poursuit avec The Computus, pour calculer des dates en lien avec le calendrier (en particulier, la Pâques). Faut tenir compte de la lune, qui est un problème fondamental pour résoudre cet important problème pour le bienfait des âmes immortelles :) Une autre chic et divertissant tour d'histoire.

Ben Deane présente ensuite une implémentation de ces calculs absurdement compliqués. Il y a tellement de trucs divertissants dans cette présentation... L'algorithme à utiliser est apparemment Meeus / Jones / Butcher qui remonte au 19e siècle

Note : calculer Pâques est un cauchemar.

Ben Deane poursuit avec des exemples de bonne utilisation de chrono. Ça vaut la peine, il y a plein de perles dans cette section!

(je n'ai pas pris beaucoup de notes, mais c'est une super présentation et il faut la regarder!)

Richard Powell : as-tu connaissance de grosses bêtises historiques en lien avec des erreurs de calendrier?

Ben Deane pas vraiment (il y en a sûrement; je me souviens d'un incident avec le roi de Suède...)

Q : as-tu produit une courbe de probabilité de Pâques par date?

Ben Deane : pas vraiment. Pâques avance un peu, puis recule brusquement... Elles ne sont pas équiprobables. Les livres du moine Bede sur le calcul des dates commencent par une explication des bases des mathématiques (avec des doigts, des phalanges, etc.) car le lectorat ne savait pas compter!

Q : clairement l'idée de zéro était absente. Est-ce que l'avènement du zéro a influencé le calendrier?

Ben Deane : l'idées de Ides est morte avec la chute des romains, dans les années 800, et l'essence des calendrier d'aujourd'hui était en place (avec plein de problèmes) vers les années 600. Les chiffres romains étaient disparus pour l'essentiel.

Du bonbon! Je vais saluer mon amoureuse dans son bureau temporaire cette semaine (notre chambre) en lui apportant une collation (on a des « Canadian Snacks » : des bâtonnets de croustilles au Hickory, des croustilles au ketchup, des barres nanaimo, des tartes au sucre et au raisin, et des smarties) puis je redescends pour la présentatoion de Fatemeh Jafargholi sur un sujet qui me préoccupe (je dois l'enseigner souvent). Je veux voir comment elle s'y prend et ce qu'elle aura à raconter.

Vidéo : https://www.youtube.com/watch?v=rBkRqJ6ESik

Fatemeh Jafargholi – C# for C++ developers

Fatemeh Jafargholi nous accueille. et dit qu'elle aurait voulu assister à une présentation sur ce thème l'an passé. Elle vient de C++ et s'est trouvée obligée de faire du C# pour un projet cette année. Elle souhaite faciliter la transition des individus qui doivent vivre la même chose qu'elle en montrant les similitudes dans certains cas.

Fatemeh Jafargholi dit classer les différences (mineures, simples, majeures). Elle commence par les « mineures » :

Fatemeh Jafargholi enchaîne avec les différences « simples » :

Fatemeh Jafargholi dit ensuite vouloir parler de deux différences « majeures » :

Fatemeh Jafargholi recommande de lire aussi sur la réflexivité et les annotations, qu'elle n'a pas couvert dans sa présentation

Q : quelle est la différence entre Dispose et un destructeur

Fatemeh Jafargholi : Dispose n'est pas un destructeur, un finaliseur ne l'est pas non plus (elle ne parle pas vraiment de IDisposable dans sa réponse, et dit que using est requis ce qui est faux). Une personne dans la salle parle des risques associés à Dispose et using dans une boucle (il y a des outils pour trouver ces bogues)

Mike Daum : comment fonctionne le paramètre out déclaré au point d'appel d'une fonction?

(les gens répondent en discutant; c'est une syntaxe qui demeure très étrange, encore aujourd'hui)

Q : à propos des méthodes d'extension, ce qui et bien est que ça limite l'implémentation aux membres publics de la classe qu'on étend (ça ne brise pas l'encapsulation)

Q : peut-on surcharger les méthodes d'extension pour plusieurs types?

Fatemeh Jafargholi : bien sûr

Q : de quoi t'ennuies-tu le plus de C++ quand tu fais du C#?

Fatemeh Jafargholi : les templates :) Je dois penser aux portées différemment maintenant que la finalisation est hors de mes mains

Mike Daum : l'absence de destructeurs influence-t-elle ta conception à haut niveau?

Fatemeh Jafargholi : au début, oui, mais je tends à utiliser finally et using maintenant. Devoir m'en préoccuper est un peu embêtant (j'aimais bien avoir des garanties de finalisation)

On finit vers 16 h 5. Je suis content d'être venu, mais ce n'est pas une présentation que je recommanderais (trop superficiel pour être utile). La dame est charmante, sûrement compétente, mais de son propre aveu elle a peu d'expérience en C# alors ce qu'elle présentait n'était qu'une impression initiale.

On bavarde un peu dans les corridors pour clarifier des trucs qui demeuraient obscurs, puis je passe saluer ma Za mais elle est en réunion alors je repars vers la salle où se tiendra la dernière présentation de la journée. Rudyard Merriam vient faire des tests; il a de la musique, et heureusement qu'on fait des tests car le son est initialement si fort qu'on doit absorber le choc! Rudyard Merriam est un retraité depuis une quinzaine d'années, mais qui programme encore pour le plaisir (il a fait de la robotique par le passé) et qui a envie de parler de ses expérimentations récentes.

Vidéo : https://www.youtube.com/watch?v=h1aRKYs-FqA

Rudyard Merriam – A Journey into Ranges, Views, Pipelines, and Currying

Rudyard Merriam débute avec un peu de musique. Il nous annonce que son épouse est de Toronto :) Il dit qu'il était à Toronto l'an dernier pendant CppNorth et que Mike Daum l'a convaincu de venir au Speaker's Dinner, ce qui explique sa présence parmi nous cette année

Rudyard Merriam montre qu'il est assez vieux pour avoir utilisé Borland C++ à l'époque. Il ne se présente pas comme un expert des Ranges, mais parle de son intérêt pour la programmation fonctionnelle et le Currying. Il dit avoir commencé à apprécier ces enjeux suivant la lecture d'un texte de Simon Tóth dans Medium à propos du Advent of Code de 2022, puis il parle du livre de Ivan Cukic (il me manque des accents dans les deux cas) sur la programmation fonctionnelle en C++. Il dit que ce livrem en particulier, comprend de vrais exemples, pas juste des exemples jouets

Rudyard Merriam présente son premier projet, qui opérait à la ligne de commande (jour 7 du Advent of Code) et les difficultés vécues pour le faire compiler de manière portable. Il navigue ensuite d'algorithmes standards traditionnels aux Ranges, étape par étape. Il décrit les intervalles à demi-ouverts (bravo pour placer les bases!) et leur rôle, de même que les séquences déterminées par un début et un nombre d'éléments, puis celles définies par un début et un prédicat, puis les séquences génératrices dont on ne connaît pas la fin de prime abord

Rudyard Merriam généralise aux séquences [début,sentinelle) ce qui recoupe par une abstraction tous les cas qui précèdent. Il dit utiliser des std::ispanstream pour éviter des copies. Il compare std::copy() avec std::ranges::copy() qui prend en paramètre un std::range::istream_view<T> plutôt qu'une paire d'itérateurs. Ensuite, il utilise une lambda et std::ranges::filter_view pour ne conserver que les lignes de données qui ne représentent pas une instruction

Rudyard Merriam fait remarquer que le code est Inside-Out, au sens où quand on appelle les fonctions, la plus profondément appelée est la première traitée. Il passe ensuite de std::ranges à std::views (sauf pour std::ranges::copy qui n'a pas d'équivalent), et explique pourquoi préférer std::views::fct à std::ranges::fct_view en se basant sur le très bon article de Barry Revzin (je réfère souvent à cela aussi), et explique toutes les optimisations et les simplifications que cela permet d'obtenir

Rudyard Merriam passe ensuite aux pipelines pour profiter des views. Cela rétablit l'ordre naturel des opérations dans l'organisation visuelle du code. Il montre des exemples de type « avant », « après » pour mettre l'amélioration visuelle en valeur. Ses exemples ont des liens culturels qu'il prend le temps d'expliquer, ce que j'apprécie (j'aime bien les présentations qui tiennent compte du contexte)

Rudyard Merriam montre quelques outils qu'il s'est écrit en cours de route, entre autres pour déboguer les étapes d'un îpeline. L'une d'entre elles est un emit, qui laisse passer ce qui arrive à une étape du pipeline mais permet d'en garder une trace au passage. Une autre est un eval pour évaluer une étape du pipeline. Si emit retourne un views::filter sur une lambda qui affiche et retourne toujours vrai. Son eval est un struct à la Barton-Nackman qui expose operator|(std::range::input_range &&v, eval) et ne fait qu'itérer sur les éléments de v(ce qui les évalue parce que c'est comme ça que ça marche!), et un eval_view sur un std::range::input_range &&v qui fait v | eval(). Il explique que comprendre l'effet peut être subtil (ça aide à comprendre la mécanique de ces intervalles). Il admet que ses outils ne sont pas de qualité industrielle :)

Rudyard Merriam poursuit avec une discussion sur le Currying. Son exemple est celui d'un prédicat binaire (à deux paramètres) alors que la structure s'attend à un prédicat unaire. Il discute de techniques pour y arriver (celles de son emit et de son eval sont fragiles à ses yeux) : std::bind() peut faire le travail, mais il recommande le Currying à travers des lambdas. Il explique le Currying par une réduction de f(a,b,c) à une séquence f(a)(b)(c) (à la diapo 35, il y a une parenthèse non-balancée, mes yeux n'aiment pas ça). Il construit des lambdas manuellement (j'aurais espéré une révélation d'automatisation, mais c'est beaucoup demander :) ). Son exemple est intéressant mais ne me convainc pas (une notation de pipeline mènerait au même résultat il me semble). Il mentionne C++ Insights d'Andreas Fertig (qui et ici cette semaine) pour aider à comprendre.

Q : comment un débogue ce genre de code quand il y a un problème au milieu d'un pipeline?

Rudyard Merriam : c'est pour ça que je me suis écrit un emit

C'était pas mal, finalement. Bien présenté dans l'ensemble.


Le Speakers' Dinner suit. Ce fut un bon repas en bonne compagnie, après lequel je suis retourné à ma chambre pour préparer ma présentation impromptue de demain.

Jour 1 18 juillet

Un peu de travail entre 5 h et 7 h du matin pour fignoler la présentation d'aujourd'hui, puis une douche et un petit déjeuner, celui-là interrompu brusquement car la carte de mon amoureuse Za est défectueuse et elle (qui a une rencontre de travail tôt ce matin) est coincée dans un corridor du 14e étage de l'hôtel.

Une fois l'imbroglio résolu (et une nouvelle carte préparée), je me dirige vers la grande salle où se tiendra le Keynote de mon ami Ben Deane, une présentation qui sera assurément passionnante. J'en profite pour souhaiter bonne chance à  Pier-Antoine Giguère qui donnera (si je ne m'abuse) sa première conférence d'une heure ce matin. Il sera excellent j'en suis sûr!

Je bavarde un peu avec mon copain Richard Powell que je n'ai pas vu depuis presque un an. Très chic type. C'est un grand spécialiste de l'audio; il m'explique les subtilités de l'évaluation du volume (c'est salement complexe mais vraiment intéressant!)

Mike Daum prend ensuite la parole pour démarrer la journée. Il nous situe à nouveau sur le fait que nous sommes sur des terres non-cédées et parle (images à l'appui) des sans-abris dans le secteur, parmi lesquels les membres des premières nations sont sur-représentées. Ensuite, il revient sur des dossiers plus souriants et remercie les commanditaires. Il explique le déroulement de la journée et invite les gens à soumettre des Lightning Talks pour ce soir. Il finit en présentant Ben Deane.

Vidéo : https://www.youtube.com/watch?v=V5SCJIWIPjk

Ben Deane – Optimizing for Change

Ben Deane commence avec une diapositive de curry() pour tester la lisibilité des couleurs choisies. Ensuite, il parle de lui, de ses principes, de ses objectifs.

Ben Deane parle ensuite du sens du mot « optimiser » (vitesse d'exécution, mémoire, temps de compilation, ...) et dit que si on ne priorise pas la capacité de changer le code, il risque de calcifier, de se mommifier. Si on n'est pas prudents, le code facile à modifier est remplacé par du code difficile à modifier... parce qu'au préalable, le code était facile à modifier n'est-ce pas? Il met ensuite de l'avant l'importance de pouvoir modifier le code, et pourquoi.

Ben Deane parle de trois domaines : flexibilité (minimiser les points de changement requis), malléabilité (maximiser la capacité de changer), vérifiabilité (maximiser la confiance envers le changement).

Pour la flexibilité, il prend quelques exemples dont les déclarations de variables (le choix approprié d'un type, viser le type correct, pas seulement le code qui compile). Il parle des revues de code et dit que quand il suggère un changement dans le code, c'est typiquement pour que le code soit plus facile à entretenir dans le futur (mais il y va par instinct, par expérience; c'est en y réfléchissant qu'il s'en aperçoit). Il distingue next() et operator+ sur des itérateurs. Utiliser les fonctions globales comme std::size() plutôt que les fonctions membres. Utiliser ++ préfixe plutôt que suffixe. Préférer std::copy_n() plutôt que std::memcpy() (attention, il y a un caveat ici, je ne sais pas s'il est au courant). Utiliser des types de retour déduits par auto ou decltype(auto) plutôt que fixés a priori. Définir des types pour les unités de mesure qui correspondent aux réalités physiques que nous décrivons (p. ex. : un tic). Utiliser des algorithmes plutôt que des boucles. Écrire des fonctions plutôt que des commentaires ou du code par étapes.

Ben Deane rappelle que souvent, le recours aux algorithmes et à la généricité est une solution, et rappelle aussi que la STL ne change pas quand nos programmes changent. Il y a une inspiration pour nous ici. Nous sommes chanceux en C++ : nous avons la généralité sans les coûts.

« I don't want to know ». Je ne veux savoir que ce qui compte pour moi. Je veux de l'abstraction. Il apporte plusieurs autres exemples : std::variant, les exceptions, les opérations monadiques sur std::optional ou std::expected, les expressions lambda... Ben Deane recommande « Deny All Knowledge » : dire quoi, pas comment. Il donne des exemples pour divers paradigmes de programmation.

Ben Deane décrit les approches basées sur des tables (p. ex. : les automates) comme des endroits où le code est facile à entretenir, en particulier quand tout va dans la même table (il profite des littéraux maison pour y arriver). La proximité du code importe. Il montre des exemples basés sur des tables de données, ce qui permet de formuler des requêtes sur le code dans le code.

Ben Deane dit que supprimer le code peut améliorer la flexibilité. Dans une base de code de taille régulière, il y a presque assurément de la répétition de fonctionnalité après tout, et supprimer puis généraliser peut nous rapprocher de code plus flexible.

Ben Deane rappelle que la flexibilité vient souvent de la composition de petites entités, de petites fonctions (du Bottom-Up). Il a roulé un script AWK sur le code auquel il participe présentement et le mode en termes de nombre d'instructions par fonction est 6. Il rappelle que le code se fait copier et modifier sans arrêt, ce qui ajoute à l'importance de l'écriture de petites fonctions.

Pour la malléabilité, il rappelle que cette prétention de la POO est un échec, mais rappelle aussi que Simula67 ne cherchait pas à maximiser la réutilisabilité. Il associe l'idée d'objet à celle de durée de vie (c'est une perspective intéressante). C++ a un superpouvoir : nous avons de la vraie programmation générique, des concepts, des templates variadiques, et de la « vraie » POO à la compilation comme à l'exécution.

Ben Deane insiste sur l'importance de fonctions élémentaires, primitives, et de code écrit en termes de ces fonctions. Une fonction membre peut briser des invariants, contrairement aux fonctions libres. Il parle de multiples algorithmes pour chercher des valeurs, et de l'apport des Ranges qui permet de mieux composer ces opérations.

Ben Deane aborde les singletons (très présents dans les systèmes embarqués). Selon lui, le choix d'avoir une seule instance d'une classe est une contrainte qui nuit à la malléabilité, et qui devrait revenir au Top Level Code plutôt qu'à l'implémentation du type. Il donne quelques exemples (fort amusants!). Il ajoute que le code fait des mathématiques (parfois) et des entrées / sorties (toujours), et que le secret de la malléabilité est de découpler les deux.

Ben Deane discute d'approches à l'injection de dépendances : interfaces au sens OO avec des Mocks, équivalent basé sur des concepts et évalué à la compilation, dépendances à l'édition des liens (on lie avec une bibliothèque ou l'autre en fonction des besoins). Il y a des coûts : surcoûts à l'exécution, ridigité imposée aux implémenteurs, etc. Il montre une approche pour la gestion des dépendances à partir de spécialisations de templates (diapos à partir de la 61), c'est cool (il y a une manoeuvre avec un Pack qui sera toujours vide et qui est spécialisé pour le cas vide par la suite!). Il dit que ça fonctionne bien avec absence de couplage si (a) les interfaces sont petites (elles devraient l'être!), (b) on fait attention aux violations d'ODR, et (c) on fait attention aux types de retour car ils doivent être soit spécifiés explicitement, soit déduits des types génériques impliqués

Pour la vérifiabilité, Ben Deane commence par mentionner Jason Turner et Writing C++ The Right Way, et recommande de profiter de nos excellents outils. Il montre un bogue réel mais très pervers où une IIFE attendue n'est pas invoquée, et est convertie en pointeur de fonction puis en bool (toujours vrai!). Il recommande de mieux utiliser les types et de moins utiliser le débogueur. Il rappelle que le débogueur nous ment : nous programmons pour la machine abstraite de C++, pas pour un matériel spécifique, et croire le contraire laisse survivre des bogues. Ça manque de rigueur. Il donne un exemple extrêmement dangereux qui passe sans avertissement à la compilation même avec /W4 avec MSVC. Les types nous offrent une vérification formelle, plus robuste, et qui passent le test du passage du temps

Ben Deane mentionne des cas où changer le code autour de ce qu'on écrit peut changer notre code et son comportement sans que les sources de ce dernier ne changent d'un poil. Il rappelle que les tests sont cruciaux et qu'ils ne devraient trouver aucun bogue dans le code qui est livré. Il rappelle aussi que ce qui est facile à faire sera fait, souvent et beaucoup. Il ajoute qu'il faut qu'un test soit bien ciblé et teste ce qui doit être testé, pas plus. Il recommande GUnit (je vais investiguer) et rapidcheck pour du Property-Based Testing (une approche intéressante). Il apporte ensuite diverses approches pour les tests, et parle par exemple d'abstraire la plateforme quand on fait des tests pour plusieurs plateformes.

Ben Deane apporte un cas concret de code concurrent pour le CPU (mais il n'a pas l'essentiel de la bibliothèque standard et pas de threads). Après un détour sur une (bonne!) citation de Dijkstra, il montre comment il aborde le problème (fort intéressant, ça débute à la diapo 85) pour en arriver à de l'injection de politique dans une section critique « maison ». C'est bien : il simule une plateforme multithread en injectant cette représentation dans le code (c'est tout petit). Le fait de pouvoir utiliser du vrai code dans les tests ouvre la porte à l'utilisation d'un Thread Sanitizer, outil précieux s'il en est un!

Ben Deane mentionne que les temps de compilation ne sont pas un enjeu avec les techniques présentées. Il revient sur le fait que vérifier le code, c'est aussi utiliser le code. Il recommande de ne pas écrire des checklists, car si on peut écrire une checklist, on peut aussi l'automatiser.

Ben Deane aborde les caractéristiques de systèmes critiques et montre en quoi les techniques d'aujourd'hui sont pertinentes dans ces cas (dans un jeu, en finance, dans les systèmes embarqués, etc.)

Ben Deane apporte un exemple d'un service de jeu en ligne destiné à des dizaines de millions de clients. Il montre en quoi l'application des principes présentés aujourd'hui sont avantageux dans un tel contexte. Il revient avec un autre exemple d'un MMO très utilisé dans lequel il y aurait une fuite de mémoire. Il dit que si un crash est probable chaque dix jours et que le jeu planterait après une semaine, on peut vivre un temps avec une maintenance hebdomadaire, mais un jour (p. ex. : si on fait une promo spéciale lors d'un long week-end) ça va revenir nous mordre...

Ben Deane conclut en expliquant que la gestion du changement est difficile et qu'on le fait mal, ce qui explique qu'il y ait beaucoup d'espace pour amélioration. Il y aura des bénéfices à nos efforts :)

Peter Sommerlad : je confirme ce que tu dis. J'ai beaucoup d'expérience avec les tests en C++ et je n'utilise jamais le débogueur. Ce que je n'ai pas bien saisi est l'enjeu de l'ODR tantôt.

Ben Deane : il faut que toutes les unités de traduction voient la même spécialisation, alors il est essentiel de ne pas en avoir deux distinctes pour un même programme

Q : à propos des tests avec concurrence variable selon les plateformes. Certains tests qui pourraient causer un Deadlock semblent difficile à vérifier 

Ben Deane : sur un processeur, on peut interrompre les interruptions. Il parle des cas où l'ordre des verrous importe, mais ça peut se résoudre avec des outils.

Excellent travail! Mike Daum lui rend hommage en disant que cette présentation lui permettra de résoudre beaucoup de discussions futiles désormais :)

Je me déplace ensuite vers le lieu de ma propre présentation. Une pensée pour mon ami et ancien étudiant Pier-Antoine Giguère qui présente en même temps que moi et que j'aurais bien aimé aller encourager ce matin, mais les affres de l'horaire m'en empêchent

Vidéo : https://www.youtube.com/watch?v=cgq8pZPyzWQ

Patrice Roy – C++ and the fight between Elves and Orcs (How controlling memory allocation can make quite a difference)

Je ne prends évidemment pas de notes, car je présente. À titre de rappel, c'est une présentation improvisée, car on m'a demandé de dépanner il  ya deux jours à peine.

Je pense m'en être tiré correctement. J'ai eu quelques discussions plus tard dans la journée avec des gens qui m'ont dit ne pas s'être attendus à cela, mais avoir été intéressés.

Petite pause pour le dîner. Mon amoureuse Za fait du crochet pour aider des gens qui sont malades (on lui envoie des projets, elle les réalise et les renvoie par la suite) et elle manque de laine alors on sort pour aller magasiner la laine manquante, puis je me prends une bouchée et je retourne m'installer pour prendre des notes.

Vidéo : https://youtu.be/_2UQa6xD3Dk

Daniel Withopf – Why Good Code is Relative (How the Environment Changes the Way We Write C++ Code)

Daniel Withopf se présente. Il commence par présenter un renard arctique avec un poisson dans la bouche et parle d'adaptation à l'environnement, puis un aardvaark et un fourmilier, puis une girafe. C'est un thème, l'adaptation :)

Daniel Withopf dit que la présentation portera sur les conditions limites qui influencent le code, puis sur la comparaison Performance vs Latency, puis sur le déterminisme, puis sur le polymorphisme statique par CRTP (combinant plusieurs niveaux et std::variant). En tant que prélude, il parle de niveaux d'éveil en programmation  : niveau 0 où on refait sans cesse les mêmes erreurs, niveau 1 quand on apprend de nos erreurs, et niveau 2 où on peut juger sur la base de nos expériences passées ce qui est pertinent à la résolution des problèmes d'aujourd'hui. Selon lui, comprendre les conditions de notre environnement de travail est un prérequis pour le succès

Daniel Withopf présente quelques conditions limites : temps de compilation (cinq minutes? deux heures?) ce qui influence les stratégies d'implémentation. Exécution sur le Cloud ou sur un composant embarqué? Est-ce qu'on est préoccupés par le débit? Par la latence? Doit-on optimiser pour le pire cas? Pour le cas moyen? Les résultats doivent-ils être totalement reproductibles? Quelles sont les conséquences d'un bogue? A-t-on accès à de l'allocation dynamique de mémoire?

Daniel Withopf se préoccupe d'abord de la question débit vs latence. Ce qu'il nomme latence est en fait la minimisation de l'écart-type. Il cite Timur Doumler sur la question de la basse latence.

Daniel Withopf enchaîne sur la question du Deterministic Computability au sens de la capacité d'obtenir les mêmes résultats dans les mêmes conditions. C'est difficile de reproduire l'état complet d'un programme à un certain point dans son exécution, surtout s'il s'exécute longtemps. Aussi, il peut y avoir des enjeux d'ordonnancement ou de Timing des opérations, surtout avec des classes qui ont des états mutables, et les générateurs de nombres pseudoaléatoires avec un germe non-fixe sont bien sûr un facteur. Il parle de l'enregistrement des entrées et des sorties des capteurs pour être capable de « rejouer » une exécution.

Daniel Withopf passe ensuite un peu de temps que les conséquences des états mutables des objets dans le déterminisme répétable des exécutions (c'est plus facile, par plusieurs ordres de grandeur, avec des fonctions pures; il parle de Data-Driven Design mais je ne suis pas sûr qu'on ait la même acception du terme lui et moi)

Daniel Withopf poursuit avec l'enjeu de la programmation sans allocation dynamique de mémoire. Il parle de temps requis (en comparaison avec le recours à la pile; je suis surpris qu'il ne parle pas plutôt d'indéterminisme), de risques d'échec d'allocation, du souhait d'éviter la gestion d'exceptions, etc. et rappelle que dans les applications Safety-Critical c'est souvent interdit, tout simplement. Les défis sont, selon lui : entreposer des objets de différentes tailles et de différents types? Remplacer le polymorphisme à partir de méthodes virtuelles (pas requis, quand même)? Implémenterdes hiérarchies de classes à plusieurs niveaux? Il ajoute qu'on tend à moins profiter de la sémantique de mouvement. Il présente un squelette de StaticVector<T,Cap> et dit que si on a deux types, on peut avoir recours à deux StaticVector distincts... ou mieux, utiliser un StaticVector<variant<T0,T1>,Cap>

Daniel Withopf présente variant en utilisant une hiérarchie de classes, mais c'est vraiment pas nécessaire (le sait-il?), puis passe à une approche reposant sur CRTP (il cite Jonathan Boccara) pour économiser une indirection virtuelle. Il parle d'ajouter des niveaux à sa hiérarchie de classes (Peter Sommerlad lui recommande – à juste titre! – de ne pas faire ça). Il montre une approche pour se simplifier la vie quand on pense en avoir besoin. Ses exemples manquent un peu de fini... (idéalement, il voudrait montrer un exemple comme template <class T> void f(const Base<T> &obj) { obj.foo(); } pour mettre son approche en valeur;  il a quelque chose qui y ressemble mais plus loin, à la diapositive 47 de sa présentation). Il a un exemple de PassKey Idiom qui en profite, c'est pas mal celui-là

Daniel Withopf poursuit avec une approche de CRTP quand il y a plusieurs dérivés possibles. Il a quelques erreurs de syntaxe dans ses diapositives (on l'aide un peu). Il mentionne que std::variant remplace le polymorphisme dynamique dans certains cas, mais il suggère de ne pas en parler sous le vocable de polymorphisme statique (le terme est galvaudé)

Daniel Withopf fait une petite boucle et montre un animal mythique qu'il présente comme un hybride de diverses approches

Peter Sommerlad : je ne suis pas sûr qu'on ait besoin du MiddleProxy dans l'exemple de CRTP à plusieurs étapes

Daniel Withopf réfléchit à haute voix...

Je discute quelques minutes avec Daniel Withopf pour l'aider dans son organisation d'exemples. J'espère qu'il a pris mes suggestions de manière constructive parce que c'était de bonne foi (et de bonne humeur!). Ensuite, j'apporte quelques fruits à mon amoureuse Za qui est en réunion au 14e étage, puis je viens manger quelques crudités en bavardant avec un chic type qui enseigne la programmation au niveau collégial dans les maritimes et avec Pier-Antoine Giguère (semble que ça se soit bien passé pour lui ce matin, cool! :) )

Alors que je me déplace vers le lieu de la prochaine présentation, Fatemeh Jafargholi m'aborde et on échange un peu sur sa présentation d'hier (de manière constructive encore une fois, évidemment). Très sympathique dame.

Une fois dans la salle, je bavarde avec Björn Fahller qui me dit qu'il pensait que ma présentation de ce matin porterait sur les allocateurs PMR (j'aurais pu le faire avec cet outil, mais il y aurait eu des coûts; peut-être une autre fois). Il me parle d'une autre conférence qu'il a donné sur le sujet où il a utilisé une pmr::unordered_map<pmr::string,T> et me fait part du coût de la propagation du pointeur vers la pmr::memory_resource du conteneur externe vers les conteneurs externes (dans ce cas, ça coûte cher!) alors que le coût de l'indirection polymorphique tend à être petit du fait qu'on y passe souvent et qu'elle tend à être en cache. Bon point!

Vidéo : https://www.youtube.com/watch?v=Wz_d2HQiIQo

Björn Fahller – Typical C++, But Why?

Björn Fahller nous accueille avec humour. Il a fait sa maîtrise à UBC, je ne le savais pas (il vit en Suède maintenant). Il dit qu'il nous parlera de casse-têtes, et dit que les puzzles d'un fabricant donné ont (s'ils ont la même dimension) les mêmes formes de pièces aux mêmes endroits. Il fait une analogie avec le système de types de C++ où les pièces peuvent s'imbriquer de manière suspecte à l'occasion... mais C++ nous permet de faire nos propres formes de pièces! Il utilise des images de https://puzzlemontage.crevado.com

Björn Fahller dit qu'on ne porte pas souvent attention aux types qui permettent de passer l'information entre les pièces du puzzle. Il commence par un bogue bête où on aurait passé le mauvais de deux paramètres (de même type) à une fonction, et montre comment résoudre le problème en introduisant un type (struct sanitized_string { string value; }; donc tout petit, tout simple, mais on peut ajouter des constructeurs explicites et des opérateurs de conversion explicites pour resserrer le tout un peu plus) pour transformer un bogue latent en une erreur de compilation. On cherche à simplifier ce qui est correct et à rendre compliqué l'acte de se mettre dans le pétrin.

Björn Fahller enchaîne avec la question (maudite) des paramètres bool de fonctions. Il montre une fonction qui accepte un string_view suivi de trois bool (comment savoir si un appel les prend dans le bon ordre?). Il suggère des enum class ce qui crée des types distincts (deux valeurs, on et off, dans chacun).

Björn Fahller parle ensuite des valeurs par défaut des paramètres aux fonctions (hé la la...). Il montre que refactoriser la fonction pour ajouter des paramètres ailleurs qu'à la fin compile alors parfois accidentellement, surtout si certains types de paramètres sont interchangeables (ouch). Trouver les bogues par la suite est... cauchemardesque. Il parle de Compiler-Error-Driven Design.

Björn Fahller poursuit avec les API qui ont des paramètres couplés, comme celles des sockets par exemple. Il montre que ça peut aisément causer des débordements de tampons. Il propose un buffer_view avec des fonctions associées qui offrent les métaphores attendues (il fait quelques itérations sur l'interface du type, mais recommande de ne pas abuser et de garder les interfaces simples et brèves; il donne dans l'orientation du principe YAGNI en quelque sorte). Recommandation d'ensemble : quand plusieurs paramètres sont couplés, un type (Range, span, etc.) est sans doute préférable (Björn Fahller dit que span est peut-être trop général dans certains cas; on peut utiliser <span> pour implémenter un buffer_view par contre)

Björn Fahller regarde ensuite le cas de multiples paramètres avec valeur par défaut. Dans ce cas, il recommande de représenter l'ensemble des paramètres par un type et d'utiliser les Designated Initializers. Il aborde la questions des paramètres requis, qu'il modélise par un template <class T> class must_init { public: must_init(T val) : value(val) { }operator T&() { return value;  } operator  const T&() const { return value; } private: T value; }; (bonne idée!)

Björn Fahller examine ensuite le cas d'une structure avec deux map dont les clés sont de même type, puis un accès à l'une par une clé destinée à l'autre. Il rappelle l'utilité des enum class quand ça suffit. C'est applicable dans mon code, ce truc. Il parle de simplification du nommage par la suite. Puis, il soulève la question de types non-entiers, ce qui exclut les enum class (pas le bon type sous-jacent). Il me en valeur operator<=> dans son exemple.

Björn Fahller termine en expliquant que le tout rend le code plus expressif, et facilite la communication dans les termes qui conviennent au domaine d'application. Ces raffinements nous donnent ce qu'il qualifie de « Inverse of Code Rot ».

Ben Deane : les paramètres bool sont validés par Clang Tidy :)

Björn Fahller : cool!

Q : dans Too Many Defaults, si on n'utilise pas C++20, devrait-on utiliser plusieurs fabriques?

Björn Fahller : tu peux avoir un constructeur par défaut et plusieurs mutateurs

C'était bien. Il y a des trucs là-dedans que je vais utiliser.

Petit tour à ma chambre pour saluer mon amoureuse Za puis je redescends pour la dernière présentation de la journée. J'ai une curiosité particulière ici car il se trouve que dans mon rôle de membre du comité de programme de CppCon, j'ai vu cette proposition passer alors je suis curieux de voir ce que ça donnera en pratique ici. Je commence à ressentir la fatigue par contre...

Vidéo : https://www.youtube.com/watch?v=kgUXfDpAmGQ

Levo DeLellis – C++ as an Optimizing Assembler – a Performance Talk

Levo DeLellis montre un « Hello World » fait main qu'il souhaite compiler et exécuter sur son propre Runtime (sans le support de bibliothèque standard). Il compile sur g++ avec -nostdlib. Il compile avec -static qui a donné des maux de tête à mon ami David Viens plus tôt cette semaine (une pensée pour toi cher ami!). Son code de base fait un segfault et il explique pourquoi. Il explique pouquoi il préfère xor %rdi,%rdi à mov %rdi,0 (le code généré occupe deux bytes plutôt que cinq pour son assembleur)

Levo DeLellis aborde la question de l'ABI et du code assembleur généré (il compile pour x86-64). Il implémente syscall (pas l'appel système du code machine) pour nous montrer la mécanique, et mentionne au passage que les mov sont probablement gratuits en pratique.

Levo DeLellis montre ensuite le code d'initialisation qui finit par appeler main(). Il utilise un errno qualifié thread_local et se ramasse avec un segfault parce que le registre fs est initialisé à zéro et qu'il essaie d'aller à un offset de -4 à partir de là (ouch), ce qu'il corrige avec un mmap() de 4Ko.

Levo DeLellis dit qu'une fois que la base fonctionne, il commence à optimiser (mais faut mesurer avant, mesurer régulièrement). Il utilise « perf record -e cache-misses ./a.out app args » comme ligne de commande. Il trouve que itoa() consomme le plus de temps (très peu, cela dit) et dit qu'il l'optimise pour les besoins de l'exemple. Il montre le code (très simple) et essaie de réorganiser les instructions pour accroître le parallélisme d'instructions dans le CPU

Levo DeLellis travaille quatre versions distinctes de itoa() (il teste avec des macros pour profiter du préprocesseur et implémenter une moins grande partie du langage). Une de ses versions utilise une Lookup Table et malgré ses tests initiaux (prometteurs), la saturation de la mémoire l'amenait en cache L2 et ça le ralentissait le tout.

Q : puisque la Lookup Table est très petite, peut-on l'inscrire dans le code plutôt que dans les données?

Levo DeLellis : j'y ai pensé aussi mais c'était pas possible

Levo DeLellis : j'ai lu que vector<T> n'utilise pas realloc(). Je ne savais pas si je devais le croire alors je me suis essayé (version non-générique)

Levo DeLellis montre un exemple avec un dialecte qui valide les bornes et dit que ça lui semble rapide. Son dialecte se nomme Bolin et il rapporte des accélérations significatives. https://bolinlang.com

Q : à quelle vitesse peut-on lire d'un fichier sans aucun test?

Levo DeLellis : je ne l'ai pas mesuré

Divertissant, mais très spécifique. Il y a des gens dans la salle qui font beaucoup d'assembleur et ces gens ont semblé aimer beaucoup (ça réagissait). Il a fini un peu tôt (20 minutes d'avance).


Mon amoureuse et moi avons mangé une bouchée, je me suis reposé un peu (la fatigue s'accumule), puis ce fut le moment des Lighning Talks.

Vidéo : https://www.youtube.com/watch?v=F4UUu2c3rWY et https://www.youtube.com/watch?v=68AswgNxwwY et https://www.youtube.com/watch?v=Dpk0z4iUFcM et https://www.youtube.com/watch?v=kKz5p8fNiYI et...

Lightning Talks

Il n'y avait pas de prise de courant disponible à mon arrivée, alors je n'ai pas pris de notes, mais c'était une excellente soirée animée par Tony Van Eerd. Quand les vidéos seront rendues disponibles, profitez-en, il y a des perles là-dedans.

Au retour à la chambre, j'ai parlé un peu avec mon amoureuse mais je me suis endormi rapidement. L'intensité de la semaine commence à me rattraper et je suis fatigué.

Jour 2 19 juillet

C'est le jour du départ, alors après la douche matinale, faut assembler les bagages (ça demande de la prudence ca il y a un poids limite par valise dans le train), s'assurer de ne rien oublier (j'ai laissé des vêtements derrière moi à CppCon 2022!) et aller porter le tout au lobby pour que ce soit rangé d'ici notre départ en fin d'après-midi.

Sympathique petit déjeuner avec mon amoureuse Za de même que Kate Gregory, Ben Deane et Mike Daum. On s'assure que Za puisse travailler tranquille cet après-midi (on a des endroits prévus pour ça ici, c'est très bien organisé), puis je vais me préparer pour ce matin. J'en profite pour féliciter Jessica Kerr pour son excellent Lightning Talk d'hier soir sur John von Neumann (c'était d'une grande fluidité; ça devrait être bon ce matin).

Mike Daum fait son discours du matin qui inclut sa reconnaissance des premiers peuples. Il en profite pour faire un commentaire sur la température (cet été est dangereusement chaud), images à l'appui. La reconnaissance des (précieux) commanditaires suit, de même que les consignes générales de la journée, et il invite les gens à l'accompagner dans un parc ce soir qu'il affectionne particulièrement.

Mike Daum nous présente ensuite Jessica Kerr.

Vidéo : https://www.youtube.com/watch?v=ltSy0CeHXl0

Jessica Kerr – I can write the code. But getting something done is another matter

Jessica Kerr explique son rôle (elle explique aux gens comment utiliser le produit de son entreprise, honeycomb.io, qui permet de soumettre des requêtes et d'obtenir de l'information). Elle nous présente tout d'abord un problème d'interface personne / machine. Après avoir corrigé ce problème... ils ont eu des plaintes d'usagers habitués avec le produit parce qu'il leur fallait faire deux clics plutôt qu'un seul pour réaliser certaines tâches. En gros : ça a été fait, mais ça n'a pas été « socialisé » et c'est mort.

Faire des changements logiciels, c'est devenu un problène social plus qu'un problème technique.

Jessica Kerr dit que la présentation porte sur la différence entre coder et obtenir des résultats :)

Jessica Kerr aborde la question du cheminement de carrière. Elle dit que quand notre logiciel ne sert qu'à notre entreprise, c'est un peu un privilège; quand on l'expose au monde entier, c'est plus compliqué. Sa deuxième histoire est le Schema Caching Project. Dans sa compagnie, le Schema est une description des données du client et on ne veut pas aller au SGBD tout le temps alors il faut du caching. Mais avant de coder, il fallait savoir ce qu'on voulait faire. Elle parle de la présentation faite aux gens du conseil d'administration, et d'une analyse subséquente pour voir ce qui pourrait briser si l'objectif était atteint. Il y a une relation directe entre les événements consommés et les revenus. Leur service, shepherd, dont il existe plusieurs instances sur AWS, doit tenir la route si les entrées croissent en volume. Au démarrage d'un shepherd, ce dernier fait une grosse requête au SGBD pour obtenir la cache locale, alors si on en démarre plusieurs le SGBD souffre. Le Schema Caching sert à amortir ce coût.

Jessica Kerr parle ensuite de la dispersion de trucs semblables au Schema Caching dans la compagnie (les serveurs ont des noms de chiens :) ). Elle explique que le changement prend du temps parce qu'il n'est pas que technique : il affecte des humains, et il faut les accompagner. Le Dataset Schema résultant crée un Bounded Context en termes de Data-Driven Design. Elle définit le code hérité (Legacy Code) comme du code dont plus personne n'a un modèle mental clair du fonctionnement

Jessica Kerr passe ensuite un peu de temps à expliquer comment on amène un individu à comprendre du code existant. C'est une bonne présentation. Elle parle se Symmathesy, un néologisme qui décrit un système d'apprentissage fait de parties qui apprennent (une équipe de travail, par exemple). Elle parle du processus humain qui a fait du projet un succès, même avant de coder quoi que ce soit (le codage a suivi, bien sûr, et il y en a eu beaucoup). Elle décrit le système existant (il y a un chemin d'observation interne qui passe de Poodle à Dogfood à Kibble :) ). On visualise l'impact des caches pour réduire les accès au SGBD.

Jessica Kerr explique que le code dans Dogfood (usage local) est le même qui est déployé à l'externe (éventuellement). Truc cool : Poodle exécute concurremment le vieux et le nouveau code, puis compare les résultats pour découvrir des régressions même en production. Ils font beaucoup de télémétrie, truc utile quand on expose des services à l'externe. Ils ont trouvé des bogues avec ce système (dans le nouveau code... et dans le vieux code! Dans ce dernier cas, faut voir si c'est fixable ou si des gens en sont venus à en dépendre). Elle décrit ce phénomène comme du Shadow Deployment et explique dans quels cas c'est applicable.

Jessica Kerr pose la question : quand le logiciel est-il complété? En fait, jamais, probablement. Elle fait un retour sur le processus de ce projet (c'est quand même pas si long, moins d'un an). Changer un système, c'est beaucoup plus que changer du code. Le processus demande de gérer du changement au sens large. Software Work is Designing Change

Jessica Kerr poursuit avec le Navbar Reorde, un autre projet. Elle décrit le processus pour un client d'entrer des données dans honeycomb et parle de MTTWFT (Mean-Time to What-The-Fuck). Le Navbar offre par défaut New Query, que les gens devraient utiliser, mais juste en dessous il y avait DataSet qui fait quelque chose de vraiment pas similaire. Déplacer DataSet vers le bas et le renommer en Data Settings mais c'est pas simpe parce que toutes les équipes de la compagnie veulent que leur produit soit en haut du Navbar. Pour le gérer, ils ont fait en sorte que le nouveau Navbar ne soit pas présenté aux vieux usagers (réorganisation dynamique). Ils ont fait une collecte de données pour mesurer les pour et les contre, puis ont présenté les données aux autres équipes pour avoir leur adhésion.

Jessica Kerr explique que cet autre projet fut un succès : l'équipe avait une mission, il y a eu de l'expérimentation, des données pour influencer les décideurs, et on a tenu compte des attentes des clients. Elle parle des effets de ces changements ailleurs, p. ex. : dans les documents qui accompagnent le produit, dans les réponses sur StackOverflow, et ainsi du suite. Le project inclut tout ce qui permet aux clients de tirer de la valeur de nos efforts.

Jessica Kerr dit que honeycomb a un Hack Week, deux fois par année, où on ne fait que des trucs techniques, par petite équipe de forces diversifiées. Ces produits sont intégrés à la version interne (Dogfood) et considérés pour exposition externe dans le futur.

Jessica Kerr rappelle que définir un problème est beaucoup plus intéressant que résoudre ce problème. Intéressant au sens de difficile, pas au sens de plaisant :)

Jessica Kerr fait un lien avec la présentation de Ben Deane hier et rappelle qu'il faut pouvoir gérer le changement dans le code, mais il faut aussi que les équipes soient capables de changer le code. Elle rappelle aussi l'importance de la télémétrie, et l'importance d'écouter les gens en charge de la production. Enfin, il faut tenir compte des attentes des gens envers notre code... alors il faut parler aux gens du marketing!

Jessica Kerr dit qu'elle travaille aux relations avec marketing maintenant (vocabulaire radicalement différent!). On se demande Does it Run? mais marketing se demande Do They Engage? et quelqu'un se demande Is it Profitable? alors que les avocats se demandent si on se fera poursuivre etc. Personnellement, sa question clé est Is it Useful? ce qui lui permet de connecter aux autres acteurs du système

Jessica Kerr rappelle que la valeur est une propriété émergente d'un système.

Jessica Kerr décrit ce qu'elle appelle le Scope of Caring. En début de carrière, c'était de 8 h à 17 h (la paix hors de cette plage!), puis c'est devenu la durée du projet, et plus on avance (en expérience, en responsabilité) les conséquences de nos gestes sont plus importantes et ça nous occupe (et nous préoccupe) plus. Elle revient sur l'idée de Symmathesy. On étend le Scope of Caring à notre équipe, à l'entreprise, etc.

Jessica Kerr parle de Pair Programming étendue (la personne qui tape sur le clavier ne peut pas prendre de décisions; les gens autour doivent verbaliser chaque décision)

Jessica Kerr : Symmathecist in the medium of Code (c'est le titre qu'elle se donne). Elle présente quelques livres (de philosophie) qu'elle estime utiles. Elle rappelle l'importance de s'exprimer de manière à ce que nos mots s'intègrent au système de valeurs de nos pairs et de nos collègues. Elle étend le Scope of Caring hors du travail et dans la sphère personnelle, faisant des liens avec le Keynote de Kate Gregory lundi portant sur les objectifs de carrière et de vie.

Jessica Kerr conclut par un appel à tous pour réduire la complexité qu'on ne peut pas influencer. Elle parle de cheminement et de développement personnel. Une très solide présentation

Mike Daum : est-ce que je comprends que ce sont des humains qui écrivent le logiciel?

Jessica Kerr : c'est les humains qui écrivent le logiciel pertinent en tout cas. Je fais produire du code de mauvaise qualité par une intelligence artificielle comme base de travail parfois, c'est Ok

Mike Daum rappelle que CppNorth est un événement sur les humaines et les humains qui programment avec un focus sur C++. Le Keynote de ce matin était tout à fait de circonstance.

Mike Daum annonce que Bloomberg s'est ajouté à titre de Gold Sponsor pour cette année, assurant le retour de CppNorth en 2024!

J'apporte une collation à Za, qui utilise notre chambre ce matin (le Check-Out est à midi). On mange bien (et généralement, on mange santé) ici : petites tartelettes aux fruits frais pour mon amoureuse; dans mon cas, des légumes verts et une trempette aux avocats. Je vais ensuite m'installer pour la présentation de Tony Van Eerd, qui est toujours excellent. Il fait le tour de ses diapos et je vois Leonard Cohen (paroles parodiées dans les sous-titres, mais chanson originale), Yoda (le titre est une référence à Star Wars) et Duff's Device... Ce sera amusant :) La salle est pleine, mais ça va être bon.

Vidéo : https://www.youtube.com/watch?v=gqopX4VInQw

Tony Van Eerd – Value-Oriented Programming Part V: Return of the Values

Tony Van Eerd situe la présentation de cette année en lien dans cette séquence de conférences. Il situe l'idée de valeur comme autre chose que des valeurs humaines. Note : je ne prendrai pas beaucoup de notes, ça va trop vite et c'est trop cool à regarder. Allez voir la vidéo :)

Tony Van Eerd parle de l'enjeu sur la table comme l'enchevêtrement, l'action (épeurante) à distance qui résulte de références et de partage d'objets. KYSS : Keep Your Stuff Separate

Tony Van Eerd revient sur le terme Complecting qu'il a utilisé dans le passé. Il revient sur son exemple classique de classe Camera un peu beaucoup enchevêtrée. Elle fait... tout. Quelle horreur. Ça grossit sans fin et c'est hors de contrôle. Les relations entre objet et attributs sont parfois 1 à 1, parfois 1 à 1 ou 0, parfois 1 à au moins 1... Il note que dans certains cas il y a des risques de condition de course de par le choix de faire de certaines données des variables membres plutôt que des variables locales à des fonctions

Tony Van Eerd distingue objets (ben correct) de orientation objet (qu'il voit dans une optique de sémantique de référence), ce dernìer étant le problème à ses yeux. Il rappelle que les classes sont faites de velcro (tout leur colle après). Dans sa classe Camera, tout petit changement risque de briser quelque chose. Ça impose une forme de raisonnement non-local

Tony Van Eerd présente les objets au sens OO comme un graphe de références. Il montre un arbre généalogique de Game of Thrones (Balance of thrones: a network study on Game of Thrones pour la source) à titre d'illustration, et rappelle que partager un pointeur ou une référence est aussi mauvais qu'utiliser une variable globale. Il rappelle les Incidental Data Structures, qui naissent un peu par accident dû à des partages, évoquées dans le passé par Sean Parent

Tony Van Eerd parle ensuite du Steering Wheel Problem, où deux conducteurs souhaitent conduire une même voiture (ça semble absurde, mais c'est une conséquence du partage d'objets). Il continue avec le navire de Thésée, où on remplaçait sans arrêt des morceaux du bateau par d'autres morceaux du même bateau (à la fin, est-ce le même bateau ou est-ce un bateau différent?). Et la question est : est-ce important? En C++, l'identité est associée à l'idée d'adresse en mémoire. Rich Hickey parle de PLOP (Place-Oriented Programming)

Tony Van Eerd compare passer l'adresse d'un int partout dans le code et en faire une globale. Selon lui, ce sont des gestes équivalents. Il rappelle que le polymorphisme classique au sens de Late Binding avec méthodes virtuelles se prête à ce type de pratique. On pourrait bien sûr faire autrement (p. ex. : utiliser un variant). Il mentionne évidemment que parfois, on veut des références, mais on veut un peu de contrôle sur la situation. Il utilise un poly_variant<B, D0, D1, ..., DN> dans ses exemples, c'est amusant

Tony Van Eerd enchaîne sur la Loi de Demeter, par laquelle on recommande d'éviter des enchaînements d'accès (a->b->c->d). Ensuite, il aborde la question des valeurs plus directement (bel exemple avec un « cliquez sur les cases qui appartiennent au navire de Thésée »). Quel est le critère pour savoir si deux choses sont égales? Ça dépend de ce qui importe aux usagers, aux auteurs de la classe, et à l'essence de ce que la classe représente (ici, le Shipness du Ship of Theseus). Il rappelle que std::span n'a pas operator== car on n'arrivait pas à en définir le sens.

Tony Van Eerd : l'enjeu clé est la substitutabilité, au sens de x==y <=> f(x)==f(y) (supposant f() pure). Est-ce que addressof(x)==addressof(y) est important? C'est beaucoup moins clair dans cette acception. Il discute de vector<T> et des comparaisons qui ne devraient pas tenir compte de capacity() (il omet l'enjeu des allocateurs, on le comprend) parce qu'il ne s'agit pas de propriétés manifestes (Salient Properties) de ce type. La capacité ne contribue pas à « l'idéal platonique » du type

Tony Van Eerd discute du concept Regular, important au concept de valeur. Ça veut en gros dire Do as the ints Do, et ça implique que == est réflexif et transitif. Il se trouve que quand les objets partagent des données, on ne peut pas (en général) garantir Regular. On s'attend en général à ce que Regular s'applique pour la plupart des types. Faire une Shallow Copy dans un constructeur de copie, c'est comme faire en sorte que operator+ fasse une soustraction.

Tony Van Eerd montre deux cercles un à côté de l'autre. On discute de leur constituion interne (couleur, position, rayon)... Il demande si deux cercles de même format et de même couleur sont égaux. On pense que oui, mais ils n'ont pas la même position. Que cherche-t-on à exprimer? Selon lui, la position est une propriété extrinsèque, pas intrinsèque, du cercle. Ça appartient à la classe, soit, mais pas à l'intérieur. Ça va ailleurs, peut-être dans une classe Layout. Le cercle peut devenir la part géométrique du cercle (le rayon est probablement là pour de bon!). Peut-être a-t-on besoin d'une autre classe, CircularRegion, qui serait un cercle à une position donnée

Tony Van Eerd : Essence is the essence of naming

Tony Van Eerd : discutions fonctions. Est-ce qu'un cercle devrait avoir une fonction membre draw()? Non, pas vraiment. Si on garde draw() là, on ne pourra plus aisément migrer le code de dessin vers d'autres plateformes. Une fonction libre est préférable ici. On discute un peu d'invariants...

Tony Van Eerd aborde une classe AdjacencyMatrix. Le seul invariant vraiment de cette classe est le nombre d'éléments. Il s'en sert pour faire de la coloration de graphes, mais la coloration de graphes n'a pas d'affaire dans cette classe (ce qu'on a besoin est de pouvoir connecter ou déconnecter des noeuds par exemple). Il explique la présence d'autres fonctions (p. ex. : compter les connexions) par le fait qu'à l'interne, on peut les implémenter O(n) alors que de l'extérieur elles seraient O(n^2)

Tony Van Eerd examine quelques fonctions très mal écrites. Instructif, mais je ne note pas :) Je note tout de même que ce sont souvent des fonctions non-const et void (hé la la...). Separate Calculating from Doing. Il intègre la beauté de RVO et du mouvement à ce portrait (ces choses aident la programmation par valeur). Il dit que son code maintenant retourne des vecteurs, des images et d'autres trucs « lourds » car c'est devenu essentiellement gratuit... et le code est devenu beau. Il fait des classes Move-Only maintenant

Tony Van Eerd produit un comparatif « objet » vs « valeurs » (sa définition de « objet » diffère de la mienne : ses « objets » sont des références; ils ont une identité de lieu mais pas de type) pour encourager le recours aux valeurs. Il distingue « OH, NO! POINTERS!!! » de « oh, no pointers » :)

(on a dépassé le temps alloué)

Q : comment empêche-t-on les gens de faire des classes trop grosses?

Tony Van Eerd : par des revues de code? Le pire est quand la classe est déjà grosse. Les gens continuent d'en ajouter dans ce temps-là. Quand une classe est petite, les gens sont plus prudents. Ajouter à une classe peut altérer ses fondements.

Amir Kirsh : avec ton AdjacencyMatrix, si tu passes le vector<bool> à l'interne à une fonction, tu le passes...

Tony Van Eerd ... par valeur ou par ref-vers-const, ce qui revient habituellement au même (c'est rare que l'appelé gardera une référence sur le paramètre, et s'il le fait il devrait l'annoncer haut et fort).

 Amir Kirsh : comment gères-tu les conditions de course alors?

Tony Van Eerd : si tu fais du multithreading, fais des copies! Il explique que dans Photoshop, la pile pour Undo / Redo fait des copies du document entier et ça se passe très bien

On finit 15 minutes plus tard que prévu, mais c'était bon. Du pur Tony Van Eerd. J'ai pris quelques minutes pour bavarder (c'est un bon ami) puis je suis allé chercher quelque chose à manger (petit resto libanais pas cher et très goûteux l'autre bord de la rue, mais j'ai dû me mettre en file pour une bonne quinzaine de minutes – endroit populaire! – alors j'ai dû manger rapidement).

Je m'installe dans la salle où Peter Sommerlad donnera sa présentation. J'ai hâte : pour diverses raisons, principalement des conflits d'horaire, je n'ai jamais pu profiter en personne d'une de ses présentations (peut-être une fois il y a plusieurs années) alors je suis bien content d'être là aujourd'hui, surtout que le titre de la présentation est amusant :)

Vidéo : https://www.youtube.com/watch?v=A6_EJ80SAmA

Peter Sommerlad – Vulnerable C++

Peter Sommerlad se présente. Il a droite à une plage de 90 minutes (je n'avais pas réalisé!). Il dit que des diapos, quand elles seront en ligne, contiendront les explications portant sur le contenu des diapositives.

Peter Sommerlad commence par expliquer le rôle du mot Vulnerable dans la présentation. Pour lui, il s'agit d'une propriété dynamique (Run-time Property), mais il dit que plusieurs des problèmes qui nous frappent dymaniquement pourraient être prévenus dans l'écriture du code. Il explique Undefined Behavior (UB), Implementation-Defined Behavior et Unspecified Behavior. UB peut voyager dans le temps. Il ajoute que dans les causes de vulnérabilité, il y a aussi... les malentendus (mal comprendre une API, générer une conversion non-désirée, faute de frappe, etc.)

Peter Sommerlad dit que cette semaine, c'est la première fois de sa carrière qu'il voit une véritable prise de conscience quant aux saines pratiques d'ingénierie logicielle dans la communauté. Il estime qu'avoir de bons tests unitaires est un prérequis.

Peter Sommerlad donne quatre manifestations de C++ vulnérable :

Peter Sommerlad : C++ a de bons côtés. Ça repose sur un standard ISO, on peut compiler en mode conforme ou Pedantic. On a un système de types très puissant, des durées de vie déterministes (vive '}'!), des modes de compilation où les avertissements deviennent des erreurs, des outils d'analyse statique comme dynamique... et on peut se discipliner pour éviter le « Bad Stuff ». Ce sont à ses yeux des mécanismes de résilience pour le langage. Il parlera aujourd'hui surtout du Bad Stuff

Peter Sommerlad mentionne son rôle avec WG23, MISRA, CERT et AutoSAR (on se croise là à l'occasion). La partie C++ de WG23 est disponible en ligne sur le Github de WG23. Il décrit le modèle mise de l'avant par le catalogue indépendant du langage de WG23 : description de la vulnérabilité, règles de codage associées, ce qui peut aller mal, ce que ça demande du langage pour survenir, comment éviter le problème, et conséquences pour l'évolution du langage. C++ a des vulnérabilités, mais aussi beaucoup d'outils pour prévenir les ennuis. Il présente la clause sur l'arithmétique de pointeurs, puis survole l'ensemble des clauses (incluant les enjeux de nommage trompeur)

Peter Sommerlad enchaîne avec les principaux mécanismes d.'évitement : valider les intrants, validers les extrants, activer les avertissements du compilateur, utiliser de l'analyse statique, valider les bornes, allouer et libérer les ressources au même niveau d'abstraction (une force de C++). Il prend un exemple plus en détail, soit l'enjeu de la fin des chaînes de caractères. La solution C++ est d'utiliser std::string (pas std::span ou std::strring_view qui ne garantissent pas un '\0' à la fin)

Peter Sommerlad donne des conseils généraux pour C++ :

Peter Sommerlad parle des parties C et POO de C++ comme les coins obscurs du langage (le reste est bien plus joli!)

Peter Sommerlad poursuit avec les tests de préconditions et la gestion des erreurs. Il rappelle la terminologie de Bertrand Meyer pour les contrats des fonctions : préconditions, postconditions, fautes (précondition non respectée, postcondition non atteinte) et erreurs (détection des fautes). Lors d'une erreur (donc lors d'une violation du contrat d'une fonction), on peut :

... mais il faut de prime abord avoir détecté l'erreur (ce n'est pas toujours possible). Évidemment, une autre option est de ne jamais échouer, p. ex. : une fonction identity(auto&&).

Certaines fonctions peuvent échouer dans leur tentative de réaliser leurs postconditions, dû à :

Peter Sommerlad présente ensuite la taxonomie d'erreurs de Herb Sutter, puis enchaîne avec les stratégies de traitement d'erreurs. C'est la diapo 30 (je vais peut-être prendre des idées pour mes cours, mais les retravailler pour mes étudiantes et mes étudiants). Ensuite, il fait le tour des types standards de C++ qui ont une sémantique de référence et demandent un travail plus poussé de la part des programmeuses et des programmeurs (on ne peut généralement pas raisonner localement). Il insiste sur le problème des Dangling References vers des objets sur la pile ou dans le tas.

Peter Sommerlad présente std::span et std::string_view comme des Parameter Types (c'est là qu'ils sont utilisables de manière raisonnée). Retourner des indirections est habituellement une mauvaise idée (je ne parle pas du cas du retour d'un pointeur intelligent responsable de son pointé ici). Évidemment, il y a des exceptions à la règle, p. ex. : vector<T>::operator[](). Il discute un peu de risques de concurrence mais il est (selon moi) beaucoup trop restrictif. Il montre un exemple très vilain de Dangling avec const int &n = std::max(i, 20); (piarkkk). Il survole ensuite brièvement les règles de Temporary Lifetime Extension (améliorées en partie avec C++23).

struct A { int a; const int & getA() { return a; } };
// ...
const int &ok = A{ 3 }.a; // Ok, lifetime extended
const int &dang = A{ 3 }.getA(); // dangling

Peter Sommerlad donne d'autres exemples plus élaborés (diapositives 53-54 et dans les alentours), incluant quelques monstruosités. Il aborde ensuite les ref-qualifiers sur les fonctions membres, prévues pour les opérateurs d'affectation avec C++ 11 à l'époque mais que les gens ont (tristement) oublié en chemin.

Peter Sommerlad aborde rapidement des enjeux avec les types numériques fondamentaux. C'est plein de pièges (il en liste plusieurs). Il donne plusieurs conseils pertinents pour éviter des irritants en ce sens (autour de la diapo 60, peut-être 58 ou 59). On regarde ensuite les représentations bit à bit (plein de pièges aussi). Il rappelle que plusieurs manoeuvres de Type Punning en C sont UB en C++. Il montre un cas vilain où on a un débordement sur une multiplication d'un unsigned short par lui-même (car le type du produit est un signed int)

Peter Sommerlad termine avec un résumé de ce qu'il a présenté. On est rendus au point où passer par valeur est généralement préférable à passer par ref-vers-const dans la plupart des cas. Il dit vouloir faire adopter std::optional<T&> (bonne chance!)

Levo DeLellis : pourquoi les Dead Stores sont-ils dans la liste?

Peter Sommerlad : c'est du code suspect. Dans un langage comme C++, les compilateurs les élimineront alors c'est plus ou moins un problème

Levo DeLellis : les débutants tendent à écrire des tests unitaires aussi gros que ce qui est testé. Comment les former à écrire de bons tests unitaires?

Peter Sommerlad : vous pouvez m'engager :) J'ai donné une conférence à CppCon 2019 sur le sujet.

Q : tu suggérais d'éviter de retourner de références sur des données internes, mais parfois il le faut. Peut-on envisager qualifier & les get?

Peter Sommerlad : c'est une recommandation de MISRA, mais c'est difficile à généraliser car on ne sait pas ce que les gens font avec leurs classes.

Miro Knejp : si je qualifie & un opérateur d'affectation et que je fais de mon objet une variable membre d'un autre, suis-je protégé par l'affectation de ce dernier?

Peter Sommerlad : tristement, non

(il dit que son but dans la vie est d'éradiquer le mauvais logiciel)

Intéressant, tout de même. Bref échange avec Peter Sommerlad sur ses plans pour std::optional<T>::operator=(const optional<T>&) dans le cas où T est une référence.

Par la suite, se suis allé porter une collation à mon amoureuse (Bloomberg a décidé de financer la pause café alors nous avons de mini hot-dogs et de mini-burgers avec des croustilles chaudes), puis je me suius installé pour la dernière présentation (que je ne verrai pas au complet, mais presque). Richard Powell, Timur Doumler, Kate Gregory, René Ferdinand Rivera, Tony Van Eerd, Matt Godbolt et Andreas Weis se joignent à moi et prennent des égoportraits :)

Mike Daum présente Timur Doumler.

Vidéo : à venir

Timur Doumler – Contracts, Testing, and the Pursuit of Well Defined Behaviour

Timur Doumler remercie les gens d'être restés pour sa présentation :) Il est co-Chair de SG21 (contrats) alors sa présentation portera sur ce sujet. Il parle d'entrée de jeu des pressions du gouvernement américain pour mettre de côté les langages Memory-Unsafe et de l'apport espéré des contrats pour rencontrer ces attentes. Il recommande plusieurs présentations récentes sur le sujet dont celle de JF Bastien à C++ Now et celle de Sean Parent à C++ On Sea.

Timur Doumler distingue divers types de Safety, dont le Language Safety (absence de UB), mais on trouve une dizaine de sous-catégories (C++ étant très polyvalent, il permet de contourner chacune d'entre elles).

Timur Doumler soulève ensuite la question de la nature de UB. Il met de l'avant que c'est un bogue, mais que ce n'est pas une erreur non plus. C'est un cas où le compilateur suppose des choses sur notre code et optimise en fonction de ces suppositions, mais notre code ne respecte pas ces suppositions. Il discute des conséquences possibles d'aller une case trop loin en lecture dans un tableau (le compilateur peut supposer certains trucs et transformer notre fonction en une constante) puis d'un possible cas de débordement arithmétique signé (qui transforme le code en boucle infinie). L'idée dans chaque cas est que le compilateur suppose que nous respectons les règles et optimise en conséquence

Timur Doumler dit que les tests unitaires peuvent trouver plusieurs de ces bogues. Il en va de même pour l'analyse statique, les Sanitizers, des`saines pratiques de programmation, des abstractions de plus haut niveau... et même par l'évolution du langage. On ne pourra pas tout éliminer, par contre. Alors pourquoi ne pas éliminer UB de C++ complètement? C'est possible en théorie, mais il y a des coûts en termes de vitesse, en termes de Correctness parfois (p. ex. : certains langages initialisent toutes les variables à zéro, mais ça peut masquer ou provoquer des bogues de logique, et ça empêche les outils de diagnostiquer le code), en termes de complexité, etc. Il présente les options qui se présentent à nous pour régler le problème de lecture de variables non-initialisées et examine les pour et les contre...

Timur Doumler se dit d'avis qu'être pleinement Safe n'est pas raisonnable, mais on peut le rendre Safer. On le fait d'ailleurs avec chaque version du langage (il parle de bit_cast, de création implicite d'objets, de start_lifetime_as, etc.). Il arrive enfin aux contrats (ouf!)

Timur Doumler relate l'historique du Design by Contracts à partir du langage Eiffel. Il arrive au point où on doit examiner pourquoi le UB s'infiltre dans notre code. Il y a des cas évidents, d'autres beaucoup moins, et c'est pour ces cas que les contrats sont intéressants. Il montre comment vector<T>::operator[]() peut bénéficier de cela (il se trouve que le problème est dans le code client, mais que le UB survient dans le code serveur). Il définit l'idée de précondition, mais pense que dans le contexte de C++ la définition ne suffit pas (elle ne dit pas ce qui se produit si la précondition est brisée). Il définiti les idées de Narrow Contract et de Wide Contract dans les acceptions de John Lakos et de Dave Abrahams. On fait un petit quiz et il nous apprend que v0.swap(v1) peut lever une exception si les allocateurs de v0 et de v1 ne sont pas du même type. En général, un appel hors-contrat (un bris de précondition) est UB

Timur Doumler utilise les termes (controversés) Language UB (ou Hard UB) et Library UB (ou Soft UB), mais pour indiquer que le Library UB pourrait devenir une erreur si nous introduisions des contrats. Cela réduirait le UB de manière générale. Nous avons assert() pour cela depuis longtemps, mais on veut un formalisme plus rigoureux (il montre une implémentation « maison » de ASSERT à titre d'exemple de ce qui pallie assert() dans bien des compagnies). Il parle des sémantiques de contrat envisagées (enforce, observe, ignore, ... assume, mais ce dernier est une optimisation et c'est peut-être pour plus tard – la controverse autour de assume fait partie des raisons pour le retrait des contrats de C++ 20). Il souligne qu'on a standardisé [[assume(expr)]] en C++23 et montre l'effet de cette annotation sur le code généré dans certains cas (c'est, bien sûr, dangereux)

Timur Doumler poursuit avec les types de contrats : préconditions, postconditions, assertions et invariants. Il faut que les contrats supportent toutes les combinaisons de ces sémantiques et supportent des Violation Handlers. Gros contrat (!) Il montre pourquoi les postconditions ne s'expriment pas bien avec des macros (elles doivent tenir compte des états en début de fonction et les comprarer avec les états en fin de fonction). Il montre qu'on peut exprimer les invariants comme des préconditions ET des postconditions de chaque fonction  d'une interface de même que comme postcondition des constructeurs et précondition du destructeur, mais c'est fastidieux. Il recommande Function Contratcs in Action de C++ Now ou ACCU 2023 (je ne me souviens plus lequel)

Timur Doumler parle de tests unitaires, et met de l'avant que les contrats sont complémentaires aux tests unitaires. Les deux approches ne trouvent pas les mêmes bogues. Sa présentation est intéressante (diapos dans le coin de 135+). Il insiste sur l'importance de tester nos préconditions pour voir si le code se comporte correctement dans le cas où celles-ci sont brisées. Comment faire? On peux exiger un échec d'une assertion (ça se fait mieux avec des exceptions :) ). Évidemment, si on fait des tests et on rapporte des problèmes par une levée d'exception, on ne peut plus utiliser noexcept même sur un Narrow Contract, ce qui explique le Throws: Nothing du texte du standard

(c'est une bonne présentation; je dois quitter à la diapo 158 pour aller prendre mon train)

Ce fut une excellente conférence, agréable et bien menée, et passer quelques jours avec mon amoureuse est chose rare pour moi, alors je suis fatigué mais ravi de mon expérience. Oh, et merci sincère à ma grande Marguerite et à son amoureux Simon pour avoir assuré notre transport entre la maison et la gare centrale de Montréal à la fois au départ et au retour. On vous aime fort!


Valid XHTML 1.0 Transitional

CSS Valide !