Moi, expert C++, j’abandonne le C++

Posté par (page perso) . Édité par Ysabeau, Davy Defaud, ZeroHeure, palm123, Pierre Jarillon, Nicolas Casanova et Benoît Sibaud. Modéré par ZeroHeure. Licence CC by-sa.
Tags :
54
6
juin
2019
C et C++

Ma carrière professionnelle de développeur C a débuté en 1994 et j’ai naturellement adopté avec enthousiasme le C++ en 1999. J’étais un développeur C++ heureux et j’avais considéré la nouvelle version du standard C++11 juste comme une évolution tant attendue. En 2015, je réalise enfin à quel point, il a révolutionné l’écosystème C++ et ses bouleversements dans l’état d’esprit de la communauté. Je me passionne alors pour C++11, C++14, puis C++17, je m’implique beaucoup, je deviens un référent pour mes collègues, je donne des conférences sur ce langage, j’organise des meet‐ups à Paris, je publie de nombreux articles C++ sur LinuxFr.org

En 2018, une expérience change radicalement ma façon d’appréhender le développement logiciel.

Sommaire

Mieux développer pour les utilisateurs finaux

Comprendre le client et développer vite

En 2018, une expérience change radicalement ma façon d’appréhender le développement logiciel. À cette époque, une équipe C++ se retrouve surchargée et ne peut implémenter toutes les fonctionnalités attendues. On réfléchit à une solution de secours, et me voilà chargé de développer une application en Python en intégrant des briques sous licence libre. Je travaille alors en étroite collaboration avec les utilisateurs finaux et on sort l’application en quelques mois.

Ma nouvelle vision :

Il y a plus important que la technologie, c’est de se mettre dans la peau du client final et de comprendre ses frustrations au quotidien. Et on y arrive mieux en intégrant l’utilisateur final dans son équipe de développement.

L’application bricolée en Python donne entièrement satisfaction. Les utilisateurs sont contents d’avoir eu très tôt leur outil, et cela a coûté moins cher par rapport à toute une équipe C++ dans sa « tour d’ivoire ».

Intégrer l’utilisateur final dans son équipe

Attention, je ne dénigre pas le C++, celui‐ci peut être une bonne solution face à de nombreuses problématiques. Mais avant de courir tête baissée, s’assurer que la technologie choisie répondra bien aux attentes non exprimées de l’utilisateur final.

J’écris « attentes non exprimées » car bien souvent le développeur se base sur sa propre interprétation d’un document présenté comme LA spécification qui a en plus été rédigée par un intermédiaire (MOA, MOE, Business Analyste, Product Owner, Architecte…).

Nous l’avons peut‐être déjà tous constaté, l’utilisateur final ne sait pas vraiment ce qu’il veut, et a beaucoup de difficulté à exprimer clairement par écrit ses attentes.

Un intermédiaire (MOA, MOE, BA, PO, Archi) est nécessaire pour lui permettre de prendre du recul et pour traduire une demande fonctionnelle en exigence technique.

Mais l’intermédiaire rajoute une couche intermédiaire ! C’est humain, l’intermédiaire aura tendance à se rendre indispensable. Et sans le faire exprès, l’intermédiaire évitera que développeurs et utilisateurs échangent en direct.

Le top est d’avoir l’utilisateur final dans son équipe de développement, même si ce n’est pas dans le même bureau. Avec les habitudes de travail à distance, développeurs et utilisateur peuvent clavarder (chat) régulièrement.

Faire des sprints d’une journée

La durée idéale d’un sprint c’est la journée.

Le matin on échange rapidement avec le client de ce que l’on pourrait faire, on s’attelle à la tâche, on livre, l’utilisateur peut tester, on re‐livre… Et, en fin de journée, on débriefe très rapidement.

L’intérêt du Python (par rapport au C++) dans ce mode de fonctionnement c’est la livraison : on peut se permettre de livrer directement le code source et hop l’utilisateur exécute l’application ! Ainsi, dans mon cas, quand l’utilisateur lançait le démarrage de l’application, la branche master du dépôt Git était automatiquement mise à jour. J’essayais quand même de le prévenir quand une nouvelle version était sur la branche master.

La joie de livrer souvent, rapidement, et d’avoir du feed‐back dans la foulée. :-)

Le choix du langage : une comparaison

Le C++ ne serait donc pas la panacée ?

Nous pourrions caricaturer :

  • en C++, le développement est lent, mais l’application est très rapide ;
  • en Python, le développement est rapide, mais l’application est très lente1.

Bien souvent, le client final a besoin rapidement d’une fonctionnalité, même si l’exécution n’est pas super optimisée. En livrant rapidement cette fonctionnalité, le client gagne en maturité et a de nouvelles idées, de nouvelles façons pour optimiser son travail… et ainsi de suite avec des itérations courtes.

WebSocket en Python

Pour une application existante, nous avons besoin de fournir une interface WebSocket basique afin que nos clients puissent accéder à un service de Souscription/Publication.

Je développe la fonctionnalité en utilisant Python et Socket.io. Les tests JavaScript sont concluants. Cependant, nous nous apercevons que Socket.io rajoute son protocole par dessus le protocole WebSocket. Nous allons donc forcer les clients à devoir utiliser Socket.io ce qui n’est pas acceptable.

Nous voulons offrir une simple WebSocket afin que le client ne soit pas enfermé dans une technologie et soit libre d’implémenter son logiciel comme il le souhaite.

Je m’oriente alors vers WAMP avec Autobahn… Mais, rebelote, le P dans WAMP signifie Protocol.

Pour ne pas réinventer la roue, je cherche alors une solution qui implémente déjà la fonctionnalité Souscription/Publication et idéalement avec des coroutines (async et await).

WebSocket en C++

C’est alors que je découvre uWebSockets (µWS), une implémentation C++17 à couper le souffle qui intègre la fonctionnalité Souscription/Publication tout en conservant le protocole WebSocket de base. \o/

Mon équipe est enthousiaste. Je clone le projet, j’adapte un exemple C++ à nos besoins et je présente un résultat convainquant. C’est agréable de compiler un projet C++ qui ne tire pas des dizaines de dépendances. :-)

