Partage
  • Partager sur Facebook
  • Partager sur Twitter

Trop de auto et de template

    1 juillet 2020 à 19:46:56

    Salut,

    Petit sujet pour discuter un peu.

    Mon stagiaire aime beaucoup (trop ?) les auto, et les template. ça me perturbe un peu.

    Je prends un exemple dont on a parlé, imaginons un for, juste un for. Au lieu de faire un int, un unsigned int, ou un size_t ou que sais-je pour itérer (una variable i) , on pourra utiliser "auto". 

    Mais du coup, si on transmet cet index à une fonction ou une méthode, et bien il faudra le récupérer en tant que template. 

    Et de fil en aiguille, en mettant des auto de partout, chaque passage de paramètres "auto" à des fonctions fera qu'on utilisera des template.

    Alors bien sur, j'entends les arguments : donner un bon nom au variables pour que le type soit intuitif. J'entends aussi que le compilo va créer tout seul les fonctions avec les bons paramètres.

    Mais cette façon de programmer me rebute un peu (suis-je déjà vieux ?). Je trouve que ça ne va pas du tout avec le principe KISS.

    Techniquement, si on une fonction ou il n'y aura jamais autre chose qu'un int dedans par exemple, pourquoi mettre un template ?

    Pour moi le template c'est vraiment quand il y a une fonction générique ou on aura un vrai besoin de passer dedans avec plusieurs types différents.

    Je voulais lancer une discussion sur cette façon de programmer que je trouve assez difficile à lire et à maintenir. 

    • Partager sur Facebook
    • Partager sur Twitter

    Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

      1 juillet 2020 à 20:16:27

      > pour itérer (una variable i) , on pourra utiliser "auto".

      Euh... ça ? `for(auto i = 0; i!=N; ++i)`? Ca ne marche pas très bien car il faut chopper le decltype de N... Pas d'auto là pour moi.

      En revanche, `for( auto && e : range) `, j'adhère!

      > suis-je déjà vieux?

      Jeune, on a tendance à tout tester sans avoir encore le recul. Vieux, il faut nous continuer à tester sur des petits tests/projets perso pour évaluer si une fonctionnalité nous convient, et sous quelles conditions.

      Ce qui me fait du mal, c'est quand le C++ commence à ressembler à du LISP avec des lambdas qui génèrent d'autres lambdas. Et... même si ce n'est pas mon schéma de fonctionnement, pour ceux qui sont habitués, c'est totalement KISS.

      > Techniquement, si on une fonction ou il n'y aura jamais autre chose qu'un int dedans par exemple, pourquoi mettre un template ?

      Pour pourrir les temps de compilation?

      Sinon, Si effectivement le type peut changer, OK pour template -- mais là il y a des contraintes, vive les concepts. Sinon, ils pourraient faire pire s'ils sont trop corrompus par Python ou les feuilles de tableur utiliser des std::any à tout va :D

      • Partager sur Facebook
      • Partager sur Twitter
      C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
        1 juillet 2020 à 20:27:28

        >donner un bon nom au variables pour que le type soit intuitif

        Très mauvais argument, si on peut nommer une variable pour en permettre un type, c'est que "l'algorithme" n'est pas générique, donc que l'utilisation de auto n'est pas bonne.

        Mais cela ne veut pas dire qu'il faut supprimer l'auto, il faut rendre l'algorithme "générique", donc pas de type "en dur".

        Si l'algorithme n'est pas généralisable, alors on utilise les types explicites, justement pour signaler ce manque de généricité.

        >(suis-je déjà vieux ?)

        Bien venu au club. ;)

        >Je trouve que ça ne va pas du tout avec le principe KISS.

        Si l'algorithme est générique, bien sûr que c'est KISS, pas besoin d'implémenter 10 fois la même chose, juste pour des types différents.

        >il n'y aura jamais autre chose qu'un int dedans par exemple, pourquoi mettre un template ?

        Si on peut avoir la même chose pour tous les types qui sont compatibles avec l'algorithme de la fonction, pourquoi s'en priver ?

        >quand il y a une fonction générique ou on aura un vrai besoin de passer dedans avec plusieurs types différents.

        C'est juste une question de point de vue. J'ai l'impression que t'es dans la démarche : "je fais un truc avec des int. Maintenant j'ai besoin de faire la même chose avec des doubles => on convertit le machin en template". Mais une approche plus systématique c'est, "je fais du code générique partout, parce que je vais pas revenir 10 fois sur ce code pour les 10 différents qui vont sortir du chapeau du compilateur, entre les const, les r-reférences, les lambda, les itérateurs, etc..., s'il y a un truc que ne marche pas avec tous ces types avenir : spécialisation de template voir passage à un typage explicite (si cela ne fonctionnera qu'avec un type, ce qui est de plus en plus rare)".

        Donc, plutôt que de justifier l'usage du template, il faudrait plutôt justifier l'usage d'un typage explicite.

        Mais la lisibilité du code est un argument très valide, mais tu ne dois pas être l'étalon de la lisibilité, mais toute ton équipe.

        Les "avancées" du langage rendent les types "sortis du chapeau du compilateur" de plus en plus commun car le code générique devient la norme et donc ne pose pas de problèmes. Elles permettent aussi de rendre code générique de plus en plus simple à mettre en oeuvre => boucle de rétraction positive.

        Donc oui, le plus d'auto possible, tant que cela ne nuit pas à la lisibilité d'un code, qui doit être le plus générique possible tout en étant "lisible". Et plus le C++ évolue plus les cas illisibilité seront rare (normalement).

        • Partager sur Facebook
        • Partager sur Twitter
        Je recherche un CDI/CDD/mission freelance comme Architecte Logiciel/ Expert Technique sur technologies Microsoft.
          1 juillet 2020 à 20:37:36

          TL;DR : oui, tu es vieux ;)

          <koala01 mode on>

          Fvirtman a écrit:

          Alors bien sur, j'entends les arguments : donner un bon nom au variables pour que le type soit intuitif. 

          La justification n'est pas celle là de mon point de vue. Cet argument, c'est juste pour justifier que mettre "auto" n'est pas une perte d'expressivité, parce que l'on a le nom de la variable qui est suffisant. Mais ce n'est pas la justification d'utiliser "auto".

          A mon sens, c'est une question de maintenabilité du code. Si le type change, avec "auto", on a la garantie que le type de la variable sera toujours correcte par rapport à la valeur que l'on veut passer. (Donc sans cast)

          Est-ce une bonne chose ?

          Oui, bien sûr. Un exemple concret. Si tu utilises "std::vector" (qui utilise std::size_t comme type pour les index) et que ton code passe a QVector (qui utilise des "int" comme type pour les index), alors ton code reste optimal (c'est a dire sans cast)

          auto i = v.size(); // std::size_t ou int selon le cas

          Es-tu sur que c'est une bonne chose ???

          Euh...

          Mouais, ok, pas toujours. J'ai triché dans le code précédent, je n'ai volontairement pas écrire une boucle for. Si on veut faire cela :

          for (auto i = 0; i < v.size(); ++i) ...

          Là, i est toujours de type "int", il faut explicitement donner une valeur initiale du type que l'on souhaite.

          for (auto i = 0; i < v.size(); ++i) ... // int
          
          for (auto i = 0u; i < v.size(); ++i) ... // unsigned int
          for (auto i = static_cast<size_t>(0); i < v.size(); ++i) ... // mieux ?

          On n'a plus le type de i qui est déduit automatiquement. Si on veut conserver la déduction automatique, il faudrait écrire :

          for (decltype(v.size()) i = 0u; i < v.size(); ++i) ... // mieux ???

          C'est lourd !

          En pratique, avoir la déduction automatique ajoute pas mal de boilerplate code, pour un gain... discutable.

          Es-tu sur de sur que c'est une bonne chose ???

          Un autre exemple. On utilise initialement QVector (donc un int pour les index) et on passe a std::vector (donc std::size_t).

          if (function_qui_retourne_un_index() < 0) ...

          Et la, on a un beau "comparaison entre signé et un non signé". On doit mettre à jour le code, ce qui signifie que le code n'était pas totalement maintenable facilement.

          --------------------------------------------------------------

          Au final, on voit avec cet exemple ce qui semble être le problème de la programmation générique à outrance : le compromis avec la maintenabilité du code. Cela va dépendre du type de projet :

          - sur une lib comme la lib standard ou boost, la généricité sans perte de performances est le critère principal. Ces libs sont tellement utilisées et dans des projets différents que la maintenance du code de ces libs est secondaire.

          - sur une application finale, où tu sais très en amont que tu vas utiliser std::vector ou QVector et donc que tu sais si tu vas utiliser std::size_t ou int comme type d'indice, l'utilisation de "auto" n'apporte rien. Le cout pour passer de std::vector a QVector (ou réciproquement) est énorme dans tous les cas, ce n'est pas l'utilisation de "auto" qui va permettre de ne pas avoir de coût pour passer de l'un à l'autre. Dit autrement, le code ne sera pas maintainable (pour ce point) et utiliser "auto" ne changera rien. Ni l'utilisation des templates.

          A mon sens, utiliser "auto" dans ce dernier cas, c'est comme utiliser des grosses roues de 4x4 sur une 2CV en disant "comme ça, on peut aller partout, c'est mieux !". En oubliant que la 2CV n'a pas 4 roues motrices et un moteur pas très puissant et que si on veut faire du tout terrain avec, on va rester dans la gadoue, peu importe les roues qu'on met dessus.

          -------------------------------------------------------------------------------------

          Pour les templates, même combat : faire un compromis entre généricité, maintenabilité du code, boilerplate code. Créer un template juste pour le type des indices, alors qu'on ne va jamais changer le type pendant 10-20 ans, c'est un surcoût très discutable en termes de lourdeur du code. Le gain par rapport à fixer l'utilisation du type (std::size_t ou int) est nul.

          Au pire, je préfère un bon vieux fichier de configuration des types

          config.h 
          
          #define INDEX_TYPE std::size //ou int
          
          for (INDEX_TYPE i = 0; i < v.size(); ++i) ...
          
          void foo(INDEX_TYPE i);

          Mais même faire cela me semble inutile dans une application finale.

          J'utilise std::vector et QVector/QList dans mes projets et je n'utilise pas auto ou des templates pour gérer les types des indices. Au contraire, je préfère avoir un cast explicit (et donc un warning si j'oublie) quand on passe d'un indice d'un type vers un autre.

          Comme toi, je réserve l'utilisation des templates pour les cas réellement générique, c'est à dire souvent l'implémentation d'algos ou des fonctions relativement bas niveau.

          ----------------------------------------------------------------------------

          Note : il faut bien comprendre que certaines fonctionnalités ajoutées au C++ sont avant tout destinées aux devs des libs génériques, comme la STL ou boost. Dans des applications finales, c'est probablement des fonctionnalités overkill. Il faut savoir faire la part des choses et ne pas utiliser systématiquement les nouvelles fonctionnalités. On ne fait pas de la généricité pour la généricité, mais parce que cela apporte quelque chose en termes de qualité logiciel (en général de la maintenabilité). Donc c'est a voir au cas par cas selon le projet et le gain concret (pas le gain théorique).

          Note2 : avec les concepts, on aura l'utilisation de "auto" dans les fonctions, comme on a actuellement avec les lambdas. On pourra écrire :

          template<typename INDEX_T>
          void foo(INDEX_T i);
          
          // devient :
          
          void foo(auto i);
          
          // ou peut être un truc comme :
          void foo(INTEGRAL_TYPE_CONCEPT i); // je sais plus le nom

          Bref, un compromis générique sans la lourdeur d'un template.

          -------------------------------------------------------------------

          bacelar a écrit:

          Mais une approche plus systématique c'est, "je fais du code générique partout, parce que je vais pas revenir 10 fois sur ce code pour les 10 différents qui vont sortir du chapeau du compilateur, entre les const, les r-reférences, les lambda, les itérateurs, etc..., s'il y a un truc que ne marche pas avec tous ces types avenir : spécialisation de template voir passage à un typage explicite (si cela ne fonctionnera qu'avec un type, ce qui est de plus en plus rare)".

          Donc, plutôt que de justifier l'usage du template, il faudrait plutôt justifier l'usage d'un typage explicite.

          Je trouve l'argument de bacelar intéressant. Et on voit que c'est pas exactement la meme démarche que lmghs ou moi.

          A mon sens, le problème est que l'on écrit très rarement (voir jamais probablement) du code totalement générique. Si on écrit :

          template<typename INDEX_T>
          void foo(INDEX_T i) {
            ...
          }

          cela est de la "fausse" généricité. Ce code n'est pas censé accepter n'importe quels types, mais uniquement les types correspondant a des indices. Même si cette fonction compile avec "double" par exemple, cela ne devrait pas être permit.

          Il faut donc ajouter du code pour valider les types acceptables. Un truc du genre :

          template<typename INDEX_T>
          void foo(INDEX_T i) {
            static_assert(std::is_integral_type(INDEX_T)); // je sais plus la syntaxe
            ...
          }

          Ca commence a faire beaucoup de boilerplate code. Si on ajoute la vérification des contrats, on a des fonctions qui deviennent assez lourde.

          (En attendant, comme le dit lmghs, les concepts)

          Le surcoût n'est pas juste d'ajouter 1 ligne dans le code pour ajouter le "template<typename INDEX_T>". Si on fait ca pour pleins de fonctions, c'est un coût très lourd pour la lisibilité et la compilation.

          Si on estime que le type ne changera pas avant 10-20 ans dans un projet particulier, ce cout me semble inutile par rapport au gain.

          Je suis partisan pour la généricité par défaut. Mais il ne faut pas perdre de vue l'objectif final de pourquoi on fait de la généricité (la qualité logicielle) et le faire en connaissance de cause.

          <koala01 mode off>

          -
          Edité par gbdivers 1 juillet 2020 à 21:04:39

          • Partager sur Facebook
          • Partager sur Twitter
            1 juillet 2020 à 21:54:10

            gbdivers a écrit:

            TL;DR : oui, tu es vieux ;)

            <koala01 mode on>

            <koala01 mode off>

            -
            Edité par gbdivers il y a 34 minutes


            :lol:

            Génial de vous lire. J'ai que 25 ans alors ce genre de débat "vieux contre jeunes" j'adore.
            • Partager sur Facebook
            • Partager sur Twitter
              1 juillet 2020 à 21:56:47

              En fait, il n'y a que des vieux qui ont répondu pour le moment :D
              • Partager sur Facebook
              • Partager sur Twitter
                1 juillet 2020 à 21:58:25

                gbdivers a écrit:

                En fait, il n'y a que des vieux qui ont répondu pour le moment :D


                :-°
                • Partager sur Facebook
                • Partager sur Twitter
                  2 juillet 2020 à 1:21:43

                  Pour moi, utiliser une variable auto n'implique pas un code générique. Dans le cas de fonction non-template, cela tend à reléguer le type en second plan, car le connaître est superflu ou il est déductible du contexte (exemple des itérateurs ou de make_unique). Du coup, on peut très bien faire des interfaces avec des types en dur et avoir des auto partout sans nuire à la lisibilité ou la compréhension.

                  Le problème de la déduction automatique arrive quand on veut introduire une valeur dépendante du type d'une autre valeur: l'exemple d'une boucle sur size_t ou int commençant à 0.

                  À mon sens, le gros problème est de vouloir utiliser 0. Si je pars dans l’extrême, une taille n'est pas forcément un entier, cela peut être une enum class, un type multidimensionnel ou finalement n'importe quoi. Et l'index n'a pas non plus de raison d'être du même type que la taille. De ce constat, decltype(v.size()) i = 0 est une mauvaise approche et cela devrait être relégué à une fonction qui créer un range for (auto&amp;&amp; i = index_range(cont)).

                  Beaucoup de problème du genre peuvent être supprimés avec la matérialisation d'une classe pour représenter l'intention. En plus, avec C++17 et les guides de déductions, on peut instancier ce genre de classe sans indiquer les types en template: l'intention reste et est nommée, les types réels sont superflus.

                  Concernant les templates, je vois 2 choix:

                  • On a une implémentation identique sur un nombre restreint de type pré-existant.
                  • On veut du générique pure et dur

                  Dans le premier cas, j'ai tendance à exposer toutes les fonctions mais déléguer l'implémentation à une template: c'est un détail d'implémentation. Au pire, je restreins le type au niveau de la signature (enable_if par exemple), mais niveau lisibilité ce n'est pas toujours ça.

                  Dans le second cas, j'évite de faire des vérifications de type qui ne sont pas nécessaires. Vérifier que mon index est un entier, bof. Déjà parce que cela exclut d'office des types valide, mais aussi parce qu'il y aura des erreurs (ou au pire des avertissements) pour indiquer que quelque chose ne va pas. Ce qu'il faut, c'est vérifier que les interactions sont valides, mais sans concept, c'est barbant.

                  En dehors de cela, je ne vois pas de raison d'utiliser des templates. En plus, cela donne une fausse impression de généricité, j'aurais tendance à penser que c’est une manière détourner de mettre un nom plus évocateur au type, là où un typedef ferrait mieux le boulot.

                  • Partager sur Facebook
                  • Partager sur Twitter
                    2 juillet 2020 à 9:08:49

                    J'attaquerai par le coté humain, et non le coté technique:

                    Pour moi la priorité du code doit être la lisibilité.
                    SI l'emploi du mot clef auto est ambigu, alors il vaut mieux (a mon sens) le laisser de coté.

                    • Partager sur Facebook
                    • Partager sur Twitter
                      2 juillet 2020 à 10:15:56

                      Lu'!

                      J'ai l'impression qu'il y a aussi un choc des cultures dans la manière de programmer. Dans les langages full-inference de types, on ne trouve des types que dans la définition de signatures de modules/fonctions, à prendre un peu au sens "header" (même si c'est pas tout à fait exact). Le résultat c'est qu'en réalité, on ne voit presque jamais les types pendant que l'on développe, et pourtant c'est généralement statiquement typé et typé bien plus fortement qu'en C++. Le résultat c'est que c'est vachement plus KISS au final : l'information sémantique importante est portée par le traitement et on ne voit des types qu'au point de jonction entre les modules.

                      Dans un langage comme C++ tout de suite, ça devient vachement moins drôle. Notamment parce que le langage est plus faiblement typé.

                      Ça a impliqué des choix comme le fait que le mot auto comme paramètre est traduit comme du code template et ça forcément, si on en met partout, ça pose problème, parce que ça ruine les temps de compilation et que ça peut cacher des générations de fonctions différentes au sein d'une même unité de compilation. Ou même, sans les cacher, à la situation relou où l'on se retrouve à foutre du template à un endroit où l'on voudrait une inférence statique (concernant ce point, les concepts vont partiellement aider mais au prix d'un ajout supplémentaire de code).

                      Un autre effet pas sympa du typage plus faible, c'est les conversions implicites, le traitement des qualifieurs, des pointeurs et des (rvalue-)références qui viennent mettre une charge cognitive encore plus importante au développeur dans un code qui manipule de l'auto. Et ça, ben, pas le choix, il faut faire avec. C++ a refusé de couper les ponts avec C, et a ajouté sa couche de complexité de ce côté, et c'est encore un terrain défavorable à l'inférence de types.

                      • Partager sur Facebook
                      • Partager sur Twitter

                      Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                        2 juillet 2020 à 11:27:56

                        Salut,

                        A mon avis, la limite d'utilisation de auto se trouve dans la différenciation de ce qui relève de l'abstraction (et de ses détails d'implémentation) et de ce qui relève de l'interface.  Je m'explique:

                        Mettons que je travaille avec une collection d'éléments, et que j'ai besoin de récupérer le nombre d'élément que cette collection contient.  Je fais donc appel à la fonction size().

                        Mais je me fous pas mal de savoir si la valeur récupérée est un int, un size_t,  ou même un short: tout ce que je veux, c'est connaitre la taille!

                        Il me semble donc tout à fait cohérent d'utiliser l'inférence de  type dans ce contexte, sous une forme proche de

                        auto size = collection.size();
                        /* je peux l'utiliser à  ma guise par la suite */

                        De même, si je veux itérer sur les éléments de cette collection, ce qui m'intéresse, c'est l'abstraction représentée par les itérateurs utilisés, et il est donc parfaitement logique d'utiliser l'inférence de type sous une forme proche de

                        for(auto /* const & */ it : collection){
                            /*je fais ce que je veux des éléments récupérés */
                        }

                        La raison pour laquelle je conseillerais d'agir de la sorte, c'est que ma collection d'éléments est un "détail d'implémentation", qu'elle peut varier au fil du temps en fonction mon "bon vouloir" : si c'est un std::vector aujourd'hui, je peux changer d'avis demain et décider d'utiliser un QVector, un std::set, une std::list, une QList ou même (pourquoi pas) une std::map ou une QMap (même si je devrai adapter mon code).

                        D'un autre coté, si l'une des données que je manipule est destinée à être fournie à une fonction, il n'y a rien à faire, je suis bien obligé de me conformer à l'interface de cette fonction.

                        Si la fonction s'attend à  recevoir un int, je ne peux en effet pas (du moins, pas sans avoir un avertissement) me permettre de lui transmettre un size_t, ou inversement.

                        Par chance, l'interface de cette fonction ne devrait pour ainsi dire pas changer dans le temps, ce qui me permet de suivre un raisonnement proche de

                        j'ai besoin d'un size_t (ou d'un int)  pour représenter l'indice de l'élément utilisé lors de l'appel de la fonction.  Je définis donc ma donnée index en tant que tel.

                        Tant que je ne décide pas de changer la fonction appelée (ce qui impliquerait sans doute pas mal de changements), ce type n'a aucune raison d'être modifié

                        Et, ma foi, si l'on décide de briser la compatibilité lors d'un refactoring majeur et de changer l'interface de la fonction appelée, ben le changement de type à ce niveau ci devra en faire partie ;)

                        • Partager sur Facebook
                        • Partager sur Twitter
                        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                          3 juillet 2020 à 9:25:44

                          Salut,

                          C'est pas parce qu'une fonctionnalité existe qu'il faut absolument l'utiliser.

                          Personnellement, j'utilise auto quand :

                          • On a pas besoin de connaître le type exact de l'objet pour le manipuler
                          • Le nom de la variable décrit suffisamment bien ce qu'elle contient.
                          • Pour éviter les redondances de ce genre :
                          // Ce petit monstre...
                          TypeQuiAUnNomBeaucoupTropLong typeQuiAUnNomBeaucoupTropLong = getMachinTruc();
                          
                          // ...devient...
                          auto typeQuiAUnNomBeaucoupTropLong = getMachinTruc();

                          Donc le coup du

                          auto i = 0;

                          , je comprends pas intérêt. D'ailleurs, comment est-ce que le compilateur va décider entre int et unsigned int ?

                          Je pense que ton stagiaire a envie de bien faire et qu'il cherche à écrire du code "ultra moderne" et qu'il oublie que le code sera lu et maintenu par d'autres programmeurs, pas n'importe qui.

                          • Partager sur Facebook
                          • Partager sur Twitter
                            3 juillet 2020 à 9:57:20

                            Raynobrak a écrit:

                            Donc le coup du

                            auto i = 0;

                            , je comprends pas intérêt. D'ailleurs, comment est-ce que le compilateur va décider entre int et unsigned int ?

                            C'est bien spécifié, donc c'est facile pour le compilo :

                            • 0 -> int
                            • 0u -> unsigned
                            • Partager sur Facebook
                            • Partager sur Twitter

                            Posez vos questions ou discutez informatique, sur le Discord NaN | Tuto : Preuve de programmes C

                              3 juillet 2020 à 10:54:56

                              Mais c'est lesquels les suffixes pour les types qui sont des typedefs dépendant de la machine?... :(

                              -
                              Edité par lmghs 3 juillet 2020 à 15:40:22

                              • Partager sur Facebook
                              • Partager sur Twitter
                              C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                3 juillet 2020 à 15:31:21

                                Et bien ce sujet déchaine les passions !

                                Merci a tous de vos témoignages.

                                Je retiendrais beaucoup la phrase de Ksass`peuk : J'ai l'impression qu'il y a aussi un choc des cultures dans la manière de programmer


                                Quand je vois mes collègues les plus agés, leur code est vraiment du C with classes. A grand coup de pointeurs nus et de concepts de C.

                                Quand je vois les jeunots (enfin les jeunots acharnés au langage comme mon stagiaire) je vois de l'auto de partout et du template de partout, et ça me semble d'une lourdeur épouvantable.... 

                                Et moi je suis une sorte d'hybride finalement. Je n'utilise plus de pointeurs nus, mais j'ai encore un style assez ancien malgré tout, et je ne me sens pas d'attaque pour changer. (du moins ça se fera avec le temps si ça doit être)

                                Après, comme il a été dit aussi, peut être que foutre de l'auto de partout n'est pas non plus la solution : faire un for avec auto quand dedans il n'y a que de l'atome, ou des fonctions qui ne dépendent pas de "i" oui, mais quand il faut passer i et faire du template mais non quoi.

                                Après, je pense que mon stagiaire complexifié pas mal de trucs qu'il ne devrait pas, et paradoxalement écrit plus de code qu'il ne devrait, juste pour prévoir un cas qui n'existera jamais.

                                -
                                Edité par Fvirtman 3 juillet 2020 à 15:32:38

                                • Partager sur Facebook
                                • Partager sur Twitter

                                Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                                  3 juillet 2020 à 15:49:22

                                  > paradoxalement écrit plus de code qu'il ne devrait, juste pour prévoir un cas qui n'existera jamais.

                                  Si tu penses que c'est le cas, à toi de le recadrer. Tu es en parti là pour participer à sa formation et que ce qu'il produit puisse être exploitable par le reste de l'équipe.

                                  Et peut-être verra-t-on un témoignage de stagiaire qui a un vieux directeur de stage qui tient absolument à utiliser un C++ de dinosaure :D

                                  • Partager sur Facebook
                                  • Partager sur Twitter
                                  C++: Blog|FAQ C++ dvpz|FAQ fclc++|FAQ Comeau|FAQ C++lite|FAQ BS| Bons livres sur le C++| PS: Je ne réponds pas aux questions techniques par MP.
                                    3 juillet 2020 à 16:03:24

                                    Oui, je le recadre déjà un peu t'en fais pas :) Mais en lui laissant quand même pas mal de libertés ! 

                                    Mais oui, on a une cassure de génération, ça crève les yeux, et on en aura de plus en plus avec le temps !

                                    • Partager sur Facebook
                                    • Partager sur Twitter

                                    Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                                      3 juillet 2020 à 16:08:45

                                      Vous travaillez tous sur le même projet ? Car avec tous ces mélanges de "génération C++", ça doit faire une drôle de soupe ! :p
                                      • Partager sur Facebook
                                      • Partager sur Twitter
                                        3 juillet 2020 à 16:11:06

                                        lmghs a écrit:

                                        > paradoxalement écrit plus de code qu'il ne devrait, juste pour prévoir un cas qui n'existera jamais.

                                        Si tu penses que c'est le cas, à toi de le recadrer. Tu es en parti là pour participer à sa formation et que ce qu'il produit puisse être exploitable par le reste de l'équipe.

                                        Et peut-être verra-t-on un témoignage de stagiaire qui a un vieux directeur de stage qui tient absolument à utiliser un C++ de dinosaure :D


                                        Ca, ca pourrait être le cas si Fvirtman ne prend pas la peine de justifier les réécritures qu'ils effectue...

                                        S'il explique à son stagiaire que les template n'ont un intérêt que lorsque l'on ne sait effectivement pas déterminer le type qui sera réellement utilisé, que quand ce type risque effectivement de varier avec les appels, qu'il faut, à l'instar de ce que disait Einstein

                                        Rendre les choses aussi complexes que nécessaire, mais guère plus

                                        Alors, nous pourrions avoir un témoignage dans lequel le stagiaire reconnaitra avoir "beaucoup appris" d'un "vieux directeur de stage" ;)

                                        • Partager sur Facebook
                                        • Partager sur Twitter
                                        Ce qui se conçoit bien s'énonce clairement. Et les mots pour le dire viennent aisément.Mon nouveau livre : Coder efficacement - Bonnes pratiques et erreurs  à éviter (en C++)Avant de faire ce que tu ne pourras défaire, penses à tout ce que tu ne pourras plus faire une fois que tu l'auras fait
                                          3 juillet 2020 à 16:41:54

                                          Je pense qu'il aura pas mal appris quand même ! Déjà sur tout de qu'il y a autour, les différents formats de fichiers qu'on manipule, les différents outils, la façon de chercher des données, de les encoder, des trucs mathématiques.... Oui il n'y a pas que le langage ! :) 

                                          Toniooo a écrit:

                                          Vous travaillez tous sur le même projet ? Car avec tous ces mélanges de "génération C++", ça doit faire une drôle de soupe ! :p


                                          Non, c'est très découpé, et la partie qu'il a développé est autonome. Dans les faits je lui demande une classe qui fait un truc particulier (assez conséquent), on écrit le .hpp ensemble, on discute bien du pourquoi du comment, et ensuite, il implémente la classe avec toutes les sous classe qu'il veut, puis on fait même temps des tests pour savoir si sa classe répond juste à tout ce qu'on lui donne à manger :)
                                          • Partager sur Facebook
                                          • Partager sur Twitter

                                          Recueil de code C et C++  http://fvirtman.free.fr/recueil/index.html

                                          Trop de auto et de template

                                          × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                                          × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                                          • Editeur
                                          • Markdown