Journal La ronde (boucle?) des langages

Posté par  (site web personnel, Mastodon) . Licence CC By‑SA.
20
13
mar.
2018

Bonjour Nal,

Voilà plus de 30 ans que je programme et plus de 20 ans que c'est mon métier. J'ai passé par pas mal de langages, au gré des demandes, des impératifs et des modes (Je ne mets pas de liste, de peur d'en oublier!).

Pour la première fois depuis près de 20 ans, je refais du C; j'ai pu convaincre que pour telle tâche, c'était le plus indiqué. Depuis j'en perds quelque cheveux mais globalement ça va bien. Le C, c'est un peu comme le vélo et je suis assez content non seulement d'en refaire, mais aussi de voir que je sais encore assez bien comment ça marche.

Et vous, chers lecteurs et amis, avez-vous effectué mille changements de langage ou êtes-vous toujours avec le même depuis toujours? Et quelles réflexions cela pose-t-il sur notre métier et sur le monde qui nous entoure?

À+

  • # Le web, mon ami

    Posté par  (site web personnel) . Évalué à 8. Dernière modification le 13 mars 2018 à 15:11.

    Vu que je travaille dans le web, je fais la ronde des langages, mais non pas au fil des ans, mais au fil des heures, avec son lot d'immaturité et déconvenue, le monde du web me tuera.

    • Mon expertise: Java (anciennement), PHP (depuis des années)
    • À côté, mais nécessaire: *SQL (si si c'est un langage à part entière)
    • Obligé à cause des autres (TM): TypeScript, JavaScript
    • De mon plein gré sur mon temps perso: Java, PHP, Python, C#

    Et j'en oublie sûrement, je suis amené parfois à intervenir sur toutes sortes de projets, toujours dans le web. Et les stacks sont tellement compliquées que de toute façon, c'est impossible sans être polyglotte.

    À noter que j'ai joué avec C, C++ et Rust aussi, mais à des fins de tests (notamment pour comparer le bytecode généré par les 3) - mais je n'ai pas un niveau assez élevé avec aucun de ces 3 là pour réellement pouvoir en profiter.

    Côté goûts:

    • Je hais: le C, le JavaScript, le Python, et tous les autres langages à typage dynamique (je sais, le C n'en est pas, mais le C est dangereux pour la santé), et encore plus ceux où le monkey patch est possible (franchement, pour tous les adorateurs de Python, désolé, mais c'est plus proche de JavaScript qu'aucun autre langage, mais on en parlera plus tard),
    • J'adore: le Rust, le PHP (c'est un biais, ça reste un langage de merde), le Java, le C#, et tous les langages à typage statique (bien que PHP moderne jouisse d'un typage fort, mais pas complètement statique car les checks sont au runtime, saloperie),
    • J'ai pas d'avis sur tous les autres.
  • # Go ou Rust côté backend, système ou embarqué

    Posté par  . Évalué à 7.

    Je code également depuis 20 ans sur une grande variété de plateformes et langages, mais Go et Rust m'impressionnent fortement bien plus que tout ce qui est arrivé depuis le C comme C++, Java, Python, C# ou Swift.

    En ce qui concerne la programmation côté backend, système et embarqué je vois bien Go et Rust régner sans partage dans les années à venir au détriment de C/C++/Python voir Java. Typescript va rafler la mise côté Browser. Pour le reste il restera toujours des langages de niches ou académiques comme R, Erlang, Prolog et autre. Je me demande même si Rust ne finira pas par éclipser Go lorsqu'il sera mûr (encore 2 ans de boulot). Quand le Web Assembly sera stabilisé je me demande aussi si le Javascript continuera à exister …

    Bref Si tu aimes le C il est impossible de passer à côté de Rust (si tu ne l'as pas déjà essayé) !

    • [^] # Re: Go ou Rust côté backend, système ou embarqué

      Posté par  (site web personnel) . Évalué à 4. Dernière modification le 13 mars 2018 à 16:05.

      Je suis bien d'accord avec toi en ce qui concerne le Rust. Go gagne énormément en popularité, je regarde un peu de temps en temps la doc et j'en lis pas mal de code, et je pense que sa simplicité et son efficacité lui font gagner des points. Cependant j'ai lu pas mal d'article qui exposent ses faiblesses, et qu'apparemment, Go c'est pas si bien que ça (apparemment il a quelques ambiguïtés, je peux pas trop juger j'en ai pas fait moi même ceci étant dit). Rust a une syntaxe qui lui est propre (je connais pas de langage qui lui ressemble) et semble un peu compliqué de prime abord, j'ai tapé des hello world ou choses du genre, c'est assez surprenant au départ, mais les promesses qu'il donne quand au zero-cost abstraction et à la memory safety semble vraiment intéresser de plus en plus de gens.

      • [^] # Re: Go ou Rust côté backend, système ou embarqué

        Posté par  (site web personnel) . Évalué à 10.

        Pour m'y mettre depuis 1 an, go est vraiment puissant. Son système de typage par interface permet une réutilisation dingue. L'exemple typique sont des lib évoluées qui utilisent l'interface de base des mux http. Ainsi on peut injecter le tout dans une autre lib qui ne connait que la lib de base.

        Pour moi, il manque surtout des types sommes (ou union en Rust).

        Il est fait pour écrire des serveurs web applicatif qui monte bien en charge. En dehors de ce cas d'usage, il n'est pas l'ultime solution.

        "La première sécurité est la liberté"

        • [^] # Re: Go ou Rust côté backend, système ou embarqué

          Posté par  . Évalué à 10.

          Go brille aussi par son implémentation des processus légers (les goroutines). Rust rattrape son retard avec des async/await qui sont une des priorités de 2018. Mais Rust a un avantage sans prix : La thread safety garantie à la compilation, ce que Go ne pourra jamais offrir.

          Mais il est clair que Rust ça pique pas mal au début, la courbe d’apprentissage est longue (je dirais un bon mois de code pour en apprécier la saveur), alors que Go c'est un des langages les plus faciles qui soit (une demi journée de code pour se faire plaisir).

          • [^] # Re: Go ou Rust côté backend, système ou embarqué

            Posté par  (site web personnel) . Évalué à 2.

            Il y a même le crate "may" qui permet de faire des goroutines comme en go. Et quand les extensions du compilateur seront stabilisées, je suppose qu'ils mettront en place une syntaxe un peu moins rustique, genre:

            go! {
                //code
            }
          • [^] # Re: Go ou Rust côté backend, système ou embarqué

            Posté par  (site web personnel) . Évalué à 3.

            Mais Rust a un avantage sans prix : La thread safety garantie à la compilation, ce que Go ne pourra jamais offrir.

            Comment ils font ça ? Avec go, si on utilise que les channels pour communiquer entre goroutine et pas de lock, il n'y a pas de problème potentiel.

            Le cas général, est complexe surtout si on rajoute le garbage collector au milieu. Un des moyens serait d'envoyer des bouts de mémoire en lecture seul, et transmettre la gestion de ce bout de mémoire pour le détruire. Il existe une théorie dont j'ai oublié le nom qui permet de faire ça, mais cela rend le code très complexe (à chaque affectation, la sémantique est que la donnée est transmise et n'existe plus dans la variable d'origine).

            "La première sécurité est la liberté"

            • [^] # Re: Go ou Rust côté backend, système ou embarqué

              Posté par  (site web personnel) . Évalué à 10.

              Avec go, si on utilise que les channels pour communiquer entre goroutine et pas de lock, il n'y a pas de problème potentiel.

              Je suis un développeur confirmé en Go et cette affirmation est fausse. Je passe sur les questions de deadlock ou de fuite de goroutines (ce sont des problèmes potentiels, mais disons que c'est en dehors du cadre du thread safety). Par contre, la communication entre goroutine par un channel ne garantit pas l'absence qu'une écriture dans une goroutine puisse avoir des effets dans une autre goroutine (j'en ai fait plusieurs fois la douloureuse expérience).

              Quand on envoie une valeur d'une goroutine à une autre goroutine dans un channel, ça en fait une copie par valeur. Ça veut dire que si on envoie un type simple (un entier ou une chaîne de caractères), on est tranquille, ce qu'on modifie d'un côté n'a pas d'effets de l'autre. Par contre, si on commence à passer des choses plus compliquées, par exemple une struct avec un pointeur vers une autre struct (mais c'est aussi vrai pour les maps ou les slices), les deux goroutines vont avoir une struct (pas la même en mémoire) avec un champ qui pointe sur la même struct. Et, du coup, on se retrouve avec la problématique des accès concurrents à cette struct.

              Une solution pour s'en sortir est de faire du deep clone avant d'envoyer sa structure dans le channel. Malheureusement, en Go, ce n'est pas facile à faire (à cause de l'absence de génériques et parce que la réflexion n'a pas accès aux champs privés). On peut faire ça en sérialisant puis désérialisant vers du JSON, mais c'est lent et on perd les champs privés. Et c'est comme ça que pour Cozy Cloud, on s'est retrouvé avec des méthodes Clone à un paquet d'endroits que l'on maintient à la main, avec de temps en temps des erreurs ou oublis.

          • [^] # Re: Go ou Rust côté backend, système ou embarqué

            Posté par  (Mastodon) . Évalué à 0.

            Mais Rust a un avantage sans prix : La thread safety garantie à la compilation, ce que Go ne pourra jamais offrir.

            Heu, tu m'expliqueras comment tu lances un thread en Go ? En fait, tu ne peux pas, parce que Go offre bien plus que les threads, il offre un l'implémentation d'un vieux modèle de programmation concurrente qui te garantie que ça va bien se passer. Si tu ne fais qu'utiliser ce modèle (avec les channel et les goroutines), tu n'as même pas besoin de garantir quoi que ce soit à la compilation, c'est juste garanti par design. C'est ça la force de Go.

            • [^] # Re: Go ou Rust côté backend, système ou embarqué

              Posté par  . Évalué à 5.

              Ce blog post donne des exemples de race conditions en Go.

              On est d'accord en faisant attention on peut se protéger des races conditions. Mais c'est au développeur de faire attention. Go ne peut pas te dire au moment de la compilation si tu es thread safe ou non, mais seulement au runtime en instrumentant le code. Dans un programme lourd il peut être très difficile pour un développeur de garantir la thread safety.

              Rust au contraire garantie la thread safety au moment de la compilation. Il y a de nombreux postes sur le sujet dont celui du blog officiel de Rust.

              • [^] # Re: Go ou Rust côté backend, système ou embarqué

                Posté par  (Mastodon) . Évalué à 1.

                Ce blog post donne des exemples de race conditions en Go.

                Oui, mais ça n'invalide en rien ce que j'ai dit. Je remets ici le morceau important : «Si tu ne fais qu'utiliser ce modèle (avec les channel et les goroutines)». Or, dans le premier cas de bug, ils n'ont pas utilisé les channels et paf le chien. Et la solution utilise un channel. Dans le deuxième cas, ils font des trucs sales (variable globale) et ils s'étonnent que ça ne marche pas en concurrence.

                De manière globale, je préfère utiliser et même forcer l'utilisation d'un modèle de programmation sûr plutôt que de demander à un compilateur de garantir quoi que ce soit. Surtout que les garanties qu'offre Rust s'arrêtent aux frontière du unsafe.

            • [^] # Re: Go ou Rust côté backend, système ou embarqué

              Posté par  (site web personnel) . Évalué à 10.

              Pas du tout, Go ne te garantit pas ça, sauf à ne pas utiliser les pointeurs (et comme les slices et maps utilisent les pointeurs, c'est particulièrement rude). Voici un exemple sans variable globale, avec uniquement de la communication entre goroutines via un channel : https://play.golang.org/p/riJqqpTHso9.

              On fait le même traitement sur chaque entrée d'une map, en parallèle sur 3 goroutines. Si tout devait bien se passer, on devrait avoir la même valeur pour toutes les entrées de la map. Or, je viens de lancer et ça m'affiche : map[%!s(int=0):2 %!s(int=4):1 %!s(int=5):1 %!s(int=6):3 %!s(int=8):2 %!s(int=1):2 %!s(int=2):2 %!s(int=3):2 %!s(int=7):3 %!s(int=9):2] (des valeurs différentes).

              L'exemple est un peu tiré par les cheveux, mais sur Cozy Cloud, on a déjà eu des problèmes réels en production d'accès concurrents entre plusieurs goroutines sur des structs qui sont passées d'une goroutine à d'autres via des channels.

              Par contre, ce que tu décris est vrai en Erlang, qui a des espaces mémoires totalement séparés entre les différents processus légers et fais des copies de données.

    • [^] # Re: Go ou Rust côté backend, système ou embarqué

      Posté par  (site web personnel, Mastodon) . Évalué à 3.

      J'avais entrevu rust il y a un moment, je vais y jeter un œil nouveau, merci!

      La gelée de coings est une chose à ne pas avaler de travers.

      • [^] # Re: Go ou Rust côté backend, système ou embarqué

        Posté par  . Évalué à 7.

        Donnes toi un peu de temps pour l'apprécier. J'ai du m'y prendre à plusieurs fois pour adopter la bête. J'ai été très découragé au début par la syntaxe et les mécanismes de gestion de mémoire "safe" (borrowing, lifetime).

        Mais en tant que programmeur C tu apprécieras sûrement :

        • Le build système intégré (Cargo), et son lot de modules tiers (crates.io).
        • Le langage a été pensé pour s'interfacer avec le C très facilement.
        • Des structs, des méthodes et des interfaces, mais pas d'héritage (fini la programmation objet de papa qu'on a tous appris à l'école).
        • Des enums vraiment sympa.
        • Des templates. Je ne suis pas fan des templates, mais l'approche de Rust est assez élégante.
        • Une gestion fine de la mémoire, complètement safe et sans l'overhead d'un garbage collector : pas de coredump, pas d'overflow, pas de release after free et autre subtilités qui font la joie des pirates.
        • Thread safety garantie à la compilation (c'est sans sans prix !)
        • Un système de macro puissant.
        • Une cross-compilation intégrée avec support de nombreuses platformes (Windows, Linux, Mac, BSD, ARM, …).
        • Une librairie standards minimaliste pour des conteneurs (Vecteurs, Lists chainées …) que tu peux exclure du link si tu veux faire un binaire minimaliste pour de la programmation embarquée.

        Bref Rust se positionne comme le remplaçant du C, plus que du Java par exemple. Mais clairement la courbe d'apprentissage est longue, à l'opposée de tout ce qui se fait aujourd'hui comme Go ou Swift.

  • # je ne suis pas développeur à temps plein, mais je fais quand même du développement.

    Posté par  . Évalué à 4.

    ma_vie:
    J'ai appris le C, et le C++ durant mes études, ainsi que de l'assembleur (6809,68hc11, 68000 et x86), ainsi que du shell unix, et du turbo pascal en stage. Ensuite dans ma vie professionnelle, j'ai fait shell, perl, awk, python, ruby, javascript, php, sql, lua (un peu) ainsi que du VBA , un peu de TCL. Depuis peu je me suis mis un peu à Groovy. A titre personnel, je me suis intéressé à Ada, Rebol, prolog, smalltalk, erlang, elixir, java, go, rust (très peu pour ces deux derniers) ainsi que Forth, j'ai refait du C, de l'assembleur (AVR et 8051), je me suis intéressé de loin à Lisp et ses dérivés et comme indiqué dans un précédent journal, du BASIC dans les années 80 sur T07.

    Ce que j'en déduis de tout ça, c'est qu'il n'y a pas de langage parfait. Chaque langage que j'ai utilisé a été développé dans un contexte et pour des besoins particuliers, avec certaines contraintes, et quand on sort un peu trop du cadre initial, on commence à avoir des problèmes.

    Parmi les langages que j'apprécie le plus, je peux citer Ruby, Erlang, C et ADA. Parmi ceux que j'aime le moins, il y a elixir, python, java, php.
    Ce que je n'aime pas pour les 3 derniers langages, c'est le fait qu'ils ne soient pas toujours très cohérents. Pour le PHP, ça fait trop longtemps que je n'ai plus fait donc je le laisserai de côté car les versions récentes corrigent peut-être ce que je n'aimais pas lorsque j'en faisais. Pour Java, un des trucs que je n'aime pas et que je trouve dangereux c'est la conversion implicite. Je n'aime pas non plus la gestion des exceptions.

    Pour python, je n'aime pas son manque de cohérence général (par exemple, on ne sait jamais si on doit faire des trucs du style str(machin) ou machin.str(), alors qu'en ruby par exemple c'est plus clair). On sent que le langage a été plus ou moins enrichi au fur et à mesure avec des trucs venus d'ailleurs, sans se poser trop de question sur la cohérence générale. Je n'aime pas non plus le manque de switch/case. Je n'aime pas trop non plus le mix de paradigme objet/fonctionnel qui casse la fluidité de la lecture du code (mais on peut s'en arranger en incluant ces bouts de code dans des fonctions qui permettent d'isoler ces changements de paradigme et améliorer la fluidité de lecture). Je n'aime pas non plus les décorateurs de Python (je n'ai jamais vraiment biern compris comment ça marche, je préfère largement les mixin de Ruby). Par contre il y a quelques concepts de métaprogrammation que je trouve intéressant en Python (notamment les métaclasses), mais je trouve que le langage ne va pas assez loin sur ces concepts. Je trouve que l'obligation d'indenter le code est une bonne idée, mais que s'en servir pour définir les blocs est une mauvaise idée, et rend la refactorisation de code compliqué. Et fondaentalement, je n'aime pas l'esprit rigide de python ("ce n'est pas la bonne façon de faire") et qui oblige souvent à se faire des noeuds au cerveau alors que d'autres langages ont l'élégance de s'effacer devant la créativité du développeur. Et pour Elixir, je n'ai pas poussé très loin, mais par rappoort à Erlang, je trouve qu'il casse un certain nombre de concepts qui font l'intéret du langage (je pense par exemple aux variables à affectation unique).

    Tout ça pour dire que bien souvent, le choix d'un langage adapté dépendra du type de problème à traiter, tout comme le choix de n'importe quel outil. Je suis d'avis qu'il n'existe pas de langage réellement "généraliste". Dans certains cas d'usages, on pourra choisir indifféremment plusieurs langages, mais on peut avoir certaines contraintes qui font que choisir le bon langage pourra permettre de s'éviter des difficultés de développement parce que le langage sera plus adapté aux problèmes à traiter.

  • # Yen a trop

    Posté par  . Évalué à 5.

    Point de vue d'un amateur, qui se limite à C et bash, et php / javascript pour le web : Je trouve assez surprenante la multiplicité excessive des langages de programmation. Je ne connais pas le milieu professionnel du développement, mais il doit y avoir une perte d'énergie considérable à l'apprentissage des langages et à l'attention à ne pas se mélanger les pinceaux entre les différentes syntaxes.
    Un truc qui m'étonne aussi, c'est la popularité des langages interprétés, y compris pour réaliser de gros programmes. Ce qui revient à faire porter au matériel la performance du logiciel.
    Et j'ai l'impression qu'on a tendance à éviter le C de nos jours, alors qu'en matière de performance (vitesse d'exécution), c'est quand même top.
    Enfin ce sont juste des ressentis par rapport aux actualités glanées ici où là, je n'ai pas de statistiques précises.

    • [^] # Re: Yen a trop

      Posté par  (site web personnel) . Évalué à 6.

      Je ne connais pas le milieu professionnel du développement, mais il doit y avoir une perte d'énergie considérable à l'apprentissage des langages et à l'attention à ne pas se mélanger les pinceaux entre les différentes syntaxes.

      Dans l'ensemble dans le milieu pro, tu n'as pas à connaître une quantité importante de langage. Ce sont souvent les mêmes qui sont employés, et de nombreux langages sont réservés à des domaines spécifiques. Or, un informaticien va rarement faire du développement système, puis du web, pour faire du noyau à la fin. Ça arrive mais c'est plutôt rare, tu vas donc te limiter aux langages de ton domaine.

      Et j'ai l'impression qu'on a tendance à éviter le C de nos jours, alors qu'en matière de performance (vitesse d'exécution), c'est quand même top.

      J'aime le C, j'aime certains de ses avantages évidents mais il faut reconnaître que pour la quasi totalité des applications le C est trop vieux et inadapté pour les contraintes du monde d'aujourd'hui.

      Aujourd'hui le matériel est largement assez puissant pour prendre en charge la surcharge imposée par des langages plus modernes. Mais cela se fait au bénéfice d'une meilleure sécurité, de tests plus performants, d'un temps de développement moindre, etc. Ce n'est pas un détail.

      Le C se réduit de plus en plus au domaine du très bas niveau (noyau, chargeur de démarrage, firmware) et aux applications type temps réel. Car en dehors ses remplaçants font le boulot.

    • [^] # Re: Yen a trop

      Posté par  . Évalué à 5.

      Et j'ai l'impression qu'on a tendance à éviter le C de nos jours, alors qu'en matière de performance (vitesse d'exécution), c'est quand même top.

      À condition de bien l’écrire… Un programme mal écrit en C n’ira pas plus vite que son équivalent bien pensé dans un autre langage. De plus l’autre langage apportera probablement des garanties inexistantes en C (on pense ici à la gestion de la mémoire, aux IO, etc) et des syntaxes plus expressives qui aideront les développeurs à écrire le programme dans une forme mieux pensée.

      Ce sont surtout sur ces points que les langages diffèrent : les garanties qu’ils apportent, et les modèle de données ou d’algorithmes qui s’y expriment aisément. Après, chacun placera le curseur où cela lui semble le plus pertinent, personnellement, mes choix ne sont pas très à la mode, car le meilleur équilibre que j’ai trouvé à ce jour (pour du calcul scientifique) est le Fortran (post 2003). Je n’irai pas défendre ce langage pour écrire un moteur de blog (quoique ça existe) mais pour manipuler efficacement et simplement des tableaux multidimensionnels, je ne lui trouve pas de compétiteur équivalent, et en l’occurrence le C est même une horreur pour ce type d’applications.

      • [^] # Re: Yen a trop

        Posté par  . Évalué à 2.

        des syntaxes plus expressives qui aideront les développeurs à écrire le programme dans une forme mieux pensée.

        Hein ? Je me demande ce que tu entends par ça : le C te permet d'exprimer ce que tu veux n'importe comment (un peu comme Perl).

        • [^] # Re: Yen a trop

          Posté par  (site web personnel) . Évalué à 7.

          Hein ? Je me demande ce que tu entends par ça : le C te permet d'exprimer ce que tu veux n'importe comment (un peu comme Perl).

          Oui mais le C standard ne propose pas grand chose et a une approche bas niveau pour ses structures élémentaires.

          Du coup non seulement c'est beaucoup de travail pour lui apporter des fonctionnalités évoluées, mais en plus en l'absence de structures élémentaires de haut niveau, le programmeur n'aura pas le réflexe d'utiliser certains algorithmes car trop lourds à écrire, ou difficilement exprimable naturellement en C.

Suivre le flux des commentaires

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