Je précise que pour ce nouveau projet, je viens de rejoindre une autre organisation, et j’ai été embauché, en partie, pour mes connaissances pointues en C++17.

Benchmark fait par l’équipe uWebSockets qui montre que uWebSockets est largement la solution la plus performante

La compilation C++ est archaïque

En Python, Node.js, Ruby, Go, Rust on a pip, npm, gem, go-get, cargo qui simplifie le téléchargement des dépendances, et l’intégration au projet avec un import xxxx. De plus, certains IDE prennent en charge cette gestion des dépendances.

En C++, la gestion des dépendances et leur compilation ne sont pas standardisées. En fait, cela n’a pas beaucoup évolué depuis les origines : le C++ a quarante ans et se compile toujours dans le même esprit que le C qui a lui soixante ans.

Pour cela, nous avons le choix du compilateur, dont voici une sélection avec leurs dates de naissance :

  • GCC et son g++ (GNU, libre, 1987-2019) ;
  • LLVM et son clang++ (Apple, libre, 2007-2019) ;
  • AOCC et son clang++ (AMD, libre, 2017-2018) ;
  • ICC et son icc (Intel, non libre, ????-2018) ;
  • MSVC et son cl (Microsoft, non libre, 1993-2019) ;
  • C++Builder et son bcc64 (Embarcadero, non libre, 1997-2019).

Construction logicielle C++

Pour la construction logicielle (build), nous avons une dizaine d’outils pour nous abstraire du compilateur, en voici une petite sélection sous licence libre :

  • make et son Makefile ;
  • Ninja et son build.ninja ;
  • Jam remplacé par Boost.build et leur Jamfile ;
  • SCons et sa configuration en Python ;
  • Waf qui ambitionne de remplacer SCons.

Générateurs de configuration pour la construction logicielle C++

Et pour nous abstraire de ces outils de construction logicielle, nous utilisons des générateurs de configuration de build, dont voici des projets toujours actifs :

  • Autotools génère du Makefile ;
  • CMake génère Makefile, build.ninja et les fichiers projet pour de nombreux IDE ;
  • Premake en cours de réécriture active depuis une dizaine d’années ;
  • xmake génère Makefile et les fichiers projet pour quelques IDE ;
  • Meson génère build.ninja et est compatible avec quelques IDE.

Autres outils de construction logicielle C++

Avec les outils ci‐dessus, le build et les tests de non régression d’une importante application C++ peut parfois prendre une demi‐journée.

C’est beaucoup trop pour attendre si ce que l’on a implémenté est correct !

D’autres outils de construction logicielle ont donc été développées dans le but de construire et tester en un minimum de temps :

  • Bazel codé en Java et géré/financé par Google ;
  • Buck codé en Java et géré/financé par Facebook ;
  • Pants codé en Python et géré par une communauté ;
  • Please codé en Go et géré/financé par Thought Machine.

Ces projets ne réutilisent pas les outils de build cités plus haut, et ne génèrent pas les fichiers projet des IDE.

En revanche, ces outils analysent finement le graphe de dépendance, gèrent de gros dépôts de code source, parallélisent la construction logicielle sur tous les cœurs (CPU) de nombreuses machines (cloud). Les étapes du build sont mémoïsées pour éviter de refaire la même opération N fois (par exemple, pour éviter de compiler un fichier non modifié, ou de lier une bibliothèque inchangée).

Sans avoir à recourir à ces outils, on peut améliorer les temps de compilation C++ et d’édition de liens (link) avec ces deux bons vieux outils :

  • ccache pour éviter de recompiler (ou lier) un fichier inchangé ;
  • distcc pour distribuer le build sur plusieurs machines (voir aussi icecream).

Ces outils ccache et distcc sont pris en charge par CMake, SCons, …

Les dépendances : gestion, essais, échecs et solution finale

Gestion de dépendances en C++

Mais au fait, comment gérer les dépendances C++ ? Quel est le gestionnaire de paquets C++ officiel (package manager) ? Quel est l’équivalent C++ pour les commandes pip, npm, gem, go-get et cargo ?

Eh bien… disons que nous avons des initiatives encourageantes :

  • le groupe de travail SG15 (du comité de standardisation du C++) réfléchit à une nouvelle approche pour compiler le C++ (voir leurs propositions P1482 et P1484 en anglais) ;
  • le projet build2 est très bien pensé et dont son auteur avait proposé de standardiser arborescence des projets C++ avec P1204 ;
  • le projet conan utilise une configuration en Python et propose déjà 600 paquets C++ disponibles sur les deux dépôts publics principaux (conan-central et bincrafters) ;
  • le projet vcpkg se base sur CMake et propose 1000 paquets C++ dont une bonne partie sont compatibles Windows, GNU/Linux et macOS ;
  • le projet Hunter se base également sur CMake et propose environ 300 paquets C++.

Attention à ne pas confondre l’exécutable b du projet build2 avec l’exécutable b2 du projet Boost.build cité plus haut.

Copier les dépendances dans son code source

Une autre façon de gérer très simplement ses dépendances C++ est de carrément copier le code source de celles‐ci (et aussi le code source des dépendances des dépendances) avec le code source de l’application. Ça compile toujours.

Mais ce n’est pas une bonne pratique pour, au moins, deux raisons :

  1. respecter les licences libres, c’est avant tout éviter de mélanger des codes sources de licences et d’auteurs différents ;
  2. mixer les codes source complique leur mise à jour (par exemple, comment intégrer la correction d’une faille de sécurité ?).

Microsoft me fait perdre deux jours

Je teste différents moyens pour obtenir le paquet uWebSocket : le package manager de ma distribution, Conan, Hunter… et finalement, le paquet uWebSocket a fraîchement été intégré au dépôt vcpkg. Je teste, et, ô miracle, cela télécharge le code source et me l’installe sur ma distribution GNU/Linux !

