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
- Le choix du langage : une comparaison
- Construction logicielle C++
- Les dépendances : gestion, essais, échecs et solution finale
- Les principaux enseignements
- Je continue d’aimer le C++
- On embauche
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.
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 sonMakefile
; -
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 :
- respecter les licences libres, c’est avant tout éviter de mélanger des codes sources de licences et d’auteurs différents ;
- 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 avecapt 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…
Aller plus loin
- Journal à l’origine de la dépêche (395 clics)
# très intéressant, échouer vite pour réussir plus rapidement.
Posté par lhardy philippe (site web personnel, Mastodon) . É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 damaki . Évalué à 5. Dernière modification le 07 juin 2019 à 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 Sébastien Bonnefoy (site web personnel) . É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.
[^] # Re: très intéressant, échouer vite pour réussir plus rapidement.
Posté par damaki . Évalué à 2. Dernière modification le 10 juin 2019 à 08:33.
Et c'est aussi valable pour vous.
Combien de temps avez-vous travaillé avec ces sprints d'une journée ?
[^] # sprint d'un jour
Posté par Oliver (site web personnel) . É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 :
Exemples d’objectif pour la journée :
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 barmic . Évalué à 2.
Tu décris déploiement continue. C'est un Graal, mais ça n'est pas donné à tout le monde.
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).
Ç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 Anthony Jaguenaud . Évalué à 4.
Comment fais-tu dans une équipe où certains arrivent à 7h30 et d’autres à 9h30 ?
[^] # Re: sprint d'un jour
Posté par Olivier ROSET (site web personnel) . É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 Pierre Jarillon (site web personnel) . Évalué à 10. Dernière modification le 10 juin 2019 à 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 :
Créer le logiciel de gestion a eu plusieurs conséquences, en particulier :
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 sylvain_daltair . É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é).
[^] # Re: Comprendre l'utilisateur final
Posté par nlhss (site web personnel) . Évalué à 2.
[^] # Re: Comprendre l'utilisateur final
Posté par nlhss (site web personnel) . Évalué à 4.
Scientiste n'a pas la même signification en français gue scientist en anglais.
D'ailleur data scientist est un truisme, tout bon scientifique travaille avec des données.
# Python websockets
Posté par bluelambda . É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 Oliver (site web personnel) . Évalué à 3. Dernière modification le 09 juin 2019 à 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 lesasync
etawait
.Comme je disais dans mon article :
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 totof2000 . É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).
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par Guillaum (site web personnel) . Évalué à 10.
Tu parles du troll vieux comme le monde sur le typage statique versus dynamique ? Alors que tous le monde sait pertinemment quelle est la meilleure solution.
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par grim7reaper . Évalué à 5.
Le typage statique œuf course, la preuve étant que de plus en plus de langage dynamique ajoute le support pour le typage statique, l’inverse étant faux :]
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par Guillaum (site web personnel) . Évalué à 7. Dernière modification le 07 juin 2019 à 21:06.
Le typage statique étant un sur-ensemble du typage dynamique les langages statiques n'ont rien besoin de faire ;)
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par NicolasP . Évalué à 1.
Sauf quand il faut s'interfacer avec un langage à typage dynamique. Par exemple, le mot clef dynamic a été introduit dans le C# pour ça.
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par brendel . Évalué à 1.
Le auto de c++ et "dynamique" de C++ c'est un pas dans cette direction.
[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par Guillaum (site web personnel) . Évalué à 2.
Le
auto
n'est que de l'inférence de type. Pour le "dynamique" que tu cites, je ne vois pas de quoi tu parles.[^] # Re: Vous etes péniblers avec vos promotions de journal en dépèche.
Posté par Maclag . Évalué à 10.
Il y a 2 sortes de types: le type bien et le sale type.
Toutes ces histoires de langages autour, c'est juste pour exciter le racisme et la xénophobie!
--------> [ ]
# Qt ça aide bien
Posté par vpinon . É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 !
[^] # Re: Qt ça aide bien
Posté par Oliver (site web personnel) . Évalué à 2.
Merci vpinon, je ne connaissais pas Craft dont son dépôt de code source montre une forte activité du projet.
Finalement, il y a vraiment beaucoup de solutions de build et de gestionnaire de paquet dans l'écosystème C++ !
Est-ce que ce projet mériterait d'être listé sur la page Wikipédia des outils de construction logicielle ?
https://en.wikipedia.org/wiki/List_of_build_automation_software
Commentaire sous licence Creative Commons Zero CC0 1.0 Universal (Public Domain Dedication)
# Composer, pip, npm, gem, go-get et cargo, ces nouveaux SPOF des temps modernes...
Posté par Raphaël G. (site web personnel) . Évalué à 10.
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 gasche . Évalué à 9. Dernière modification le 08 juin 2019 à 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 nokomprendo (site web personnel) . Évalué à 4.
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 Amaury Bouchard (site web personnel) . É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 gasche . É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 Amaury Bouchard (site web personnel) . É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 Gof (site web personnel) . Évalué à 2. Dernière modification le 09 juin 2019 à 23:25.
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 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 Guillaum (site web personnel) . É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 gasche . É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 Guillaum (site web personnel) . É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 donk . É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 totof2000 . Évalué à 2.
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 gasche . É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.
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.
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 vitanix . É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 Yves Martin . É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 Xavier Combelle (site web personnel) . Évalué à 1.
Je pourrais être interessé par du télétravail, mais quel est donc le nom de l'entreprise ?
[^] # Re: nom de l'entreprise ?
Posté par nouknouk (site web personnel) . Évalué à 2.
un ptit indice: son adresse mail ;-)
# Hoobap a lua
Posté par Finway . Évalué à 0.
Et Lua dans tout ça ?
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.