L’outil vcpkg fonctionne avec CMake, donc ce sera CMake qui gérera la construction logicielle.
Le temps de se documenter et bien prendre en main vcpkg, de tenter une intégration dans mon CMakeLists.txt, d’échouer, de recommencer…

Pourtant l’exemple avec SQLite3 fonctionne chez moi… Arg… En fait, c’est mal empaqueté, le find_package() ne pourra jamais trouver la bibliothèque uWebSocket fournie par vcpkg.

J’essaye de le faire moi‐même. Puis, je me rends compte au second jour que vcpkg est un outil amateur, à ne surtout pas utiliser pour aller en production : pas de version des dépendances, impossible de décider des options de compilation des dépendances…

Allez, on empaquette soi‐même cette bibliothèque

Bon, je connais bien C++, alors empaqueter proprement une bibliothèque qui ne dépend de rien ne devrait pas poser problème. Je retrousse mes manches et je commence à chercher si quelqu’un a déjà empaqueté uWebSockets…

Je trouve surtout que le mainteneur principal a supprimé les fichiers CMakeLists.txt et meson.build en 2017.

Et celui‐ci semble envoyer bouler les contributeurs proposant la compatibilité avec CMake, supprime le titre des pull requests et on trouve même des commentaires supprimés.

On trouve une explication dans la FAQ :

I don’t accept any specific build systems because I know from experience that doing so opens up hell. People simply cannot agree on which build system to use, or even how to use one particular build system.

That’s why I no longer accept any such PRs. I’ve had too many CMake PRs dragging in completely different directions to know this is the only solution.

You’ll have to clone the repo and create a new project in whatever build system you want to use.

En gros, le mainteneur principal refuse tout système de construction logicielle, car les développeurs veulent utiliser différents outils et que pour un même outil, les développeurs ne se mettent pas d’accord sur la bonne façon de faire.

Un commit très étonnant est le « Not my problem » qui change la licence et remplace dans tous les fichiers la ligne :

Copyright 2018 Alex Hultman and contributors.
par :
Authored by Alex Hultman, 2018-2019.
Intellectual property of third-party.

CMake gagne, Meson rentre à la maison

Mon IDE préféré pour le C++ est QtCreator, mais celui‐ci ne prend pas encore en charge Meson. Et je n’ai plus beaucoup de temps pour prendre en main GNOME Builder.

Et j’obtiens un joli CMakeLists.txt qui fonctionne sur deux différentes distributions GNU/Linux et aussi sur GitLab.

Je me rends aussi compte que GCC 8 ne compile pas cette bibliothèque, et que nous devons utiliser seulement Clang.

Mais, mon plus gros problème est que je n’arrive plus à faire compiler cette bibliothèque par QtCreator, alors qu’avec la ligne de commande cela fonctionne parfaitement… Argh… J’investis encore du temps…

Échec C++

Mes collègues ne comprennent pas pourquoi je mets autant de temps pour faire l’équivalent d’un pip install en C++. De plus, je vais devoir refaire ce même travail dès que j’intégrerai les autres bibliothèques : base de données, file d’attente de messages, journalisation

Nous décidons ensemble d’arrêter de s’obstiner, de relever la tête, et de lister les possibilités :

  • continuer l’intégration de uWebSockets avec CMake ;
  • utiliser seulement les paquets Conan ou Hunter comme boost::beast pour la websocket (c’est même disponible avec apt install) ;
  • revenir sur le Python et implémenter la Souscription/Publication ;
  • passer sur Node.js et intégrer la bibliothèque C++ uWebSockets avec la simplicité de npm (uWebSockets.js) ;
  • prendre le virage Rust, seul rival au C++ avec la simplicité de cargo ;
  • Go to the langage Go qui est simple comme Python et est une des technos les plus performantes.

WebSocket en Node.js

J’ai plusieurs collègues très compétents en Node.js, alors c’est parti. Effectivement, l’installation de la dépendance est très simple et on implémente rapidement l’application.

Le grand avantage de Node.js (et de JavaScript en général) est la taille de la communauté et l’esprit de partage et d’innovation incroyables. Alors qu’une décennie est nécessaire en C++ pour se décider, la communauté JavaScript décide en quelques mois. Les projets, les concepts de programmation, les méthodes de travailler ne cessent d’évoluer.

J’entre dans un vaisseau qui se déplace à la vitesse de la lumière. En C++, la durée de vie d’un projet peut être d’une dizaine d’années. En Node.js, c’est plutôt dix mois. C’est aussi l’inconvénient, il faut s’adapter vite.

Mais, nous nous apercevons que le projet uWebSockets.js ne prend pas en charge la Souscription/Publication de la bibliothèque sous‐jacente uWebSockets. Ça ne marche pas.

Stop, nous venons de gagner en maturité, voyons voir les possibilités :

  • Node.js (implémenter la Souscription/Publication en JavaScript…) ;
  • Rust ;
  • Go.

Les principaux enseignements

WebSocket en Go

Nous prenons conscience que la partie WebSocket risque d’être un point sensible au niveau performance. Finalement, nous mettons entre parenthèses notre tentative Node.js.

Le Rust est encore trop jeune (peu de développeurs maîtrisant Rust sur le marché). Et nous avons un collègue devops fan du Go.

Notre collègue maîtrisant Go n’étant pas très disponible, on apprend se débrouille seul. Finalement, le principal du langage Go s’acquiert en quelques heures de programmation. Le test WebSocket est un succès et nous implémentons une première version basique de la publication/souscription en Go.

Nous mettrons en place des tests de performance reproductibles, et seulement après nous pourrons décider quelles sont les parties qui nécessitent d’être optimisées.

Valoriser l’échec

  • C’est grâce à nos échecs successifs que nous avons pu trouver notre solution pour les WebSockets ;
  • nous aurions pu décider qu’il fallait éviter les échecs ;
  • mais nous avons plutôt cherché à nous planter car l’échec est un très bon moyen d’apprendre (de ses erreurs) ;
  • se planter plus rapidement/souvent permet donc d’apprendre plus vite ou souvent ;
  • donc, essayons d’augmenter nos échecs (car c’est augmenter notre apprentissage) ;
  • pour encourager à tester une idée, nous devons valoriser l’échec ;
  • tester simplement/rapidement une idée permet de gagner en maturité.

Enseignements sur les langages

  • Ce n’est pas une bonne idée de coder dans son langage de programmation (C++) ; quand on est le seul dév. de l’organisation qui connaisse ce langage ;
  • JavaScript et Node.js ça décoiffe ;
  • Go c’est vraiment simple (car c’est limité).

Louanges sur la simplicité

  • La simplicité permet de se concentrer sur l’essentiel ;
  • faire simple est souvent compliqué ;
  • avoir une IT simple permet d’intégrer de nouvelles contraintes et idées plus facilement ;
  • dans un monde de plus en plus concurrentiel et qui s’accélère, la simplicité évite de se perdre dans le brouillard.

Je continue d’aimer le C++

Mais, non, je n’abandonne pas le C++ !

J’apprécie d’acquérir de nouvelles cordes à mon arc, de m’ouvrir l’esprit sur de nouvelles pratiques. Certaines technologies sont plus adaptées à certains contextes. N’ayons pas de dogme, choisissons la bonne technologie selon la situation.

Cependant, je ne sais pas quand je coderai à nouveau en C++… Peut‐être quand on aura un C++ package manager standardisé… :-)

On embauche

Un peu de publicité… Tu apprécies cet état d’esprit et que tu aimes coder en Python, Node.js, JavaScript/TypeScript/Angular ou Go ? N’hésite pas à me contacter sur oli (à) Lmap (point) org. Nous avons des postes à Paris et à Metz. On peut s’arranger pour le télétravail. Pour le moment, on ne publie rien sous licence libre. Mais je pousse pour libérer quelques briques intéressantes…


  1. Utiliser Pythran, PyPy, Cython, Numba, etc. accélère l’exécution, mais cela ralentit le développement : compilation plus lente, développement plus complexe, bogue difficile à investiguer… 

Aller plus loin

  • # très intéressant, échouer vite pour réussir plus rapidement.

    Posté par (page perso) . Évalué à 8.

    Un partage d'expérience bien argumenté et avec beaucoup de références, merci.

    Le coup du sprint de un jour m'a pris par surprise dans le récit.

    Une des difficulté avec la pratique de 'échouer vite' c'est d'arriver à déterminer que l'on a échoué, car il est toujours possible de transformer en échec en quelquechose qui fonctionne en fermant les yeux sur les efforts et les moyens.

    • [^] # Re: très intéressant, échouer vite pour réussir plus rapidement.

      Posté par . Évalué à 5. Dernière modification le 07/06/19 à 09:31.

      Je suis aussi surpris par le sprint en un jour. Je suis toujours sceptique sur la validité de cette approche sur la durée. En effet, le but du concept de sprint, c'est qu'on ait une unité de travail répétable indéfiniment sans épuiser les équipes. C'est pour ça qu'un sprint originel, c'était :
      - préparation et chiffrage des stories (certains le font d'avance)
      - présentation des stories et engagement
      - le taf du sprint, finir les stories rapidement sans trop de parallélisme
      - démo
      - rétro
      - SLACK, une demie journée voire plus au rythme zen. On fait ce qu'on veut de ce temps, mais en générale, on fait des mini-tâches techniques tranquillement, des refactorings, etc…

      En passant, je sais bien que le slack a été éliminé dans SCRUM, la méthode agile la plus populaire, mais c'est un des points les plus importants pour un rythme soutenable. Car oui, quand le rythme n'est pas soutenable, c'est la première pratique agile qui saute.

      Je peine donc à comprendre comment tu cases ça dans une journée, slack compris et à tenir un rythme sain et soutenable. Alors j'ai un biais, car je bosse depuis 10 ans sur des projets majoritairement backend et quasi indécoupables en micro stories, néanmoins, j'ai déjà testé les sprints de 7 jours avec des mini stories ; c'était juste l'enfer. C'était épuisant et on a du stopper. CQFD.

      • [^] # Re: très intéressant, échouer vite pour réussir plus rapidement.

        Posté par (page perso) . Évalué à 2.

        Je crois effectivement qu'un rythme soutenable est indispensable et que sinon l'équipe va au case pipe… Mais des sprints très courts ne sont pas forcément incompatibles.
        Ce n'est pas parce-que cela n'a pas marché pour toi que forcément c'est impossible. Il y a beaucoup de facteurs qui peuvent participer, la dynamique de l'équipe, le contexte technique, la proximité et l'implication de client, la culture de l'entreprise…
        C'est toujours un peu hasardeux de tirer des conclusions générales à partir d'un seul exemple.

      • [^] # sprint d'un jour

        Posté par (page perso) . Évalué à 3.

        Quand on fait des sprints d’un jour, on s’organise très différemment : on ne cherche pas à caser dans la journée toutes les réunions d’un sprint traditionnel de quelques semaines. Le sprint d’un jour est bien plus souple :-)

        Un exemple :

        • le matin, un clavardage (chat) avec les différents acteurs (dont un ou des utilisateurs finaux) pour se fixer le ou les objectifs de la journée ;
        • à chaque commit, un test est exécuté et si aucune régression n’est trouvée, c’est publié directement à un ou des utilisateurs ;
        • le ou les utilisateurs finaux peuvent vérifier la nouvelle version ;
        • à n’importe quel moment, développeurs et utilisateurs peuvent s’appeler ou clavarder pour éclaircir un aspect selon leurs disponibilités ;
        • en fin de journée, un dernier clavardage permet de faire un débriefing de la journée, si besoin on prévoit une réunion plus formelle pour résoudre une problématique plus complexe.

        Exemples d’objectif pour la journée :

        • un dév. réécrit une partie du code afin de simplifier les développements futurs
        • un utilisateur réfléchit à un test complet de bout en bout (end to end) à destination de l’intégration continue
        • un dév. investigue un bogue avec l’aide d’un utilisateur final
        • un utilisateur final met à jour le manuel d’utilisation

        Je rajoute un autre aspect qui ne fait pas partie du sprint d’un jour :

        Idéalement, on travaille dans un esprit de respect des uns vers les autres.
        Personne ne ressent d’intimidation ou de l’hésitation quand il/elle s’exprime.
        Chacun dit ce qu’il/elle pense être utile au projet.
        Et personne ne bloque l’idée d’un(e) autre.
        Ainsi personne n’est obligée de faire un truc en sous-marin.

        Dans le sprint d’un jour, c’est difficile de travailler en sous-marin, donc il faut absolument adopter pleinement le respect mutuel.

        On peut décider unilatéralement d’abandonner son objectif de la journée pour aider un collègue qui rencontre une difficulté, ou car on n’est plus convaincu de la pertinence de l’objectif… À côté de l’objectif principal, chacun peut librement s’atteler à d’autres tâches, en toute transparence avec l’équipe (d’où l’importance du respect mutuel).

        Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)

        • [^] # Re: sprint d'un jour

          Posté par . Évalué à 2.

          Tu décris déploiement continue. C'est un Graal, mais ça n'est pas donné à tout le monde.

          Personne ne ressent d’intimidation ou de l’hésitation quand il/elle s’exprime.
          Chacun dit ce qu’il/elle pense être utile au projet.
          Et personne ne bloque l’idée d’un(e) autre.

          C'est un point rarement vu dans l'agilité mais c'est très important. C'est le psychological safety. C'est super intéressant, mais ça ne se décrète pas. Les turnovers et la méthode d'embauche peuvent être importante (par exemple impliquer l'équipe dans le processus d'embauche).

          en fin de journée, un dernier clavardage permet de faire un débriefing de la journée, si besoin on prévoit une réunion plus formelle pour résoudre une problématique plus complexe.

          Ça me paraît compliqué à tenir. J'aurais peur que des retro trop informels (et trop régulière) empêchent de se poser, regarder en arrière, avoir du recul et que ça devienne du aussi vite terminé aussi vite parti (d'autant plus quand c'est en fin de journée…). J'insiste, je ne dis pas que ça ne marche pas, juste que c'est ce dont j'aurais peur.

        • [^] # Re: sprint d'un jour

          Posté par . Évalué à 4.

          Comment fais-tu dans une équipe où certains arrivent à 7h30 et d’autres à 9h30 ?

          • [^] # Re: sprint d'un jour

            Posté par (page perso) . Évalué à 1.

            Ben, on fixe une heure limite de réunion, ceux qui ne sont pas là à temps, tant pis. :)

            À un moment il faut avancer, non ?

            Quitte à fixer la réunion à 9h30. :)

            Et puis, on peut enregistrer la session de clavardage et la publier sur un wiki. Les retardataires peuvent ensuite la consulter.

  • # Intégrer l’utilisateur final

    Posté par (page perso) . Évalué à 10. Dernière modification le 10/06/19 à 00:06.

    C'est un point sur lequel je suis complètement d'accord, d'autant plus que je l'ai pratiqué.
    J'ai fait sans le savoir de la méthode Agile à partir de 1980. Je m'étais aperçu que les spécifications qu'on m'avait données n'en étaient pas et qu'elles avaient été faites par quelqu'un qui ne connaissait pas le travail des personnes qui devaient utiliser le logiciel.

    Heureusement, je connaissais bien le métier des utilisateurs et j'ai réussi à faire une application qui leur a très vite rendu service. Ces utilisateurs étaient les méthodes de contrôle qui déterminaient ce qu'il fallait contrôler et les inspecteurs qui faisaient les relevés.
    Il fallait faire une arborescence de documents que l'on validait, que l'on remplissait et que l'on acceptait. J'ai découvert que le contrôle qualité faisait intervenir plus de 300 règles plus ou moins écrites dans un fatras de documents. Quelques exemples :

    • pour qu'un produit soit accepté, il faut que tous ses constituants le soient aussi.
    • la date d'acceptation d'un produit est postérieure à la date d'acceptation de tous ses constituants.
    • Une valeur hors tolérances ne peut être acceptée qu si elle est couverte par une dérogation acceptée.

    Créer le logiciel de gestion a eu plusieurs conséquences, en particulier :

    • Stabilisation des règles de gestion qui variaient selon les sites et les services.
    • Les chefs ne voyaient plus passer les documents dans les corbeilles. Leur utilité a été réduite.
    • La chasse aux documents a été supprimée. Elle était dévoreuse de temps.
    • Les inspecteurs ont travaillé avec beaucoup plus de sérénité.

    J'ai eu aussi à batailler pour supprimer des règles qui étaient faites pour gérer du papier. La gestion des versions des documents types avec l'informatique est beaucoup plus précise et il n'était pas utile de lui superposer l'imitation de la gestion du papier.

    Le logiciel a changé la façon de travailler des opérateurs.

    On sait vérifier qu'un logiciel est conforme aux spécifications (et au cahier des charges), mais il n'existe pas de méthodologie qui permette de vérifier que les spécifications sont conformes au besoin, surtout que le besoin évolue avec la mise en place du logiciel. Il y a eu une convergence vers un état final que personne n'était capable de définir au départ. Même si il avait été possible de le définir, les opérateurs n'auraient pas suivi, leur hiérarchie non plus !

  • # Comprendre l'utilisateur final

    Posté par . Évalué à 4.

    Après être devenu ingénieur en informatique j'ai suivi une autre formation métier. Je suis devenu actuaire. Je pense que ton raisonnement va dans le bon sens mais pas assez loin.

    Voici les deux points principaux de ma réflexion :
    • C’est une erreur d’évaluer un développeur sur le langage de programmation. S’il a les bases en architecture IT, en réseau, sur le fonctionnement d’un PC et les concepts de programmation (ce qui n’est pas toujours le cas) il peut être opérationnel sur un nouveau langage en moins d’une semaine.
    • Tous les métiers de l’IT (allant du développeur au data scientiste) ont pour métier de traiter une donnée ou une information. Pour bien faire ce traitement il faut bien comprendre la donnée. Il est donc important pour un ingénieur IT de se spécialiser dans un secteur d’activité et ainsi avoir les connaissances nécessaires pour comprendre les besoins métier. Il faut bien réaliser que connaître un secteur demande plusieurs années, c’est donc un élément essentiel du CV (qui n’est malheureusement presque jamais regardé).

  • # Python websockets

    Posté par . Évalué à 5.

    Salut,

    je ne suis pas expert Python (loin de là), mais j'ai déjà il y a longtemps utilisé les websockets en Python, pour concevoir une extension Firefox qui communiquait avec un serveur, avec des événements poussés vers l'extension par ce biais.

    J'ai ressorti mon code, j'avais utilisé 'websockets'.
    Voir websockets: Getting started.
    Quel était le problème avec ce module dans le cadre de votre projet?

    • [^] # Re: Python websockets

      Posté par (page perso) . Évalué à 3. Dernière modification le 09/06/19 à 17:36.

      Bonjour Bluelambda,

      Effectivement, le module Python websockets continue d’évoluer au point de nécessiter les dernières versions de Python, notamment en utilisant les async et await.

      Comme je disais dans mon article :

      Pour ne pas réinventer la roue, je cherche alors une solution qui implémente déjà la fonctionnalité Souscription/Publication […]

      Par exemple, l’implémentation websocket du projet Python Socket. IO gère la Souscription/Publication avec une notion de rentrer dans une pièce (souscrire) et sortir d’une pièce (dé-souscrire).

      Un autre exemple, wampy est une des implémentations websocket qui respecte le standard WAMP et qui propose également la fonctionnalité Souscription/Publication.

      Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)

  • # Vous etes péniblers avec vos promotions de journal en dépèche.

    Posté par . Évalué à 10.

    Vous pourriez ammener les commentaires avec, c'est pénible de scinder les discussions comme ça (d'autant plus que les discussions qui en ont suivi ont été très intéressantes).

  • # Qt ça aide bien

    Posté par . Évalué à 7.

    Un jour en marge de mon boulot j'ai cherché à faire l'inverse de websockify (bridge TCP vers WebSocket), cet outil étant en python je suis d'abord parti de ce code… et je ne m'en suis pas sorti, car pour éviter les dépendances il recode le protocole, mais juste ce qu'il lui faut.
    Alors j'ai cherché dans d'autres implémentations, j'ai même essayé du perl !
    Et puis j'ai dégaîné Qt, auquel je suis un peu plus habitué, et en 15 lignes j'avais mon outil qui marche, et il tourne depuis plusieurs années maintenant.

    Issu de la communauté KDE, si je cherche quelque chose qui n'est pas encore dans Qt & KF5, je fais un tour sur inqlude et normalement ça s'intègre bien.
    Et comme gestionnaire de paquet, "fatalement" je suis passé à Craft, et même si j'ai dû participer à pas mal d'empaquetage je suis bien content !

  • # Composer, pip, npm, gem, go-get et cargo, ces nouveaux SPOF des temps modernes...

    Posté par (page perso) . Évalué à 10.

    En Python, Node.js, Ruby, Go, Rust on a pip, npm, gem, go-get, cargo qui simplifie le téléchargement des dépendances, et l’intégration au projet avec un import xxxx. De plus, certains IDE prennent en charge cette gestion des dépendances.

    Tu nous cites ça comme de super outil, j'ai une autre vision de la chose.

    Ces outils dépendent d'un site internet (piratable), qui va tirer tout un tas de dépendances sans aucun contrôle de ta part.

    Il y a déjà eu des exemples où un type t'explique qu'il a ajouté une porte dérobée dans une super librairie de coloration utilisée par plein de monde.

    Un système de packaging qui marche, c'est celui de ta distribution ou faut pas hésiter à remonter un patch.

    urpmi lib(64)machin(_version)-devel ou yum install lib(64)machin-dev(el?) ou apt-get install lib(64)machin-dev

    Comme ça, tu as un suivi de dépendance, la livraison de correctifs de sécurité si le contributeur fait sa veille correctement et le reste. Modulo une compatibilité d'abi de mémoire, tout ça…

    Tout ça c'est sans compter sur les temps de déploiement.

    Si on prends un exemple PHP, comme cette bouse de composer.

    Quand tu veux déployer ton projet, il faut que le site liant projet et adresse de dépôt fonctionne, que TOUS les dépôts git répondent et seulement à la fin ton projet sera prêt à être déployé.

    Pour avoir codé une version Perl pour déployer du symfony en prod sans passé par composer, mon code faisait le déploiement en une trentaine de secondes modulo les temps de réponse des dépôts, composer de son côté c'était minimum 5 minutes…

    Pour résumer, ces nouveaux outils de gestion de dépendance de nouveaux langages, c'est des catastrophes, codées par des développeurs qui n'ont pas trempé dans la gestion de dépendance des distribution linux. Ils ré-inventent très souvent la roue en codant avec les pieds (et/ou en dépit du bon sens), ajoute une passoire niveau sécurité et des gros SPOF (single point of failure ou point unique de défaillance).

    Donc se mettre une dépendance sur ces bouses quand c'est pour un projet perso, pourquoi pas.

    Dépendre d'un truc pas fiable quand on a un client à livrer en temps contraint c'est une connerie.

    Packager la librairie dans ta distribution t'aurait pris beaucoup moins de temps que ça au final et ça ne t'exploses pas à la figure au moment où tu dois livrer un correctif en urgence ou de sécurité.

    • [^] # Re: Composer, pip, npm, gem, go-get et cargo, ces nouveaux SPOF des temps modernes...

      Posté par . Évalué à 9. Dernière modification le 08/06/19 à 17:25.

      Sauf que créer un paquet npm (ou pip, gem, etc.) me permet de déployer mon code chez des gens qui utilisent n'importe quelle distribution, pas seulement la mienne. C'est autrement plus facile que d'écrire un paquet pour chaque empaqueteur Linux, OSX et BSD.

      Les gestionnaires de paquets spécifiques à une communauté ont des défauts et aussi des avantages. Pour les gens qui attachent plus d'importance à l'appartenance à cette communauté qu'à leur utilisation d'une distribution spécifique, ils sont clairement avantageux. Pour des gens qui utilisent ces travaux communautaires comme un paquet parmi d'autre au sein d'un système donné, ils sont clairement moins commodes qu'un empaquetage de distribution.
      Je trouve un peu triste qu'on répète ce débat à chaque fois, chaque personne donnant seulement un des points de vue ("développeur Javascript", "admin Debian", etc.), ce qui ne permet pas de comprendre la situation.

      Par ailleurs je remarques que les empaqueteurs des distributions sont très lents à réagir à de nouveaux besoins. Les développeurs sont très clairs sur le fait qu'ils ont besoin de travailler sur plusieurs projets qui vont utiliser chacun une version différente d'un paquet donné. Quels sont les gestionnaires de distributions qui permettent ça facilement ? À ma connaissance il n'y a que Nix et Guix qui font un bon boulot là-dessus, alors que pourtant c'est un besoin qui est apparu il y a des années. C'est bien beau de venir ensuite faire la morale "non mais les gestionnaires paquage-spécifique c'est puéril, il suffit d'utiliser Rpm/Deb/whatever".

      • [^] # Re: Composer, pip, npm, gem, go-get et cargo, ces nouveaux SPOF des temps modernes...

        Posté par (page perso) . Évalué à 4.

        Les développeurs sont très clairs sur le fait qu'ils ont besoin de travailler sur plusieurs projets qui vont utiliser chacun une version différente d'un paquet donné. Quels sont les gestionnaires de distributions qui permettent ça facilement ? À ma connaissance il n'y a que Nix et Guix qui font un bon boulot là-dessus, alors que pourtant c'est un besoin qui est apparu il y a des années.

        Complètement d'accord. Nix est très pratique pour configurer et déployer un projet C++ ou Python (ou les deux en même temps). Malheureusement, Nix demande un certain effort d'apprentissage et manque sérieusement de buzz comparé à des outils comme flatpak. Et je doute que Guix devienne beaucoup plus populaire, surtout avec sa volonté d'être 100% libre et le choix de guile comme langage de packaging.

  • # Petite erreur

    Posté par (page perso) . Évalué à 4.

    Ce retour d'expérience est vraiment très intéressant, aussi bien pour les aspects techniques qu'organisationnels.

    J'ai juste relevé une petite erreur, induite je pense par l'excès d'enthousiasme :
    le C++ a quarante ans et se compile toujours dans le même esprit que le C qui a lui soixante ans

    Autant on peut arrondir à 40 ans pour le C++ (37 ans en fait), autant c'est vieillir le C d'une quinzaine d'années (créé en 1972 mais stabilisé vers 1978).
    Et je pense qu'on ne compilait pas dans les années 70 de la même manière que maintenant (make est apparu en 1977, et j'imagine que ça a pris du temps avant qu'il ne se répande).

    Encore merci pour l'article. Personnellement, je préfère le C quand je veux m'éloigner des langages interprétés (et je ne suis pas le seul, comme je l'écrivais sur mon blog il y a quelques années). La simplicité extrême du langage, la sensation de puissance… Comme le dit Ben Klemens (auteur du livre 21st Century C), le C c'est le langage punk :)

    • [^] # Re: Petite erreur

      Posté par . Évalué à 7.

      C est aussi le langage des "comportements indéfinis", où personne n'est d'accord sur ce que devrait faire un programme et en fait tous les programmes sont faux (n'ont pas de sémantique définie) (en tout cas presque tous, surtout les programmes qui utilisent du multi-threading). Utiliser C pour un nouveau projet aujourd'hui, pour moi c'est irresponsable du point de vue de la correction et de la sécurité.

      • [^] # Re: Petite erreur

        Posté par (page perso) . Évalué à 5.

        Question de point de vue. Il y a tellement de logiciels écrits en C qui te prouvent le contraire…
        Encore une fois, si tu sais ce que tu fais et que tu utilises les bons outils, le C est à la fois simple et puissant.

        Mais bon, on s'éloigne du sujet (et c'est de la bonne matière à troll, tout ça).

        • [^] # Re: Petite erreur

          Posté par (page perso) . Évalué à 2. Dernière modification le 09/06/19 à 23:25.

          Il y a tellement de logiciels écrits en C qui te prouvent le contraire…

          Argumentum ad populum mais qui ne prouve rien du tout, car il y a aussi tellement de logiciels écrit en C++, et en PHP

          le C est à la fois simple et puissant.

          Le C n'est ni simple (gestion de la mémoire manuelle, undefined behaviour, …) Ni puissant (pas de destructeurs, pas de templates, …)

      • [^] # Re: Petite erreur

        Posté par (page perso) . Évalué à 2.

        99% d'accord avec toi. Le % qui manque c'est parce que C11 apporte, il me semble, le support du multi-threading. (i.e. une sémantique pour le modèle de concurrence).

        • [^] # Re: Petite erreur

          Posté par . Évalué à 3.

          Peu de gens comprennent vraiment le modèle mémoire des atomiques de C11 (les concepteurs du standard ont voulu faire plus fin et plus optimisé que celui Java, et donc pendant longtemps on n'a pas su si le modèle était raisonnable/correct), et parmi les gens qui le comprennent vraiment il y en a peu qui écrivent des programmes en C. Du coup pour les programmes multi-threadés, la plupart n'utilise pas les atomiques de C11 (typiquement le noyau Linux qui avait ses propres macros pour insérer des barrières), et la plupart de ceux qui les utilisent sont quand même indéfinis. En tant que simple mortel il faut vraiment être très strict, et ne pas descendre en-desous de release/acquire, pour ne pas se planter.

          • [^] # Re: Petite erreur

            Posté par (page perso) . Évalué à 2.

            C'est un autre probléme ;) Mais je suis d'accord avec toi.

            Je me rappel lisant avec intérêt la spec sur le modèle mémoire. Avoir l'impression de comprendre quelque chose, implémenter, utiliser des contraintes relachée pour "plus de performance", être satisfait du résultat et me prendre une claque dans les dents 3 mois plus tard.

            Surtout que on a la mauvaise tendance à implémenter / expérimenter sur x86_64 qui a nativement un modèle de mémoire différent d'arm et que certaines suppositions sur l'un ne sont pas valables sur l'autre.

            Bref, ce truc c'est complexe.

      • [^] # Re: Petite erreur

        Posté par . Évalué à 4.

        Pourtant l'OS le plus utilisé sur la planète est écrit en C, toute l'infrastructure de l'internet (serveur web, mail, routeur…) a été construite grâce au C.
        Le langage n'a rien à voir avec la qualité du soft. Une mauvaise architecture, un mauvais développeur donnera du code non secure et buggué quelque soit le langage.
        C'est une illusion de croire que le dernier langage à la mode protège des failles de sécurité et des bugs.

        • [^] # Re: Petite erreur

          Posté par . Évalué à 2.

          C'est une illusion de croire que le dernier langage à la mode protège des failles de sécurité et des bugs.

          Je ne pense pas que ce soit le message qui passe, et dans l'absolu je suis d'accord avec toi. Cependant il y a des langages qui permettent d'éviter certains types de bugs que l'on a pu rencontrer dans tout les exemples que tu as cité. Ca filtre déjà pas al de choses.

        • [^] # Re: Petite erreur

          Posté par . Évalué à 3.

          Les OS les plus utilisés sont écrits dans des langages non-sûrs (C et C++) et d'ailleurs ils sont bourrés de failles, comme les logiciels qui font l'infrastructure internet. Ça fait des décennies que des centaines voire milliers de gens sont payés pour réagir au quart de tour à la dernière faille de type "buffer overflow" trouvée dans un logiciel critique, tout ça parce que tout ce logiciel est écrit dans un langage où la grande majorité des erreurs de programmation permettent à un attaquant malicieux d'exécuter du code arbitraire. On a collectivement investi des milliers d'années de travail, de l'argent par million, pour gérer les conséquences de ces choix désastreux (même si c'était moins visible à l'époque où ils ont été faits) de construire toute notre infrastructure sur des langages fortement peu sûrs.

          Le langage n'a rien à voir avec la qualité du soft. Une mauvaise architecture, un mauvais développeur donnera du code non secure et buggué quelque soit le langage.

          Buggué, sans doute—même s'il existe des langages qui permettent d'exprimer son besoin plus clairement et donc d'avoir moins de bugs. Mais tous les bugs ne deviennent pas automatiquement des énormes failles de sécurité. Par exemple, si tu as un parseur d'un format binaire quelconque écrit en C, la plupart des erreurs de programmation permettent à un attaquant qui fournit un binaire malicieux d'exécuter du code (d'où l'exemple de prise de contrôle d'une voiture en insérant un CD audio bien choisi; il y a une erreur d'architecture dans le système, mais aussi un langage non-sûr qui permet de l'exploiter très facilement). On n'a pas du tout le même problème si on écrit le même parseur en Java, Ada, OCaml, WebAssembly, ou n'importe quel autre langage qui garantit la sûreté mémoire par défaut.

          C'est une illusion de croire que le dernier langage à la mode protège des failles de sécurité et des bugs.

          Un langage qui garantit que tous les accès à un tableau sont vérifiés pour leur validité protège des failles de sécurité lié à un accès arbitraire en mémoire—si l'implémentation du langage et le matériel dessous sont corrects. Tous les langages à la modes ne donnent pas forcément de bonnes garanties—mais en fait aujourd'hui presque tous les langages donnent de meilleures garanties que C.

          (Certains langages dynamiques introduisent des problèmes de sécurité qui n'existent pas avec C, en permettant à chaque bibliothèque d'aller redéfinir n'importe quel autre symbole visible par l'utilisateur ou presque.)

  • # Java et Maven

    Posté par . Évalué à 2.

    Bonjour,
    Moi je l'aurais fait en Java 8/Maven avec l'api standard des Web socket. Voici un tutoriel :
    tutoriel

    • [^] # Re: Java et Maven

      Posté par . Évalué à 1.

      Pourquoi pas, mais je trouve que c'est encore trop de travail.

      Pour un système de billeterie avec point de vente, on codait les services REST en Java et le client en JS/Angular.

      Pour une communication supplémentaire (dans le sens, introduite après architecture) entre l'interface "vendeur" et une tablette d'affichage et de saisie destinée au "client", on a vite fait le choix du WebSocket avec un protocole d'échange de messages texte très simple.

      On avait déjà ActiveMQ pour assurer du traitement asynchrone en JMS, alors ajouter le support WebSocket s'est limité à créer une queue par POS dans ActiveMQ… le plus long a été de passer en SSL à travers un reverse-proxy. Quantité de code spécifique ajouté au projet, proche de zéro. On a juste sélectionné un client WebSocket en JS.

      Évidemment ce n'est pas comparable en terme de performance, tout dépend des objectifs - mais je pense que la conclusion est la même: répondre le plus rapidement possible au besoin avec les compétences de l'équipe.

      Et je pense malheureusement que le C++ n'offre pas le cadre initial qui permet de le faire.

      Dans ma boîte, on fait essentiellement du Java et du C# mais l'incontournable JS et son écosystème "mouvant" nous pose un problème d'efficacité, de rentabilité et de maintenance à long terme - dans notre contexte de développement sur-mesure (durée de vie > 5 ans), il est difficile de financer à nouveau une "mise à jour" (par exemple après 2 ans) de frontend JS (en général de complexité moyenne à élevée) quasiment au même prix que sa conception initiale… Bref si possible, on préfère fournir une application de bureau en JavaFX ou WPF.

  • # nom de l'entreprise ?

    Posté par (page perso) . Évalué à 1.

    Je pourrais être interessé par du télétravail, mais quel est donc le nom de l'entreprise ?

  • # Hoobap a lua

    Posté par . Évalué à 0.

    Et Lua dans tout ça ?

Suivre le flux des commentaires

Note : les commentaires appartiennent à ceux qui les ont postés. Nous n'en sommes pas responsables.