Journal Typage statique versus typage dynamique

Posté par  . Licence CC By‑SA.
Étiquettes :
32
8
juil.
2012

Réveillé par le journal précédent sur la transformation de programmes python vers le C, je me suis dit qu'en ce beau dimanche, ce serait cool de lancer le fameux troll "typage statique versus dynamique", mais avec des sources de poids :)

Un mec a transcrit (ligne à ligne !) des programmes python vers haskell pour voir si cela ferait apparaître des bugs grâce au typage statique.
Il n'a bien sûr pas changé le design et suivi celui qui avait été fait avec python.

Il raconte son aventure là : http://evanfarrer.blogspot.ca/2012/06/unit-testing-isnt-enough-you-need.html
En fait c'est plutôt une comparaison "typage dynamique + tests unitaires" vs "typage statique".
Il conclue que les tests unitaires ne remplacent pas le typage statique, et que l'implémentation des programmes ne demande pas de re-conception particulière pour être traduite dans un langage à typage statique.

Et un autre mec en tire quelques conclusions, en particulier sur la bonne utilisation des types pour qu'ils servent à quelque chose et la stupidité du "null" : http://blog.rafaelferreira.net/2012/07/types-and-bugs.html

Et moi je rajoute : mais pourquoi y a-t-il encore des gens pour croire que le typage dynamique a un quelconque avantage ?
Surtout si on a de l'inférence de type !

Bonne journée \o/

  • # Les tests U et les bugs c'est bien, la productivité c'est mieux (mais la conclusion reste la même)

    Posté par  (site web personnel) . Évalué à 10. Dernière modification le 08 juillet 2012 à 20:00.

    Avant même de parler de bugs ou de tests unitaires, on a déjà de très gros problèmes de productivité avec le typage dynamique.

    De par sa nature même, un langage à typage dynamique interdit toute complétion automatique ou assistance à la refactorisation digne de ce nom. Cela ralenti énormément le développement.

    Idem, je ne compte plus le nombre de fois où je me pose la question de ce qu'attend comme paramètre une fonction python ou ce qu'elle est sensée me retourner. Quand ce n'est pas littéralement un gros « data » tout moche, aussi bien en entrée qu'en sortie…
    Développer en Python ou en Ruby, c'est passer plus de temps à regarder ce qu'a codé le voisin pour savoir comment utiliser son API que de coder son propre code.
    (Et qu'on ne me parle pas de Javadoc, Doxygen, Sphinx, ou autre, je n'ai JAMAIS vu une documentation complète et correcte, et encore moins sur des API internes…)
    On est à des années-lumières de la productivité d'un langage à typage statique type Java, où l'IDE va directement sortir les bons types de paramètres de la fonction, voire même y placer les variables disponibles qui correspondent (merci Eclipse !).

    Enfin, la refactorisation de code est juste une hérésie en dynamiquement typé.
    Comme l'IDE ne peut être d'aucune sorte d'utilité, réécrire une méthode, renommer un paramètre ou introduire du polymorphisme ou une super-classe, et on a la quasi-certitude d'une énorme régression qu'on ne détectera qu'à la prochaine exécution (loi de Murphy aidant, la probabilité que cela arrive en production avoisine les 100%…).

    L'étude réalisée par Evan Farrer est intéressante, mais arrive trop tard dans la chaîne de développement.
    Surtout qu'apparement, vu la popularité des librairies analysées, les bugs non détectés ne devaient pas être si méchants et fréquents que ça.
    Avant de penser à corriger du bug ou à implémenter du test unitaire (quoi que TDD, tout ça tout ça, mais je vous laisse imaginer le calvaire en Python ou Ruby…), il faut déjà l'avoir écrit, le code =)

    • [^] # Re:

      Posté par  . Évalué à -3.

      (Et qu'on ne me parle pas de Javadoc, Doxygen, Sphinx, ou autre, je n'ai JAMAIS vu une documentation complète et correcte, et encore moins sur des API internes…)

      C'est peut-être là qu'est le problème.

      On est à des années-lumières de la productivité d'un langage à typage statique type Java, où l'IDE va directement sortir les bons types de paramètres de la fonction, voire même y placer les variables disponibles qui correspondent (merci Eclipse !).>

      Mais, s'il n'y a pas de doc, ce n'est pas vraiment utilisable vu qu'on ne connais pas les conditions sur les paramètres (peut-on mettre un null, une liste vide…)

      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

      • [^] # Re:

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

        Mais, s'il n'y a pas de doc, ce n'est pas vraiment utilisable vu qu'on ne connais pas les conditions sur les paramètres (peut-on mettre un null, une liste vide…)
        Ça peut être un problème certes. Mais idem en dynamique et en statique à ce niveau.
        Et pour les contenus que tu cites :
        * « null », cay mal http://qconlondon.com/london-2009/presentation/Null+References:+The+Billion+Dollar+Mistake
        * Pourquoi une liste vide poserait problème ???

        • [^] # Re:

          Posté par  . Évalué à 3.

          • Pourquoi une liste vide poserait problème ???

          C'est uniquement un exemple, il y a plein de cas limite qui existent et qu'il faut documenter pour utiliser la fonction correctement.

          « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

          • [^] # Re:

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

            Soit le cas est correct, et il doit péter une erreur/exception
            Soit il est incorrect, et il doit conduire à une exécution correcte du code, et surtout ne pas être source d'erreur plus loin dans le code (cas du canard à la con qui passe le « add » et ira péter les plombes plus loin).

            Les cas aux limites seront justement testés unitairement.

            • [^] # Re:

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

              Bon, j'ai tapé trop vite au clavier, il faut bien sûr inverser correct et incorrect :þ

            • [^] # Re:

              Posté par  . Évalué à 5.

              Mais ça n'a aucun rapport avec le fait qu'il faut que ça soit documenter pour l'utiliser. Sinon, ça n'a aucune différence avec le typage dynamique, dans les deux cas on peut mettre des paramètres et voir si ça tourne mais ce n'est vraiment pratique.

              « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

    • [^] # Re: Le titre est trop long

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

      Enfin, la refactorisation de code est juste une hérésie en dynamiquement typé.

      Puis

      quoi que TDD, tout ça tout ça, mais je vous laisse imaginer le calvaire en Python ou Ruby…

      Ça m'a tout l'air d'un gros troll velu mais j'y vais quand même.

      Un code conçu en TDD est refactorisable les doigts dans le nez, quelque soit le type de typage (ah ah) utilisé.

      Et si ton langage de prédilection est java pour faire du test unitaire ou du TDD, je t'encourage vivement à regarder RSpec pour voir ce qu'un framework de test des années 2010 ressemble (et pourtant je ne suis pas un ruby-iste).

      • [^] # Re: Le titre est trop long

        Posté par  (site web personnel) . Évalué à 0. Dernière modification le 08 juillet 2012 à 20:30.

        Un code conçu en TDD est refactorisable les doigts dans le nez, quelque soit le type de typage (ah ah) utilisé.

        Je gros +1 là-dessus.
        Mais faire de la TDD, c'est presque en contradiction avec le typage dynamique, ou en tout cas tout bonnement inutile.
        En effet, tes tests U ne testeront que les cas utilisant les types que TOI tu as bien voulu tester.
        Si un mec te balance un truc qui braille comme un canard, vol comme un canard, nage comme un canard, mais qui n'est pas un canard, tous tes tests U seront potentiellement verts, mais avec un plantage au runtime, sauf à avoir 100% de couverture de code.

        Typiquement, le truc indétectable : http://pastebin.com/NYStSPRe
        Tes tests U ne testeront jamais avec autre chose que du canard, et donc ne détecterons pas le cas où l'utilisateur (entendre aussi un autre développeur) va réellement merder.

        • [^] # Re: Le titre est trop long

          Posté par  . Évalué à 2.

          foo(int, int) est in-détectable non plus, open(string), qui va vérifier si le string est bien un nom de fichier et pas un nom d'oiseau ? On pourrait multiplier les exemples avec tout ce qui touche à l'interface utilisateur (a t'il bien rentré le jour avant le mois ?), ou a une requête sql (le compilateur va-t'il aller vérifier le type des champs d'une bdd ?) etc. Le typage s'adresse au compilateur, pas au développeur, sinon le nommage des paramètres serait obligatoire par ex.

          • [^] # Re: Le titre est trop long

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

            foo(int, int) est in-détectable non plus

            Détectable, car justement, l'utilisateur n'aura aucun moyen de me balancer un « nonInt » en paramètre. Ou s'il le fait, le compilo le rappelera à l'ordre.

            open(string)

            Détectable aussi, via test unitaire.
            Si tu lui passes un nom d'oiseau, typiquement ça doit te balancer un « No such file or directory »

            On pourrait multiplier les exemples avec tout ce qui touche à l'interface utilisateur

            Dans « utilisateur », il y a « utilisateur final », pour qui effectivement, tu dois survérifier tout ce qu'il est susceptible de te balancer, mais aussi « autre développeur » (aussi bien de ta propre équipe, mais peut-être aussi d'une autre équipe qui utilise ton API).

            Le cas du canard à la con, c'est typiquement le cas d'un co-dev Python qui a fait son propre objet en mimant ce qu'il a pu déjà voir ailleurs, mais en omettant tout ce qui était du domaine des API internes, pourtant nécessaires au bon fonctionnement de l'application.
            Dans le code de mon paste, c'est typiquement dès les 1ères lignes que le développeur de l'API aurait du refuser le canard boiteux (« f.addDuck(aFakeDuckWithoutFeathers) »). Sauf que pour faire ça, il aurait fallu avoir connaissance de toutes les méthodes que l'application est potentiellement en droit d'appeler sur l'objet en question. Littéralement impossible… sauf à réimplémenter du typage statique !

            • [^] # Re: Le titre est trop long

              Posté par  . Évalué à 7.

              foo(int, int) est in-détectable non plus
              

              Détectable,

              def date_de_naissance(int, int, int)

              date_de_naissance(2010, 9, 14)
              date_de_naissance(9, 10, 3923)

              Le compilo ne détecte rien du tout, ni l'ordre des paramètres ni leur cohérence. On se retrouve exactement dans le même cas qu'avec tes canards.

              Si on veut être prudent on va dire
              date_de_naissance(jour, mois, annee)

              date_de_naissance(jour=4, mois=3, annee=1950)
              L'interpréteur ne va rien vérifier du tout mais on a beaucoup moins de chance de se tromper.

              Le compilateur va trouver certaines fautes, c'est incontestable, mais si c'est au détriment d'un code beaucoup plus lourd le gain est annulé et même inversé. Du moins c'est ce que j'ai constaté en passant de Java à Python par ex.

              • [^] # Re: Le titre est trop long

                Posté par  . Évalué à 5.

                Tu peux définir des sous types d'entiers nommés, genre des plages d'entiers "mois" 1..12 dans certains langages.

                • [^] # Re: Le titre est trop long

                  Posté par  . Évalué à 1.

                  Ça s'appelle de la sécurisation des entrées. On est plus dans des considérations de typage mais plutôt des considérations fonctionnelles.

                  • [^] # Re: Le titre est trop long

                    Posté par  . Évalué à 10.

                    Non je parle bien de typage en l'occurence : http://en.wikibooks.org/wiki/Ada_Programming/Types/range par exemple.

                    • [^] # Re: Le titre est trop long

                      Posté par  . Évalué à 1.

                      Non mais je sais qu'on peut le faire en Ada en l'occurence, mais quand tu utilises ce genre de sous-typage, on est rendu bien loin du débat initial et on entre dans un autre champs de considération.

                      • [^] # Re: Le titre est trop long

                        Posté par  . Évalué à 8.

                        Je vois pas en quoi c'est si loin du débat initial. Si on parle du typage d'Haskel et de son inférence de type, du fait qu'avec lui il faut déplacer la complexité dans les types et pas dans les algorithmes, on peut tout a fait parler du typage d'Ada et de sa capacité à spécifier beaucoup de choses dans le type.

                        D'ailleurs c'est possible avec tout langage objet typé statiquement sauf qu'au lieu de créer des types limités il faut créer des classes qui encapsule le type.

                        Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                        • [^] # Re: Le titre est trop long

                          Posté par  . Évalué à 1.

                          Éloigné dans le sens statique vs. dynamique. Mécaniquement parlant, que t'es une notion de sous-type qui sont des types de base avec une contrainte ne change rien au fonctionnement derrière. Oui tu vas lever plus d'erreurs de typage qu'avec un langage qui n'a pas ce mécanisme, oui ça permet déplacer une partie de la complexité liée à ça dans la déclaration du type. Dis moi que ce n'est pas purement fonctionnel (syn. pratique), et utilisé pour sécuriser tes données en entrée d'algo ?

                          D'ailleurs c'est possible avec tout langage objet typé statiquement sauf qu'au lieu de créer des types limités il faut créer des classes qui encapsule le type.

                          Attends, là faut que tu m'expliques où tu veux en venir, parce que la première idée qui me vient avec ça, mis à part que tu vas lever une erreur à la compil si tu pousses pas un objet d'une classe compatible, la vérification des valeurs que tu assignes à ton type encapsulé tu vas ne la faire qu'au runtime dans le constructeur … donc à mes yeux ça ne ferait pas une grosse différence avec un wrapper sur ton algo chargé de vérifier les entrées par exemple (à de la factorisation de code près)

                          • [^] # Re: Le titre est trop long

                            Posté par  . Évalué à 2.

                            Dis moi que ce n'est pas purement fonctionnel (syn. pratique), et utilisé pour sécuriser tes données en entrée d'algo ?

                            Je vois pas ce que tu veux dire. Ça peut servir à déterminer la taille en mémoire de la variable. À quoi tu vaudrais que ça serve ?

                            Attends, là faut que tu m'expliques où tu veux en venir, parce que la première idée qui me vient avec ça, mis à part que tu vas lever une erreur à la compil si tu pousses pas un objet d'une classe compatible, la vérification des valeurs que tu assignes à ton type encapsulé tu vas ne la faire qu'au runtime dans le constructeur … donc à mes yeux ça ne ferait pas une grosse différence avec un wrapper sur ton algo chargé de vérifier les entrées par exemple (à de la factorisation de code près)

                            Tu as raison je ne devais pas encore être bien éveillé.

                            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                            • [^] # Re: Le titre est trop long

                              Posté par  . Évalué à 1. Dernière modification le 09 juillet 2012 à 11:13.

                              Quand tu fais un range en Ada, la fonctionnalité que tu cherches, c'est pas la taille en mémoire, le surtype le fait déjà (modulo des optimisations du compilo), c'est surtout vérifier que tu assignes des valeurs dans les bornes la vraie valeur ajoutée.

                              • [^] # Re: Le titre est trop long

                                Posté par  . Évalué à 2.

                                Ça te permet d'organiser ton code au même titre que le typage d'Haskell, je vois pas qu'elle est la différence.

                                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                          • [^] # Re: Le titre est trop long

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

                            Éloigné dans le sens statique vs. dynamique. Mécaniquement parlant, que t'es une notion de sous-type qui sont des types de base avec une contrainte ne change rien au fonctionnement derrière.

                            bah, justement, le système de typage d'Ada te permet de faire des choses statiquement (par contre, pas avec des sous-types). Par exemple :

                            procedure Annee is
                               type Annee is new Integer;
                            
                               procedure Date(A : Annee) is begin null; end;
                            
                               Toto: Integer := 2012;
                            begin
                               Date(Toto);
                            end Annee;
                            
                            

                            Le compilo va râler à la compil :

                            annee.adb:8:09: expected type "Annee" defined at line 2
                            annee.adb:8:09: found type "Standard.Integer"
                            
                            

                            J'aurais pu en plus ajouter une contrainte sur mon type Annee, mais c'est un autre problème.

                            • [^] # Re: Le titre est trop long

                              Posté par  . Évalué à -1.

                              C'est le genre d'exemple qui illustre bien pourquoi faire simple quand on peut faire compliqué juste pour faire plaisir au compilo. L'algo va être complètement noyé, le développeur va passer un temps fou à gérer les types au lieu de s'intéresser à l'algo.

                              • [^] # Re: Le titre est trop long

                                Posté par  . Évalué à 7.

                                Un programme bien typé est à l’abri des erreurs non détectées à l’exécution. Cette garantie de correction (partielle) n'est vraiment pas chère payée.

                                Please do not feed the trolls

                                • [^] # Re: Le titre est trop long

                                  Posté par  . Évalué à 1.

                                  Regarde le code qu'il faut écrire en Java pour lire un fichier texte, au prix où est la ligne aujourd'hui j'ai pas les moyens :-)

                                  • [^] # Re: Le titre est trop long

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

                                    FileUtils.readFileToString(new File("foo"))
                                    
                                    
                                    • [^] # Re: Le titre est trop long

                                      Posté par  . Évalué à 1.

                                      Tu vois, toi-même tu préfère écrire du java comme si c'était du python ;-)
                                      Il manque quelques décorations autour non ? et il faut carrément une bibliothèque externe pour ça. tu as même oublié le ; !

                                      • [^] # Re: Le titre est trop long

                                        Posté par  . Évalué à 5.

                                        Et quand t'arrête de faire des Hello world, des projets d'école et de coder dans ton coin ça donne quoi ?

                                        Par ce que la réalité c'est des codes volumineux qui ont 10 ans, modifiés par des dizaines de personnes dont beaucoup ont quitté le navire avec leurs connaissance. Les objectifs et les technos ont changés en cours de route, on a refactoré dans tout les sens pour s'adapter au besoin. On a des besoins de backward/forward compat. Lire un fichier texte comme une String en on s'en balance un peu, l'informatique ce n'est pas ça.

                                        • [^] # Re: Le titre est trop long

                                          Posté par  . Évalué à 2.

                                          Et quand t'arrête de faire des Hello world, des projets d'école et de coder dans ton coin ça donne quoi ?

                                          Si l'expérience est un critère, ça fait bientôt 20 ans que je code à mon compte et que je dois donc assumer tous les choix d'outils de développement que j'ai fais. Si je fais du prosélytisme autour de Python c'est que ma fois je lui dois sûrement ma maison et tout le temps que je peux passer avec mes enfants. Je me souviens de la période où je programmais en Java, en vacance j'avais toujours un livre avec moi !

                                          Tu remarqueras un jour petit scarabée que la programmation n'est qu'une suite de petites choses toutes simples que l'on s'évertue bien souvent à compliquer inutilement.

                                          • [^] # Re: Le titre est trop long

                                            Posté par  . Évalué à 9. Dernière modification le 10 juillet 2012 à 03:20.

                                            D'un autre côté faire la remarque qu'il faut une bibliothèque pour lire un fichier en sous entendant qu'il existe des langages où c'est implémenté genre par magie, quand on a 20 ans d'xp c'est triste.

                                            • [^] # Re: Le titre est trop long

                                              Posté par  . Évalué à 4.

                                              En shell ça existe avec l'opérateur < :D

                                              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                          • [^] # Re: Le titre est trop long

                                            Posté par  . Évalué à 4.

                                            Si l'expérience est un critère, ça fait bientôt 20 ans que je code à mon compte

                                            Voilà l'explication. Pour coder tout seul sur une base de code que tu maîtrises à 100%, dont tu as tout l'historique et l'évolution en tête et dont tu connais parfaitement le domaine fonctionnel un langage très flexible est effectivement souvent une facilité. Quand je fais un truc pour moi, une bibliothèque simple, ou une petite appli j'aime bien Python.

                                            Le problème c'est que ça à du mal à passer à l'échelle quand tu enlèves une ou plusieurs de ces conditions.

                                            • [^] # Re: Le titre est trop long

                                              Posté par  . Évalué à 3.

                                              Voilà l'explication. Pour coder tout seul sur une base de code que tu maîtrises à 100%, dont tu as tout l'historique et l'évolution en tête et dont tu connais parfaitement le domaine fonctionnel un langage très flexible est effectivement souvent une facilité.

                                              Je code souvent tout seul mais j'utilise quand même des bibliothèques externes, parfois j'y contribue. Donc si ça ne devait pas impacter mon propre code, ça devrait quand même avoir un impact sur ma capacité à pouvoir utiliser celui des autres. Hors non, comme je l'ai déjà écrit, je passe moins de temps sur les bibliothèques externes qu'avant et je peux plus facilement contribuer à des bibliothèques externes…

                                      • [^] # Re: Le titre est trop long

                                        Posté par  (site web personnel) . Évalué à 3. Dernière modification le 09 juillet 2012 à 20:16.

                                        Tu vois, toi-même tu préfère écrire du java comme si c'était du python ;-)

                                        Il me dit que ça prenait trop de lignes, je lui montre que non =)
                                        Il n'a pas dit que cela devait être robuste.
                                        Auquel cas de toute façon, Java est largement devant Python et Python moins robuste car non typé.

                                        List<String> read(String name) throws IOException
                                          try (File file = new File(name)) {
                                            return FileUtils.readFileToString(file);
                                          }
                                        }
                                        
                                        
                                        • Pas de risque d'avoir autre chose qu'un String en paramètre
                                        • Pas de risque de conserver le fichier ouvert en cas d'erreur lors du readFileToString (autoclose)
                                        • Garantie que le type de retour est bien une liste de String…
                                        def read(name):
                                          '''
                                            Lit l'intégralité d'un fichier
                                            @param name : chemin du fichier à lire
                                            @return lignes du fichier
                                          '''
                                          with open(name, 'r') as file
                                            return file.readline()
                                        
                                        
                                        • Qui a fait un test U pour voir ce que ça fait si je lui passe un Int ou un Canard en paramètre ?
                                        • Si répondu « moi » à la question précédente, ça fait quoi avec une Voiture ou un Path ou Obiwan ou … ?
                                        • Comment ça cette fonction peut lever une exception ?
                                        • Comment ça cette fonction peut lever une exception à 2 endroits ?
                                        • Ça me retourne quoi ? Un tuple, une liste, un array, un dictionnaire { n° de ligne, contenu } ?

                                        5 lignes en Java, 8 en Python, au coût de la ligne, je prend Java !!!
                                        Et en plus, trouve-moi un seul mec qui va m'écrire ce code python du 1er coup…
                                        Généralement, j'obtient plutôt

                                        def read(name):
                                          file = open(name, 'r')
                                          return file.readline()
                                        
                                        

                                        et il faut carrément une bibliothèque externe pour ça

                                        Au prix où est Maven, je ne vais pas me géner non plus =)
                                        Ça m'évitera même d'écrire la moindre ligne de code…
                                        D'ailleurs, au prix où est la ligne…

                                        • [^] # Re: Le titre est trop long

                                          Posté par  . Évalué à 1.

                                          Tu arrives à écrire plus de code en python qu'en java, trop fort, je ne peux que m'incliner.

                                        • [^] # Re: Le titre est trop long

                                          Posté par  . Évalué à 1.

                                          Et en plus, trouve-moi un seul mec qui va m'écrire ce code python du 1er coup…

                                          Personne en effet, car faire une fonction dédiée à quelque chose d'aussi trivial est stupide.
                                          Désolé, mais cet exemple ne montre que ta propre incompétence.

                                          Python moins robuste car non typé

                                          Python est fortement typé, c'est juste que le typage est dynamique et non statique.

                                        • [^] # Re: Le titre est trop long

                                          Posté par  . Évalué à 4.

                                          En fait ton exemple python n'a en effet que peut d’intérêt (à cause du open qui prend le path d'un fichier)
                                          en plus de duckfriendly:

                                          def readToArray anInput
                                            arr = []
                                            begin
                                              anInput.open
                                              anInput.each { |elm| arr << elm }
                                            ensure
                                              anInput.close
                                            end
                                          end
                                          
                                          

                                          Cela fait toujours plus que ton exemple java, mais cela me permet d'utiliser cette méthode sur tout type pouvant s'itérer, que ce soit un fichier, un tableau excel, une main (pour lire les ligne de la main… bon ok ;) ), là où dans ton exemple il faudrait sous classer file et/ou recoder un tas de trucs

                                          Qui a fait un test U pour voir ce que ça fait si je lui passe un Int ou un Canard en paramètre ?
                                          Si répondu « moi » à la question précédente, ça fait quoi avec une Voiture ou un Path ou Obiwan ou … ?

                                          On s'en fout, ton test U doit être sur que pour un type itérant, la méthode te renvoi un tableau contenant chaque élément de ce type, au dev qui développera ce type de faire les tests U qui confirme que son objet c'est ouvrir/itérer/fermer
                                          Ceci dit je t'accorde qu'à la relecture, ton exemple "s'autodocumente" mieux

                                          Bon c'est vrai que je saute de votre troll java/python vers un troll canard/pas canard. De plus je fais moi même le lien entre typage dynamique et ducktyping, alors qu'il est possible d'en faire avec certains langages statiques dont le c++

                                          • [^] # Re: Le titre est trop long

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

                                            Cela fait toujours plus que ton exemple java, mais cela me permet d'utiliser cette méthode sur tout type pouvant s'itérer, que ce soit un fichier, un tableau excel, une main (pour lire les ligne de la main… bon ok ;) ), là où dans ton exemple il faudrait sous classer file et/ou recoder un tas de trucs

                                            J'aime pas cette philosophie du « Un anneau pour les gouverner tous ».
                                            Parce qu'après, on essaie de tout faire rentrer pour pouvoir utiliser cette méthode, quitte à dévier un peu de ce qu'on aurait du réellement faire. Par exemple ici, y'a fort à parier qu'un gus ira inventer des open/close dummy rien que pour se faire plaisir d'utiliser cette méthode…
                                            Et à l'inverse, on va plâtrer méchamment cette méthode dans tous les coins pour traiter toutes les petites subtilités à la con (« Ah oui mais mon fichier est déjà ouvert et/ou je ne veux pas le fermer », etc), en gardant une compatibilité afin de ne pas casser les 99 autres % de l'application qui utilisent cette méthode:

                                            def readToArray anInput
                                              arr = []
                                              begin
                                                if isinstanceof(anInput, file) and file.isOpen():
                                                  open = false
                                                else:
                                                  open = true
                                                  anInput.open
                                                anInput.each { |elm| arr << elm }
                                              ensure
                                                if open:
                                                  anInput.close
                                              end
                                            end
                                            
                                            

                                            (ne rigolez pas, j'ai déjà vu des trucs comme ça, y compris dans des libs python ultra-utilisées…)

                                            Non, pour moi, un fichier ne doit pas être lu par la même méthode qu'un main ou qu'une table excel. Que le comportement derrière soit mutualisé si possible via du polymorphisme, c'est autre chose.
                                            Ça a l'énorme avantage de pouvoir isoler les choses facilement si (comprendre « quand ») une évolution future arrivera.

                                            On s'en fout, ton test U doit être sur que pour un type itérant, la méthode te renvoi un tableau contenant chaque élément de ce type, au dev qui développera ce type de faire les tests U qui confirme que son objet sait ouvrir/itérer/fermer

                                            Sauf que sans aller voir ta méthode, et même avec toute la meilleure volonté du monde, sans aller voir dans ton code, je n'aurais AUCUN moyen de savoir que je dois répondre à open, each et close !
                                            Sans parler que plus je vais aller vers les couches hautes, plus les tests que tu demandes seront impossibles à vérifier, vu la quantité effroyable de comportements qu'un simple objet devra respecter !

                                            • [^] # Re: Le titre est trop long

                                              Posté par  . Évalué à 4.

                                              Ton exemple crade ne me parait pas pertinent, je ne nie pas que cela puisse exister, mais même sans ducktyping j'ai vu des choses tout aussi laide pour faire rentrer des types lanternes dans le type vessie.

                                              Sauf que sans aller voir ta méthode, et même avec toute la meilleure volonté du monde, sans aller voir dans ton code, je n'aurais AUCUN moyen de savoir que je dois répondre à open, each et close !

                                              D'où ce que je disais plus haut, il est impossible de faire du ducktyping sans être rigoureux et écrire de la doc et des tests. Mais un système de contrat manque en effet.
                                              le problème se pose également sans ducktype, en effet le fait de connaitre la signature permet déjà d'avoir pas mal d'info sur ta méthode, néanmoins je ne sais pas pour autant si le fichier doit être ouvert ou pas, si il est fermé à la fin de la méthode, voir quelles ressources sont instanciées et libérées

                                        • [^] # Re: Le titre est trop long

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

                                          Ah non, moi je lit 3 lignes de python, pas 8. Si tu comptes la docstring python faut que tu comptes aussi la javadoc pour être cohérent.

                                          5 lignes en Java, 3 en Python, au coût de la ligne, je prend Python !!!

                                          Et en plus, trouve-moi un seul mec qui va m'écrire ce code python du 1er coup…

                                          Et trouve moi un seul mec qui va m'écrire ce code java du 1er coup…

                                          Généralement, c'est plutôt (exemple pris d'ici (4em résultat de la recherche google "java readfile"):

                                          public ArrayList read () throws java.io.FileNotFoundException, java.io.IOException
                                          {
                                              FileReader fr = new FileReader (this.getFileName());
                                              BufferedReader br = new BufferedReader (fr);
                                              ArrayList aList = new ArrayList (this.getBufferSize());
                                          
                                              String line = null;
                                              while (     (line = br.readLine()) != null)
                                              {
                                                  aList.add(line);
                                              }
                                          
                                              br.close();
                                              fr.close();
                                          
                                              return aList;
                                          }
                                          
                                          

                                          Matthieu Gautier|irc:starmad

                                          • [^] # Re: Le titre est trop long

                                            Posté par  . Évalué à 6.

                                            Ah non, moi je lit 3 lignes de python, pas 8. Si tu comptes la docstring python faut que tu comptes aussi la javadoc pour être cohérent.

                                            5 lignes en Java, 3 en Python, au coût de la ligne, je prend Python !!!

                                            Non c'est plutôt cohérent avec ce qui avait était dis au dessus comme quoi le typage statique est remplacé par de la doc. Si c'est pour indiquer les types d'entrées et de sortie ça ne sert strictement en rien en Java.

                                            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                            • [^] # Re: Le titre est trop long

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

                                              Et en quoi "@return lignes du fichier" m'indique le type retourné ? String, liste de string ? tuple de string ? générateur de string ? (ESOF des trois derniers tant que c'est un iterable de string ?)

                                              List<String> read(String name)
                                              
                                              

                                              Et en quoi, quand je lit juste la signature de la fonction, je sais que "name" doit être le chemin (absolu?) d'un fichier ? Et que ça retourne le contenu du fichier ?

                                              Non c'est plutôt cohérent avec ce qui avait était dis au dessus comme quoi le typage statique est remplacé par de la doc.

                                              Pour moi c'est un bien pour un mal. Tu gagnes en flexibilité mais faut être un peu plus carré sur ce que tu fais (ce que tous le monde ne fait pas, moi le premier).

                                              Après je vous l'accorde, il manque peut être à python un truc permettant de définir l'interface attendu des arguments (mais je suis pas totalement sûr, un canard peut avoir des plumes après être entré dans la ferme).

                                              Matthieu Gautier|irc:starmad

                                              • [^] # Re: Le titre est trop long

                                                Posté par  . Évalué à 3.

                                                Après je vous l'accorde, il manque peut être à python un truc permettant de définir l'interface attendu des arguments (mais je suis pas totalement sûr, un canard peut avoir des plumes après être entré dans la ferme).

                                                Je pense que ça pourrait être bien pour les bibliothèques.

                                                Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                          • [^] # Re: Le titre est trop long

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

                                            Ah non, moi je lit 3 lignes de python, pas 8. Si tu comptes la docstring python faut que tu comptes aussi la javadoc pour être cohérent.

                                            Non, car la javadoc est facultative pour le développement (elle est même presque complètement interdite dans mes équipes de dev, un code qui a besoin d'une doc est un code qui doit être réécrit !), alors que la docstring python est obligatoire sous peine de ne pas savoir quoi passer en paramètre et ce qui est retourné !
                                            La javadoc est vraiment du domaine de la documentation, alors que la docstring est du domaine du développement.

                                            Et trouve moi un seul mec qui va m'écrire ce code java du 1er coup…

                                            Je te l'accorde, mais je pense que le niveau minimal en Java qui conduira à écrire ce code naturellement est bien plus faible que celui de Python.
                                            J'aurais même tendance à dire que la culture Java-iste a tendance à inculquer ce genre de bonne pratique assez tôt, ce qui n'est pas le cas de Python où c'est plutôt généralement du DIY.
                                            Je ne suis même pas sûr que la personne qui déclare ici avoir 20 ans d'expérience Python l'aurait écrit comme ça…

                                            • [^] # Re: Le titre est trop long

                                              Posté par  . Évalué à 4.

                                              Je n'ai jamais dis que j'avais 20 ans d'xp en python, j'ai fais du java, du C etc aussi (j'en ai mangé du statique !)… Mais je ne veux pas mettre mon xp en avant, la durée n'a rien à voir avec la qualité, c'était juste pour témoigner.

                                              L'avantage en python c'est que le code (pour lire un fichier ou autre) ne sera pas forcément le même suivant le contexte. Il sera très robuste si c'est nécessaire sinon il ne sera pas inutilement lourd.
                                              Par exemple un accès fichier robuste devrait obligatoirement faire un contrôle sur le chemin, tout comme une date de naissance devra vérifier qu'elle est cohérente, ce qui est une erreur bien plus fréquente. La vérification du type et la lourdeur obligatoire autour fait faussement croire que le code va être robuste. Il n'est robuste que pour le compilateur, pas pour l'utilisation.
                                              Un bon exemple où la lourdeur n'est pas nécessaire (et dissuasive) c'est quand on écrit des tests unitaires par ex. Je me sert souvent des tests unitaires comme documentation, il faut qu'ils soient le plus concis possibles. Dans un test unitaire, lire un fichier texte ça doit tenir sur une ligne sans nécessiter de bibliothèque tierce. L'idéal serait je pense d'avoir du typage statique que quand c'est nécessaire, il y a des prémices en python il me semble et on peut déjà utiliser des outils comme pylint pour faire certains contrôles avant exécution, mais au moins ça n'interdit pas les avantages du dynamique et interprété.

                                            • [^] # Re: Le titre est trop long

                                              Posté par  . Évalué à 8.

                                              un code qui a besoin d'une doc est un code qui doit être réécrit !

                                              C'est la perle du jour. J'espère que tes clients sont au courant.

                                              • [^] # Re: Le titre est trop long

                                                Posté par  (site web personnel) . Évalué à 3. Dernière modification le 10 juillet 2012 à 13:12.

                                                En quoi est-ce une perle ?
                                                À partir du moment où tu as la nécessité de documenter ton code parce qu'il n'est pas compréhensible, pourquoi ne pas plutôt le refactorer pour le rendre justement compréhensible sans doc ?
                                                Connaissant la propension de la doc à devenir fausse avec le temps, je préfère un code auto-porteur compréhensible sans doc qu'un code pas compréhensible avec une doc fausse.
                                                Et un code compréhensible documenté, du coup c'est de la perte de temps et du bruit…

                                                Après oui, je vais quand même documenter les morceaux vraiment « impropifiables », type les algos bas niveaux ou les trucs vraiment mathématiques.

                                                Et oui, tout le monde est au courant =)

                                                • [^] # Re: Le titre est trop long

                                                  Posté par  . Évalué à 2.

                                                  Fait gaffe, ça fait deux fois que tu penche vers des méthodes toutes pythonesques ;-)

                                                  • [^] # Re: Le titre est trop long

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

                                                    En même temps niveau code pythonesque, encore trouvé dans le code de DJango aujourd'hui

                                                    241         if not isinstance(result, (list, tuple)):                                                                                        
                                                    242             result = [result]
                                                    
                                                    

                                                    On est clairement dans le cas « Ah wé mais merde, les mecs me passent aussi un singleton et pas une liste en paramètre, aller, ça va passer quand même… ».
                                                    Généralement, c'est aussi pour se simplifier la vie et pouvoir appeler du foo(toto) au lieu de foo([toto]).

                                                    Soit on fait du vrai duck-typing, et donc on arrête de se limiter qu'au list et tuple et on prend aussi du seq, du generator et tout ce qui est itérable. Et je met au défi quiconque ici de me donner le code python qui permettra de faire ça :þ
                                                    Soit on fait du vrai typing, et donc on arrête le python.

                                                    • [^] # Re: Le titre est trop long

                                                      Posté par  . Évalué à 3.

                                                      Le ducktyping n'est pas une contrainte, c'est une possibilité.

                                                      Soit on fait du vrai typing, et donc on arrête le python.

                                                      le ducktyping n'est pas une spécifité ni de python, ni des langages à typage dynamique (même si je fais moi même souvent le raccourci)

                                                    • [^] # Re: Le titre est trop long

                                                      Posté par  (site web personnel) . Évalué à 0. Dernière modification le 10 juillet 2012 à 13:58.

                                                      def function(input):
                                                          """
                                                          Take an input that may be a iterable or not.
                                                          """
                                                      
                                                          if isinstance(input, basetring):
                                                              """ basetring is the only particular case as it is also an iterable"""
                                                              do_the_stuff(input)
                                                          else:
                                                              try:
                                                                  iterable = (x for x in input)
                                                              except TypeError:
                                                                  iterable = (input, )
                                                              for i in iterable:
                                                                  do_the_stuff(i)
                                                      
                                                      

                                                      Matthieu Gautier|irc:starmad

                                                      • [^] # Re: Le titre est trop long

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

                                                        Je m'y attendais à celle-là =)

                                                        def foo():
                                                           yield 1
                                                        
                                                        function(foo())
                                                        
                                                        

                                                        Je vais attendre un bail…
                                                        Same player shoot again ?

                                                        • [^] # Re: Le titre est trop long

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

                                                          Et ?

                                                          foo() retourne un générateur qui est un iterable. Il est où le problème ?

                                                          Matthieu Gautier|irc:starmad

                                                          • [^] # Re: Le titre est trop long

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

                                                            Un générateur peut être infini.
                                                            Et donc ton code ne jamais se finir, alors que le do_stuff lui pouvait se finir sans ton test d'iterable (condition d'arrêt, utilisation de seulement certaines valeurs, etc).

                                                            def foo():
                                                              while True:
                                                                yield 1
                                                            
                                                            function(foo())
                                                            
                                                            
                                                            • [^] # Re: Le titre est trop long

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

                                                              Ben c'est pas le même problème aussi.

                                                              def function(input):
                                                                  """
                                                                  Take an input that may be a iterable or not.
                                                                  """
                                                              
                                                                  iterable = None
                                                                  if isinstance(input, basestring):
                                                                      """ basestring is the only particular case as it is also an iterable"""
                                                                      iterable = (input, )
                                                                  else:
                                                                      try:
                                                                          iterable = (x for x in input)
                                                                      except TypeError:
                                                                          iterable = (input, )
                                                                  if iterable is not None:
                                                                      do_the_stuff(iterable)
                                                              
                                                              

                                                              C'est mieux comme ça ?
                                                              (En même temps, tu me donnes un itérable infini et tu me demandes de boucler dessus, je m’arrête jamais moi. Quel que soit le langage ou le typage)

                                                              Matthieu Gautier|irc:starmad

                                                              • [^] # Re: Le titre est trop long

                                                                Posté par  . Évalué à 6.

                                                                D'un point de vue perf c'est quand même juste abominable ce genre de trucs.

                                                                • [^] # Re: Le titre est trop long

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

                                                                  À oui ? Parce qu'il y a un générateur au milieu ? On fait du python je te rappelle, c'est pas les appels de fonction qui coute le plus cher. (surtout que c'est un générateur "builtin", donc optimisé)

                                                                  Matthieu Gautier|irc:starmad

                                                                  • [^] # Re: Le titre est trop long

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

                                                                    Non, parce qu'on va parcourir 2× l'itérable dans le cas où l'objet est réellement itérable.

                                                                    • [^] # Re: Le titre est trop long

                                                                      Posté par  . Évalué à 2.

                                                                      Tu sais pas si ça se trouve do_stuff n'itère pas (oui oui je sais :)

                                                                      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                                                      • [^] # Re: Le titre est trop long

                                                                        Posté par  (site web personnel) . Évalué à 1. Dernière modification le 10 juillet 2012 à 15:30.

                                                                        Sauf que function ne parcourt pas l'iterable, donc ça se trouve on l'itère jamais.

                                                                        Matthieu Gautier|irc:starmad

                                                                        • [^] # Re: Le titre est trop long

                                                                          Posté par  . Évalué à 2.

                                                                          $ python -m timeit "for i in range(1000000): pass"
                                                                          10 loops, best of 3: 48.9 msec per loop
                                                                          $ python -m timeit "for i in (x for x in range(1000000)): pass"
                                                                          10 loops, best of 3: 156 msec per loop
                                                                          $ python -m timeit "for i in xrange(1000000): pass"
                                                                          10 loops, best of 3: 26.5 msec per loop
                                                                          $ python -m timeit "for i in (x for x in xrange(1000000)): pass"
                                                                          10 loops, best of 3: 131 msec per loop

                                                                          On peut faire la conso mémoire, le coût du isinstance et de l'exception aussi si tu veux. Surcout de la version avec polymorphisme adhoc: 0%.

                                                                          • [^] # Re: Le titre est trop long

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

                                                                            Ok,

                                                                            def function(input):
                                                                                """
                                                                                Take an input that may be a iterable or not.
                                                                                """
                                                                            
                                                                                iterable = input
                                                                                try:
                                                                                    (x for x in input)
                                                                                except TypeError:
                                                                                    iterable = (input, )
                                                                                else:
                                                                                    """ it is an iterable, maybe it is a string """
                                                                                    if isinstance(input, basestring):
                                                                                        """ basestring is the only particular case as it is also an iterable"""
                                                                                        iterable = (input, )
                                                                                do(iterable)
                                                                            
                                                                            

                                                                            Et maintenant ?

                                                                            On peut faire la conso mémoire, le coût du isinstance et de l'exception aussi si tu veux. Surcout de la version avec polymorphisme adhoc: 0%.
                                                                            Tu fais comment avec du polymorphisme à 0% de surcout ?

                                                                            Pour le cout de l'exception, ça dépend surtout de la proba que tu passes un itérable ou pas. Si c'est principalement des itérables, ton exception occasionnelle ne coute pas bien chère face à un if que tu fais tout le temps (http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Initializing_Dictionary_Elements)

                                                                            Quant au isinstance, effectivement, j'ai pas d'autre solution qui limiter le test au cas où on sait que l'on a déjà un itérable.

                                                                            Matthieu Gautier|irc:starmad

                                                                            • [^] # Re: Le titre est trop long

                                                                              Posté par  . Évalué à 2.

                                                                              Le polymorphisme adhoc c'est toujours 0% par définition (et tu ne peux pas faire autre chose en Python). Le polymorphisme paramétrique ca a un coût de nul (on peut savoir à la compile) à faible.

                                                                              Pour la proba tu te fous du monde. Si tu offres cette possibilité c'est que tu estimes aussi probable de prendre une entrée que l'autre et dans tout les cas tu ne peux pas le reprocher à l'utilisateur c'est dans ton contrat. Bref si tu généralises cette approche ca coute vite un max pour rien…

                                                                              • [^] # Re: Le titre est trop long

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

                                                                                Je te rappelle l'énoncé du problème:

                                                                                On est clairement dans le cas « Ah wé mais merde, les mecs me passent aussi un singleton et pas une liste en paramètre, aller, ça va passer quand même… ».
                                                                                Généralement, c'est aussi pour se simplifier la vie et pouvoir appeler du foo(toto) au lieu de foo([toto]).

                                                                                Soit on fait du vrai duck-typing, et donc on arrête de se limiter qu'au list et tuple et on prend aussi du seq, du generator et tout ce qui est itérable. Et je met au défi quiconque ici de me donner le code python qui permettra de faire ça :þ

                                                                                La fonction, à la base, elle prend une liste, pas n'importe nawak.

                                                                                Je te repose la question, tu fais comment avec du polymorphisme adhoc ?

                                                                                Matthieu Gautier|irc:starmad

                                                                                • [^] # Re: Le titre est trop long

                                                                                  Posté par  (site web personnel) . Évalué à -1. Dernière modification le 10 juillet 2012 à 17:12.

                                                                                  La fonction, à la base, elle prend une liste, pas n'importe nawak.

                                                                                  Pk elle prend une liste ? Un tuple est tout aussi autorisé, comme tout ce qui peut être itérable. On fait du python ou pas à la fin ?

                                                                  • [^] # Re: Le titre est trop long

                                                                    Posté par  . Évalué à 2.

                                                                    Par ce que dans tout les cas tu te prends une claque à l'exec, y'a même pas un chemin d'exécution qui est épargné.
                                                                    - Tu passes un itérable, t'itères dessus et tu la reconstruis (mémoire + cpu)
                                                                    - Tu passes que des non itérables tu t'exploses une exception (cpu)

                                                                    Dès que tu rentres dans un cas pathologique type méthode toujours appelée avec un non itérable, gros itérable etc. tu prends un facteur vertigineux par rapport à une version avec polymorphisme paramétrique… pour rien.

                                                                    • [^] # Re: Le titre est trop long

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

                                                                      http://pastebin.com/xteDw182

                                                                      Et là vous comprenez la différence entre generator expression et list comprehension ?

                                                                      Matthieu Gautier|irc:starmad

                                                                      • [^] # Re: Le titre est trop long

                                                                        Posté par  . Évalué à 2. Dernière modification le 10 juillet 2012 à 16:42.

                                                                        Maintenant que tu as ton code. Tu changes do pour virer le print et le break à 10 pour consommer toute la liste. Et tu appelles function avec range(10000000).

                                                                        Tu ajoutes function2 qui ne fait que do(input) sans vérification de type. Tu peux constater que tu as un facteur 2 entre les deux versions.

                                                                        Maintenant tu remodifies ton code pour faire une boucle dans laquelle tu appelles function avec 1 en paramètre puis ensuite function2 avec [1]. La maintenant tu as plus d'un facteur 4.

                                                                        • [^] # Re: Le titre est trop long

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

                                                                          Maintenant que tu as ton code. Tu changes do pour virer le print et le break à 10 pour consommer toute la liste. Et tu appelles function avec range(10000000).

                                                                          Tu ajoutes function2 qui ne fait que do(input) sans vérification de type. Tu peux constater que tu as un facteur 2 entre les deux versions.

                                                                          Avec la fonction du commentaire https://linuxfr.org/nodes/94784/comments/1367242

                                                                          def do(it):
                                                                             for i in it:
                                                                                pass
                                                                          
                                                                          print timeit.timeit("function(xrange(10000000))", "from __main__ import function", number=100)
                                                                          # 21.3466279507
                                                                          print timeit.timeit("do(xrange(10000000))", "from __main__ import do", number=100)
                                                                          # 21.0114998817
                                                                          
                                                                          

                                                                          Maintenant tu remodifies ton code pour faire une boucle dans laquelle tu appelles function avec 1 en paramètre puis ensuite function2 avec [1]. La maintenant tu as plus d'un facteur 4.

                                                                          print timeit.timeit("function(1)", "from __main__ import function", number=100000)
                                                                          #0.276041984558
                                                                          print timeit.timeit("do([1])", "from __main__ import do", number=100000)
                                                                          #0.033077955246
                                                                          print timeit.timeit("function(xrange(100000))", "from __main__ import function", number=1)
                                                                          #0.00220608711243
                                                                          
                                                                          

                                                                          Rien à dire. Sauf que le premier qui m'appelle 100000 fois function avec un simple objet au lieu de m'appeler une fois function avec une liste de 100000 objets alors que function est prévu pour prendre un itérable, je l'envoie chier en lui conseillant de prendre des cours de dev.

                                                                          L'optimisation ça se fait, quand ça marche, quand c'est nécessaire et là où c'est nécessaire.

                                                                          Matthieu Gautier|irc:starmad

                                                                          • [^] # Re: Le titre est trop long

                                                                            Posté par  . Évalué à 2.

                                                                            Quelle version de python ? Par ce que j'ai pas avancé les chiffres au hasard, j'ai testé sur ma machine avant. Et si je refais exactement ton test j'ai un facteur 6 en 2.6.6 et un facteur 3 en 3.1.3.

                                                                            Sauf que le premier qui m'appelle 100000 fois function avec un simple objet au lieu de m'appeler

                                                                            J'ai pas parlé de faire quelque chose de stupide. Mais au final ta fonction peut très bien se retrouver appeler très souvent avec un int. C'est le risque de se genre de chose; ca s'empile et au fil du temps ca pèse lourd. Tu retrouves énormément cette construction en JS ou tu peux passer soit une liste soit un objet unique.

                                                                            • [^] # Re: Le titre est trop long

                                                                              Posté par  (site web personnel) . Évalué à 2. Dernière modification le 10 juillet 2012 à 19:34.

                                                                              Attention, c'est avec la version de ce commentaire

                                                                              Avec la version d'origine, je suis entièrement d'accord, je me prend un rapport 5. Les commentaires se sont croisés entre les threads.

                                                                              Tu as raison, le générateur coute cher (bien plus que je pensait). Mais la correction est pas compliquée.

                                                                              J'ai pas parlé de faire quelque chose de stupide. Mais au final ta fonction peut très bien se retrouver appeler très souvent avec un int. C'est le risque de se genre de chose; ca s'empile et au fil du temps ca pèse lourd. Tu retrouves énormément cette construction en JS ou tu peux passer soit une liste soit un objet unique.

                                                                              Oui, mais là tu perds un quart de second pour 100000 appels.

                                                                              • Soit tu peux pas faire un appel groupé. Ça sous-entend que c'est du cas par cas (interactif, serveur) et ça reste probablement négligeable.
                                                                              • soit tu peux faire un appel groupé et c'est que c'est mal codé.

                                                                              Dans tous les cas, quand tu vas faire de l'optimisation (et donc du profiling) tu vas vite te rendre compte qu'il faut soit appeler "do" au lieu de "function", soit faire du traitement par lot (utiliser la fonction comme il faut).

                                                                              (Mea culpa pour les commentaires un peu sec, un fois relus chez moi au calme ça passe moins bien qu'entre deux compiles qui passent pas)

                                                                              Matthieu Gautier|irc:starmad

                                                                              • [^] # Re: Le titre est trop long

                                                                                Posté par  . Évalué à 4.

                                                                                J'arrive loiiiin après la bataille mais il y a aussi la solution fonctionnelle pour ce genre de choses, tu écris une fonction ou un bloc de code pour traiter l'un des cas, et tu l'appliques sur ta liste ou ton itérable par la fonction "map"

                                                                                Et là l'appelant sait parfaitement si il doit appeler la fonction individuelle ou appliquer map.

                                                              • [^] # Re: Le titre est trop long

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

                                                                Ça ne change strictement rien.
                                                                Et j'ai pas demander de faire une boucle sur un iterable, juste de tester si ça l'est (principe du duck-typing), en plus de trouver une solution pythonesque à une pythonerie très courante consistant à « caster » en liste un argument simple.

                                                                En gros plus un truc dans le goût:

                                                                def _do_stuff(param):
                                                                  blabla
                                                                  blabla
                                                                
                                                                def do_stuff(param):
                                                                  if not is_iterable(param):
                                                                    param= [ param ]
                                                                        _do_stuff(param)
                                                                
                                                                

                                                                Je l'ai vu très souvent en python ça, y compris dans DJango, Rhodecode et d'autres trucs Python, mais tous sont soit buggés (is_iterable pas vraiment is_iterable, cas des generateurs infinis, cas des basestrings), soit limite le duck-typing (is_iterable = list et tuple, point barre…).

                                                                • [^] # Re: Le titre est trop long

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

                                                                  Je m'y attendais à celle-là =)

                                                                  l = [x for x in foo()]
                                                                  # est equivalent a
                                                                  def bar(iterable):
                                                                     ret = []
                                                                     for i in iterable:
                                                                         ret.append(i)
                                                                     return ret
                                                                  l = bar(foo())
                                                                  type(l) # <type 'list'>
                                                                  
                                                                  
                                                                  l = (x for x in foo())
                                                                  # est equivalent a
                                                                  def bar(iterable):
                                                                     for i in iterable:
                                                                         yield i
                                                                  l = bar(foo())
                                                                  type(l) # <type 'generator'>
                                                                  
                                                                  

                                                                  Same player shoot again ?

                                                                  On revient à ce que je disais, tu codes en python comme tu codes en java: Tu veux savoir si c'est du type iterable avant de travailler dessus.
                                                                  En python on s'en fout : on essaye et si ça passe pas c'est que c'est pas un iterable.

                                                                  Matthieu Gautier|irc:starmad

                                                                  • [^] # Re: Le titre est trop long

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

                                                                    On revient à ce que je disais, tu codes en python comme tu codes en java: Tu veux savoir si c'est du type iterable avant de travailler dessus.
                                                                    En python on s'en fout : on essaye et si ça passe pas c'est que c'est pas un iterable.

                                                                    Raté, c'est pas mon code, mais le code d'exemple que j'ai donné est issu de très grosses librairies python mondialement utilisées. Rhodecode, DJango, Pylon, et même la lib standard Python si mes souvenirs sont exacts !!!…
                                                                    On est donc d'accord, Python code comme en Java, malgré le duck-typing et le typage dynamique…

                                                                    • [^] # Re: Le titre est trop long

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

                                                                      Et j'ai pas demander de faire une boucle sur un iterable, juste de tester si ça l'est (principe du duck-typing)

                                                                      Je te cite, tu veux savoir si c'est iterable avant de le faire.
                                                                      Et je me répète, la syntaxe "(x for x in iterable)" ne parcourt pas iterable. Ça crée un générateur qui parcourra iterable quand on itèrera le générateur.

                                                                      Raté, c'est pas mon code, mais le code d'exemple que j'ai donné est issu de très grosses librairies python mondialement utilisées. Rhodecode, DJango, Pylon, et même la lib standard Python si mes souvenirs sont exacts !!!…

                                                                      Si des softs sont mal codé, c'est la faute au dev, pas du langage et son de typage dynamique.

                                                                      Matthieu Gautier|irc:starmad

                                                                      • [^] # Re: Le titre est trop long

                                                                        Posté par  (site web personnel) . Évalué à 0. Dernière modification le 10 juillet 2012 à 15:44.

                                                                        Si des softs sont mal codé, c'est la faute au dev, pas du langage et son de typage dynamique.

                                                                        Ou que le langage est trop permissif =)
                                                                        Ou alors que le bon développeur Python n'existe tout simplement pas, vu la réputation des gus qui taffent sur les projets sus-nommés.

                                                            • [^] # Re: Le titre est trop long

                                                              Posté par  . Évalué à 4.

                                                              Soit, c'est un bug, mais quel rapport avec le typage, java, python ou je ne sais quoi ?

                                                              Si pour implémenter ton buffer cyclique tu hérites d'un buffer normal tu vas avoir le même problème, d'où l'importance de faire de la doc

                                                • [^] # Re: Le titre est trop long

                                                  Posté par  . Évalué à 2.

                                                  Comment tu faire pour définir tes contrats d'interfaces ? Tu fais ressortir comment dans l'interface de ton code que tes arguments doivent avoir tel ou tel propriétés ? Tu complexifie l'API avec des builders et des factory qui vont vérifier les conditions ou tu met des noms à rallonge ?

                                                  Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                                  • [^] # Re: Le titre est trop long

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

                                                    Je parlais dans le cadre du Java.

                                                    Clairement dans python, je ne suis pas capable de faire tout ça. Du coup je dois documenter, doc qui va devenir obsolète avec le temps, donc conduire à des erreurs, de la perte de temps, etc.
                                                    En plus la doc python n'est généralement pas suffisante pour coder les couches appelantes, et il faudra aller lire le code de toute façon, doc ou pas doc…

                                                    • [^] # Re: Le titre est trop long

                                                      Posté par  . Évalué à 3.

                                                      Avec ton code Java, il faut quand même une doc pour savoir si le nom de fichier est absolu ou non, si tu gère des protocoles réseau (http, smb, ftp…) si le fichier est ouvert ou non à la fin de la fonction

                                                      « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                                                      • [^] # Re: Le titre est trop long

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

                                                        Ben déjà en Java au final, je laisserais le mec me gérer toute la merde d'ouverture et cie, et je prendrais uniquement un InputStream en paramètre.
                                                        Ça permet même d'être encore plus générique, en reportant sur l'utilisateur le choix de m'envoyer ce qu'il veut, que ça soit un FileInputStream, un MemoryStream ou même un SocketStream !

                                                    • [^] # Re: Le titre est trop long

                                                      Posté par  . Évalué à 3.

                                                      Du coup je dois documenter, doc qui va devenir obsolète avec le temps

                                                      La doc, ça ne devient pas magiquement obsolète. C'est un problème de paresse et de manque de rigueur (et de culture de travail, si vous êtes plusieurs : un patch qui oublie de modifier la doc devrait être refusé à la revue de code).

                                                      Enfin, j'aimerais bien voir ta tronche si la bibliothèque standard de Java était livrée sans doc, sous prétexte qu'il suffit de lire le code.

                                                      • [^] # Re: Le titre est trop long

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

                                                        Enfin, j'aimerais bien voir ta tronche si la bibliothèque standard de Java était livrée sans doc, sous prétexte qu'il suffit de lire le code.

                                                        Et bien bizarrement, je consulte bien moins voire quasiment pas les javadoc (sinon à l'apprentissage d'une librairie) que je ne consulte les docstring python !
                                                        Généralement, un ctrl+espace sous Eclipse me met à dispo tout ce que j'ai besoin, sans avoir besoin de la javadoc.

                                                        Au contraire, même après avoir utilisé plusieurs centaines de fois une méthode en python, j'en suis toujours à me poser des questions dessus voire même à trouver quoi appeler et comment le jour où j'en ai besoin…

                                                        • [^] # Re: Le titre est trop long

                                                          Posté par  . Évalué à 3.

                                                          Généralement, un ctrl+espace sous Eclipse me met à dispo tout ce que j'ai besoin, sans avoir besoin de la javadoc.

                                                          Ça tombe bien, ce ctrl+espace affiche aussi la javadoc, le monde est bien fait.

                                                          « Rappelez-vous toujours que si la Gestapo avait les moyens de vous faire parler, les politiciens ont, eux, les moyens de vous faire taire. » Coluche

                                                          • [^] # Re: Le titre est trop long

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

                                                            Ça tombe bien, ce ctrl+espace affiche aussi la javadoc, le monde est bien fait.

                                                            Elle arrive après la bataille, la javadoc…
                                                            Le 1er ctrl+espace, elle t'affiche toutes les méthodes et attributs disponibles d'abord, avec le typage de chaque paramètre et le type de retour. C'est ça qui me file le plus gros coup de pouce.
                                                            La javadoc sur le 2nd ctrl+espace, c'est le cadeau dans le paquet de céréales, elle ne me sert que très très rarement, et ne fait que confirmer que j'ai fait le bon choix =)

                                                • [^] # Re: Le titre est trop long

                                                  Posté par  . Évalué à 3.

                                                  À partir du moment où tu as la nécessité de documenter ton code parce qu'il n'est pas compréhensible, pourquoi ne pas plutôt le refactorer pour le rendre justement compréhensible sans doc ?

                                                  La documentation n'est pas réservée au code « incompréhensible », elle sert à éviter d'avoir à lire le code, que celui-ci soit compréhensible ou non. Évidemment, cela prend tout son intérêt quand tu écris des bibliothèques de plus de vingt lignes, et encore plus si d'autres développeurs utilisent ton code.

                                                  (les déclarations de typage que tu défends sont aussi une forme de documentation, mais cela n'a pas l'air de t'effleurer l'esprit)

                            • [^] # Re: Le titre est trop long

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

                              le système de typage d'Ada te permet de faire des choses statiquement

                              Ada, c'est bien le langage où que tu vas au marché, tu achètes trois poires, deux figues et cinq abricots, et qu'une fois arrivé chez toi, il faut écrire cinquante lignes de code pour savoir combien de fruits tu as ramené ?

                • [^] # Re: Le titre est trop long

                  Posté par  . Évalué à 4.

                  Et pour seconde, tu mets quoi ? 0..59 ou 0..60 ?

                  Tous les nombres premiers sont impairs, sauf un. Tous les nombres premiers sont impairs, sauf deux.

              • [^] # Re: Le titre est trop long

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

                def date_de_naissance(int, int, int)

                Soit tu sais ce que tu fais : new DateTime(2012, 12, 25, 0, 0)
                Soit tu veux vraiment être sûr : new DateTime().withYear(2012).withMonthOfYear(12).withDayOfMonth(25).withTimeAtStartOfDay()
                Mais ça serait vraiment aller chercher des pous…

                Ce code est justement le genre de code à être tester et unit-tester, qui doit péter des exceptions si les valeurs sont incorrectes.
                Et ceci n'a rien à voir avec du code statique ou dynamique.
                Python et Java ont tous deux des manières de faire de rendre ce code robuste, via une factory par exemple. On est plus dans le domaine d'une bonne conception/architecture que dans le choix du langage proprement dit.

              • [^] # Re: Le titre est trop long

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

                def date_de_naissance(int, int, int)

                en C++:
                http://pastebin.com/pWD1hCjL
                (oui, je sais, c'est affreux… mais il faux mettre ce genre de truc dans les bibliothèques)

                • [^] # Re: Le titre est trop long

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

                  C'est plus affreux à ce niveau… C'est carrément du suicide collectif !
                  Et niveau maintenabilité… hum… No comment =)

                  • [^] # Re: Le titre est trop long

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

                    Je ne suis pas d'accord: en quoi est-ce affreux et difficile à maintenir ?

                    void setBirthDay( day_t d, month_t m);
                    
                    void reset() {
                        setBirthDay( 9_day , 7_month  );
                    }
                    
                    

                    les définition des types de day et month sont défini une seule fois dans une bibliothèque.
                    Et ils sont assez facile à définir en utilisant les bibliothèque qui vont bien.

                    (Tu remarqueras que dans mon code je ne fait appel à aucune bibliothèque. Et je ne sais pas s'il en existe qui font ça, mais j'imagine que ça ne va pas tarder car pour le moment c'est encore une nouveauté du langage)

          • [^] # Re: Le titre est trop long

            Posté par  . Évalué à 5.

            D'où l'utilisation de types :
            open(File) <- tadam !

            • [^] # Re: Le titre est trop long

              Posté par  . Évalué à 2.

              Dans l'absolu oui, mais tu crée comment ton File ?

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

              • [^] # Re: Le titre est trop long

                Posté par  . Évalué à 3.

                Et bien, à l'endroit où l'erreur a du sens d'être traitée.

                De toute façon la question n'est pas de supprimer TOUTES les erreurs, c'est impossible, mais de les traiter au bon endroit et ensuite d'être SUR qu'elles ont été traitées.

                Si tu trimbale une valeur de type File, alors tu es sûr d'avoir un truc qui marche (bien que… IO, toussa, ça peut péter, mais bon, c'est encore une autre problématique, qui est traitable avec d'autres choses)

        • [^] # Re: Le titre est trop long

          Posté par  . Évalué à -1.

          Ouais enfin faut se sortir les doigts aussi, ça aide pas mal en développement…

          Si dans ton équipe t'as des mecs qui utilisent n'importe comment les choses, faut se poser des questions sur votre organisation / communication / documentation.

          Si dans tes utilisateurs finaux t'as des mecs qui utilisent ton API/soft n'importe comment, faut se poser des questions sur votre documentation et la sécurisation de vos interfaces (aucune confiance dans le client ça s'applique n'importe où dans une chaine de service).

          Qu'une technologie donnée puissent induire plus facilement que les autres une classe d'erreur, et que les solutions usuelles ne puissent pas y répondre out of the box, on est à deux doigts d'un prix Turing là…

          • [^] # Re: Le titre est trop long

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

            Postulat n°1 : ton utilisateur est une buse…
            Postulat n°2 : demain, t'es plus là…
            Postulat n°3 : la doc n'est jamais à jour, cohérente ni même disponible…

            Étant donné qu'un utilisateur peut être utilisateur final et/ou développeur, plus le compilo te détectera des erreurs a priori, et non pas uniquement a posteriori au runtime, mieux tu te portes.
            Idem, plus il est capable de t'aider (via l'IDE) mieux tu t'en porteras.

            • [^] # Re: Le titre est trop long

              Posté par  . Évalué à 2.

              Postulat n°1 : ton utilisateur est une buse…

              Toujours pris en compte, je pense que c'est une faute grave de ne pas le faire. Si mon utilisateur final est un développeur qui fait du code merdique, ça ne me regarde pas. Que ça plante au runtime ou à la compil, le problème est ailleurs.

              Postulat n°2 : demain, t'es plus là…

              Oui et ? Quelqu'un me remplace, il hérite d'une magnifique doc, de plein de schémas, qui auront pris plein de temps à faire mais assureront la pérennité des projets au delà de ma petite personne. C'est un problème de professionnalisme… mais je te l'accorde, les gens qui verrouille leur environnement de travail pour se rendre indispensable, on en croise un paquet.

              Postulat n°3 : la doc n'est jamais à jour, cohérente ni même disponible…

              J'aimerai vraiment pas bosser dans tes conditions…

              • [^] # Re: Le titre est trop long

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

                Si mon utilisateur final est un développeur qui fait du code merdique, ça ne me regarde pas.

                Si c'est quelqu'un de ton équipe, si.
                Et t'es bien content que l'intégration continue pète gentillement sur chacun de ses commits plutôt que de te rendre compte pendant une recette qui a codé grave de la daube :þ

                Quelqu'un me remplace, il hérite d'une magnifique doc, de plein de schémas, qui auront pris plein de temps à faire mais assureront la pérennité des projets au delà de ma petite personne.

                Des docs de conception ou d'architecture, certes, ça se fait et ça se trouve.
                Mais trouve-moi une seule doc type javadoc ou doxygen où tu peux lui faire aveuglément confiance… C'est généralement blindé d'erreur de copiés/collés, de trucs refactorisés mais sans mise-à-jour de la doc, voire même pas documenté du tout.

                Et en plus, avoir une doc (par exemple en python) capable d'avoir un niveau de détail suffisamment fin pour éviter les erreurs qu'auraient détectées un compilateur, c'est juste inenvisageable.
                Si tu prends le add(duck) précédent, soit tu le documentes avec un simple duck : canard à ajouter, doit être de type Duck ou dérivé et autant avoir un joli compilateur pour faire ce travail de vérif en plus de perdre tout intérêt au duck-typing, soit tu le documentes avec un gros duck : canard à ajouter, doit répondre à la méthode fly, quack, swim et posséder les attributs feathers, qui, en plus de ne sûrement pas être exaustif, sera une simple plaie ambulante à maintenir…

                J'aimerai vraiment pas bosser dans tes conditions…
                Trouve-moi une seule doc qui soit disponible et sans erreur (avec la preuve qui va bien, hein)…
                Même la doc officielle python est truffée d'erreurs en tout genre.

                • [^] # Re: Le titre est trop long

                  Posté par  . Évalué à 1.

                  Si c'est quelqu'un de ton équipe, si.

                  Encore une fois, non et non … ça rejoint ce que je te disais plus haut sur la gestion de ton travail d'équipe.

                  Et t'es bien content que l'intégration continue pète gentillement sur chacun de ses commits plutôt que de te rendre compte pendant une recette qui a codé grave de la daube :þ

                  Peut être parce que les réponses aux problèmes d'intégration ne sont pas les mêmes d'une technologie à une autre et que la chaine doit avoir des étapes différentes …

                  Pour la doc, y'a pas à argumenter plus, c'est une vision différente que l'on a toi et moi. Ton point de confiance est dans le compilateur, moi dans les docs de qualités (et elle n'est pas aveugle ;) )

                  Pour la petite histoire, et aller dans ton sens au sujet des docs, dans le passé j'ai bossé avec une GED espagnole avec une API "webservice" mal documentée (lire ici complètement en freestyle, pas à jour ET EN ESPAGNOL BORDEL !!!) pleine de bugs et cas particuliers non gérés. Le premier boulot, qui a pris du temps pour pouvoir l'utiliser ça a été, après un peu de reverse gentil, de refaire une doc à jour sur les fonctionnalités élémentaires et l'API, documenter son architecture et de faire une couche intermédiaire qui se chargeait de faire les opérations en proposant une interface sécurisée et sa propre doc. Et bien depuis aucun souci sur la partie interface : de la doc de qualité + des entrées sécurisées, ça permet de fonctionner de manière fiable avec une potentielle passoire derrière.

                  • [^] # Re: Le titre est trop long

                    Posté par  . Évalué à 3.

                    Pour la doc, y'a pas à argumenter plus, c'est une vision différente que l'on a toi et moi. Ton point de confiance est dans le compilateur, moi dans les docs de qualités (et elle n'est pas aveugle ;) )

                    Donc tu fais pas de python par ce que simplement la doc de la lib standard à des gros trous que tu combles en faisant des print ou en essayant…

                    D'une manière générale avoir une doc nickel pour l'API publique ca se trouve et ca devrait se faire; bien que ce soit assez rare. Pour le code interne j'ai jamais vu…

                    • [^] # Re: Le titre est trop long

                      Posté par  . Évalué à 2.

                      Non mais tu carricatures pour Python et me fait dire ce que je n'ai pas dit. C'est quand même un langage qui ne manque pas de ressources documentaires …

                      Pour le code interne, encore une fois, ça va au delà d'une simple doc mais elle est nécessaire …

                      • [^] # Re: Le titre est trop long

                        Posté par  . Évalué à 8.

                        Je ne caricature rien du tout. Je n'ai pas dit que la doc était merdique ou inexistante. J'ai dit qu'il existe de nombreux endroits où il est impossible de coder uniquement à partir de la doc. Et les lacunes sont encore plus criant avec un langage dynamique par ce que quand il manque un truc tu peux même pas reposer sur le système de typage. Par exemple en Python il manque très souvent les exceptions, ce qui est pourtant vital. De même certains types de paramètres ou de retour sont flous.

                        Maintenant si tu parles de qualité de la doc, j'ai jamais vu une unchecked exception manquante dans la doc du JDK (pourtant j'en ai écris du code et à chaque fois que j'ai raté un truc c'était documenté). En python il manque même souvent l'équivalent des checked exception…

                        Pour le code interne, tu peux jouer le couplet que c'est nécessaire, je ne vais pas te contredire là dessus. Maintenant en pratique jamais vu sur un vrai projet qui a vécu et dans un domaine non critique. Simplement par ce que c'est tellement refactoré que le coût est simplement exorbitant et qu'on se concentre sur le sous ensemble minimal pour permettre aux gens de bosser. Avec un typage statique souvent ca inclus le design général et l'explication des parties délicates/algos/méthodes quand la lecture du code n'est pas immédiatement suffisante. Avec un typage dynamique, il faut rajouter dans la doc une bonne partie des infos de typage. Le meilleur exemple c'est en javascript où tout le monde refait un système de typage en JS doc. En gros pour survivre il faut écrire les mêmes infos, sauf qu'elles servent à rien hormis générer un fichier texte en qu'elles ne seront pas vérifiées…

                        • [^] # Re: Le titre est trop long

                          Posté par  . Évalué à 5.

                          Je ne peux que pertinenter, sur tous les projets où j'ai bossé (7 ans de bouteille maintenant), les seuls projets avec une doc convenables étaient les petits projets, avec les primo développeur encore dessus.

                          Ensuite venaient les projets où un wiki avait été mis en place, avec une contrainte pour les nouveaux de leur dire que la réponse était dans le wiki (et surtout ne pas le faire à la place du nouveau, ou lui dire comment faire); si la réponse n'était pas dans le wiki, il fallait l'ajouter.

                          Enfin, la grosse majorité des projets, la doc, c'est le code (comprendre par là que la doc écrite par les primodév n'est plus à jour, voire inexistante).

                          Et là j'ai pu voire une grosse différence entre les typages statique façon C++ et python.

                          Python sur les petit projets, pas de soucis, c'est génial, tu fais ton TAF (Try And Fail) itérativement et tu abouti à un truc qui marche; sur les gros projets, la même approche amène irrémédiablement des plantages au moments les plus imprévisible, et pas forcément à coté de la modif; il faut faire une recherche plus approfondie sur le code et prier pour ne pas avoir raté un ou deux cas.

                          En C++, les erreurs sont plus du type fonctionnels, et une très grosse partie des erreurs et repéré à la compil (ne pas oublier que -Wall est généralement une bonne idée. et fort heureusement la lourdeur de la déclaration des itérateurs disparait avec auto ;)

                          Il ne faut pas décorner les boeufs avant d'avoir semé le vent

                      • [^] # Re: Le titre est trop long

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

                        Non mais tu carricatures pour Python et me fait dire ce que je n'ai pas dit. C'est quand même un langage qui ne manque pas de ressources documentaires …

                        J'ai jamais dis le contraire, mais elle n'est pas complète, blindée d'erreurs, ne comporte pas de doc sur les API internes, etc.
                        Elle est donc globalement inutile, étant donné que je devrais quand même faire tout le taff d'aller réellement voir comment c'est fait dedans pour que ça fonctionne.
                        Et que je passe mon temps à lancer mon appli et à la tester à 1000% pour être sûr qu'une runtime exception ne se pointera pas le jour de la recette.

                        Je ne peux avoir confiance en une doc si je n'ai pas la preuve qu'elle est correcte.
                        Comme personne n'est capable de me donner cette preuve pour aucune des docs existantes actuelles, alors toute documentation est inutile (doc type doxygen/javadoc j'entend).

                        • [^] # Commentaire supprimé

                          Posté par  . Évalué à 3.

                          Ce commentaire a été supprimé par l’équipe de modération.

                          • [^] # Re: Le titre est trop long

                            Posté par  . Évalué à 2.

                            De plus, il est à remarquer que le dynamique est un strict sur-ensemble du statique. Il est totalement envisageable dans un langage dynamique de n'utiliser aucunes des fonctionnalités dynamiques et donc, de faire de la vérification automatique de type. Par exemple, common lisp permet de déclarer les types : declare, check-type, proclaim, …

                            Et ces déclarations en lisp sont toutes checkées, avant le lancement du programme, et pour tous les code-paths ? (vraie question, hein)

                            De plus, il est à remarquer que le statique est un strict sur-ensemble du dynamique. Il est totalement envisageable dans un langage statique d'utiliser des fonctionnalités dynamiques et donc, de faire de ne pas faire de la vérification automatique de type. Par exemple :

                            • Haskell permet de mettre n'importe quoi dans une boite noire de type Dynamic et de récupérer la valeur grâce à une fonction de type Dynamic → Maybe t qui renvoie Just a si on avait mis un objet a de type t dans la boite, et Nothing sinon.
                            • C a le bon vieux void*
                            • [^] # Commentaire supprimé

                              Posté par  . Évalué à 2.

                              Ce commentaire a été supprimé par l’équipe de modération.

                        • [^] # Re: Le titre est trop long

                          Posté par  . Évalué à 0.

                          Tu critique et tu répond à la question en même temps.
                          Quand je programmais en Java j'adorais la documentation, toujours le nez dedans et je lisais pleins de livres passionnants. En python je n'ai jamais eu à acheter un seul livre, la documentation je ne la survole que de temps en temps. Dans mon code, pareil, je le documente rarement, non pas par flemme mais parce que c'est souvent inutile tellement le code est explicite et tien sur un écran. Ca évite également d'avoir une documentation qui n'est pas à jour !
                          L'exemple classique c'est pour lire un fichier en Java et en python, dans un cas la doc est indispensable !

                          Ensuite si tu passes ton temps à lancer ton appli et à la tester tu es juste entrain de réinventer les tests unitaires, qui sont nécessaires autant avec un typage statique que dynamique. Par contre, avec un typage statique, même le code des tests unitaires devra être explicitement typé, quel intérêt ?

                          De toutes façon tout ça est subjectif, ça dépend vraiment des cas, peut-être des personnes… On le voit bien dans les expériences décrites dans les commentaires. Pour moi il n'y a pas photo, le gain que ce soit en temps de développement qu'en maintenance est très largement supérieur avec python que java (sachant que je viens du C et ASM).

                          • [^] # Re: Le titre est trop long

                            Posté par  . Évalué à 5.

                            Du coup tu lis le code des bibliothèque que tu utilise pour savoir comment t'en servir ?

                            Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                            • [^] # Re: Le titre est trop long

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

                              Du coup tu lis le code des bibliothèque que tu utilise pour savoir comment t'en servir ?

                              En Python, clairement tu y es justement obligé.
                              Va faire du X509 uniquement avec la doc de la lib du même nom en Python (http://packages.python.org/pyOpenSSL/openssl-x509.html), c'est juste impossible.
                              Tu es obligé d'aller voir ce qu'ils attendent comme type de paramètre.
                              set_subject(subject): Set the subject of the certificate to subject. ne te dit pas que subject doit être de type X509Name si tu ne vas pas voir dans le code…

                              En Java, abstract Principal getSubjectDN(): Gets the subject (subject distinguished name) value from the certificate., plus besoin d'aller voir le code pour savoir ce qu'on manipule. Et même sans la doc, ton IDE te donnera aussi le prototype du bidule (ce qui au final est équivalent, vu la pauvreté de la doc, totalement inutile à ce niveau).

                              • [^] # Re: Le titre est trop long

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

                                c'est juste impossible.

                                Est ce juste ?

                              • [^] # Re: Le titre est trop long

                                Posté par  . Évalué à 2.

                                Je sais pas si c'est avec toi que j'en avais déjà discuté mais on m'a déjà sorti l'exemple du X509. Dernièrement j'ai eu à l'utiliser, je confirme volontiers que la doc est imbitable (on dirait presque que c'est moi qui l'ai faite ;-p) mais c'est une exception, on ne peut pas généraliser avec cet exemple. C'est vraiment rare que je me casse la tête sur une bibliothèque comme ça.

                                Sans doc l'ide va t'aider avec le prototype en java, sans doc je peux assez facilement lire le code en python… C'est au cas par cas après, il faut voir le résultat à la longue (et le contexte bien sûr, dev seul ou en équipe etc.)

                                • [^] # Re: Le titre est trop long

                                  Posté par  . Évalué à -1.

                                  En d'autre termes le meilleur choix est d'avoir les préconditions et posconditions dans la doc?

                                  • [^] # Re: Le titre est trop long

                                    Posté par  . Évalué à 5.

                                    Excellente idée ! Et puis on va utiliser un truc qui vérifie statiquement que les conditions sont toujours remplies (tu peux utiliser un objet dans différentes fonctions qui ajoutent différentes contraintes), et on appellera ça l'inférence de type !

                                    Le principal argument du typage dynamique, c'est que tu ne te fais pas chier avec, tant que tu reste cohérent.
                                    Le principal argument du typage statique, c'est que tu as beaucoup de barrières de sécurité qui s'ajoutent.

                                    Le principal argument de l'inférence de type, c'est que ça combine les deux a la fois, tu ne te fais pas chier avec les types, mais le compilateur vérifie a tout moment que tu reste cohérent.

                                    Trop peu de dev se rendent compte de la puissance de l'inférence et de sa facilité d’accès.

                                    • [^] # Re: Le titre est trop long

                                      Posté par  . Évalué à 4.

                                      Je pense qu'il parlait plus de trucs comme JML qui va bien plus loin que ce que fait l'inférence de type. Par exemple tu peut faire des conditions entre les arguments :

                                      //@ ensure a > b
                                      public void foo(int a, int b) {
                                          // ...
                                      }
                                      
                                      

                                      Mais c'est un cas très simple, tu peut aussi définir des invariants, mettre des conditions sur le résultat indiquer les condition d'une exception, faire des appels de méthode dites « pures »,… Bref de la programmation par contrat.

                                      Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

                                • [^] # Re: Le titre est trop long

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

                                  Je suis un grand fan de Python mais je suis tout à fait d'accord avec le fait que l'absence de typage ne facilite vraiment pas la documentation. Dans le style d'autre package où tu as besoin de lire le source, j'ai mechanize (Ok, c'est pas dans la lib officielle).

                            • [^] # Re: Le titre est trop long

                              Posté par  . Évalué à 1.

                              Ca m'arrive souvent, en particulier dans mes bibliothèque perso car j'essaye de coder de manière à ce que ce soit facile à relire par la suite. Si je documente j'essaye de faire des doctests.
                              Dans tous les cas je ne passe pas beaucoup de temps que ce soit dans la doc ou dans le code des bibliothèques, au bout d'un moment j'utilise généralement toujours les mêmes, elles sont suffisamment intuitives pour que je n'ai pas à revenir dessus.
                              Peut-être que c'est parce que je me fait une règle d'utiliser peu de choses mais que je connais bien ? mais ce qui est sûr c'est qu'en procédant de la même manière en Java, pour exactement les mêmes types d'application j'y passe beaucoup moins de temps. C'est plus une constatation qu'un théorie.

                  • [^] # Re: Le titre est trop long

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

                    Encore une fois, non et non … ça rejoint ce que je te disais plus haut sur la gestion de ton travail d'équipe.

                    On peut continuer dans les postulats si tu veux :
                    Postulat n°4 : on a toujours une brebis galeuse dans l'équipe
                    Le but du jeu est de la détecter immédiatement, pas le jour de la recette.
                    Et le typage statique est assez efficace pour ça, ça l'obligera même à venir te poser des questions parce que le compilo gueule plutôt que de faire un truc à l'arrache qui semble plus ou moins tomber en marche subitement par moment.

                    Pour la doc, y'a pas à argumenter plus, c'est une vision différente que l'on a toi et moi. Ton point de confiance est dans le compilateur, moi dans les docs de qualités (et elle n'est pas aveugle ;) )

                    Même la doc python ou java est foireuse à souhaits, ou en tout cas ne peut pas être considérée comme fiable. Alors celles de nos projets… Je t'ai dis, j'attend toujours une doc en qui je puisse avoir confiance…

                    documenter son architecture et de faire une couche intermédiaire qui se chargeait de faire les opérations en proposant une interface sécurisée et sa propre doc. Et bien depuis aucun souci sur la partie interface : de la doc de qualité + des entrées sécurisées, ça permet de fonctionner de manière fiable avec une potentielle passoire derrière.

                    Pour les docs d'archi et de conception, je suis d'accord avec toi que c'est possible et même obligatoire. Mais pour le détail nécessaire au développeur lambda, les docs ne sont généralement pas suffisantes…
                    Prend l'exemple de ton API espagnole. OK, aujourd'hui ça fonctionne. Mais demain ? Si tu dois faire évoluer la partie moisie, c'est juste mort, avec ou sans doc.

                  • [^] # Re: Le titre est trop long

                    Posté par  . Évalué à 2.

                    Pour ce qui est de remettre la doc au carré c'est vrai dans un monde idéal, mais dans mon monde (celui des SSII), c'est payant et depuis que j'ai commencé à bosser, il y a 20 ans, je n'ai jamais un client pret à payer pour ça. Donc soit ton projet fait des marges suffisante pour le permettre (et même dans ce cas on va te dire : le client ne paie pas, on fait pas) soit tu n'a pas une documentation qui va bien et tu fais avec. Je dirais même que je n'ai jamais vu un projet avec une doc nickel, à part peut être à la fac

                • [^] # Re: Le titre est trop long

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

                  Si tu prends le add(duck) précédent, soit tu le documentes avec un simple duck : canard à ajouter, doit être de type Duck ou dérivé et autant avoir un joli compilateur pour faire ce travail de vérif en plus de perdre tout intérêt au duck-typing, soit tu le documentes avec un gros duck : canard à ajouter, doit répondre à la méthode fly, quack, swim et posséder les attributs feathers, qui, en plus de ne sûrement pas être exaustif, sera une simple plaie ambulante à maintenir…

                  Oui, mais pour moi le principal problème vient du fait que tu veux les avantages du typage statique avec un langage à typage dynamique, ça peut tous simplement pas marcher (tout seul).

                  Ta fonction addDuck, elle ne prend pas un duck comme argument mais un truc qui à les méthode fly, quack et swim (point). Elle devrait d’ailleurs s’appeler add (pas de raison qu'une ferme accepte que des canards)

                  Si tu veux un duck faut faire du isinstance. (Et la tu perds l'avantage du python)

                  De la même façon, removeFeathers prend un truc à plume, pas un canard.
                  Un canard sans plume c'est peu être un canard mais c'est pas un truc à plume. Faut pas chercher plus loin.

                  Si tu veux une fonction qui prend un truc qui peut avoir des plumes, c'est ça:

                  def removeFeathers(self, duck):
                      try:
                          self.feathers += duck.feathers
                          duck.feathers = 0
                          print "Feathers removed"
                      except AttributeError:
                          print "no feather"
                  
                  

                  Dans tous les cas, tu ne peux pas faire du python comme tu ferais du c++. C'est pas la faute du python ou du typage dynamique, c'est la faute au dev qui veut du typage statique dans python. Les paradigmes sont différents, faut coder différemment.

                  Matthieu Gautier|irc:starmad

                  • [^] # Re: Le titre est trop long

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

                    Dans tous les cas, tu ne peux pas faire du python comme tu ferais du c++. C'est pas la faute du python ou du typage dynamique, c'est la faute au dev qui veut du typage statique dans python. Les paradigmes sont différents, faut coder différemment.

                    J'ai jamais dis le contraire =)
                    C'est même une de mes principales conclusions : le code tient en plusieurs fichiers et/ou dépasser les 200 lignes ⇒ adios le dynamique, vive le statique ! En tout cas d'un point de vue stabilité / maintenance / évolutivité.

                    • [^] # Re: Le titre est trop long

                      Posté par  . Évalué à 3.

                      dépasser les 200 lignes ⇒ adios le dynamique

                      C'est marrant, je fait l'inverse, langage dynamique pour la plus grosse partie du code et du statique pour les petites parties où la perf est primordiale par ex.

                    • [^] # Re: Le titre est trop long

                      Posté par  . Évalué à 2.

                      En tout cas d'un point de vue stabilité / maintenance / évolutivité.

                      Je pense que ces objectifs n'ont rien à voir avec le fait d'utiliser un langage statique ou dynamique. Je pense même que que l'on produit assez souvent des programmes en c++ peu stables malgré son typage statique.

                      J'ai vu suffisamment de projets pour trouver des bons et de mauvais exemples dans tout les cas, par contre j'ai un plus gros désaccord pour le refactoring: en effet le dynamique peut poser problème lorsque l'on renomme des méthodes ou ptit trucs du genre, par contre en cas de gros refactoring (modif d'archi), il me semble que le dynamique est là bien supérieur.

                      • [^] # Re: Le titre est trop long

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

                        Je pense que ces objectifs n'ont rien à voir avec le fait d'utiliser un langage statique ou dynamique. Je pense même que que l'on produit assez souvent des programmes en c++ peu stables malgré son typage statique.

                        Oui, on peut faire du crade avec tout, certains langages étant juste plus enclins que d'autres à faire du code dégueu.

                        J'ai un plus gros désaccord pour le refactoring: en effet le dynamique peut poser problème lorsque l'on renomme des méthodes ou ptit trucs du genre, par contre en cas de gros refactoring (modif d'archi), il me semble que le dynamique est là bien supérieur.

                        Pas convaincu.
                        Un refacto d'archi risque typiquement de casser l'intégralité de ton code Python, cause qu'elle laisse une chiée de truc pas refactorisé car pas détecté par l'IDE car pas de typage statique donc incapable de détecter qui est impacté.
                        Pour l'avoir vécu sur pas mal de projets assez conséquent en python, ça se finit généralement en séance de

                        while not working:
                            run
                            debug
                            correct
                        
                        

                        Au moins en Java, la refacto corrigera déjà énormément plus de choses via la puissance du refactoring des IDE cause aide du compilo et analyse statique du code, et le restant pétera directement en rouge cramoisi tant que ça sera faux.

                        • [^] # Re: Le titre est trop long

                          Posté par  . Évalué à 2.

                          Oui, on peut faire du crade avec tout, certains langages étant juste plus enclins que d'autres à faire du code dégueu.

                          Pas une question de coder crade, juste une erreur humaine
                          Dailleurs je dirai que le dynamique oblige à coder propre, faire tes testsU et faire la doc… des fois ce n'est pas fait et là évidemment c'est une catastrophe.

                          Un refacto d'archi risque typiquement de casser l'intégralité de ton code Python

                          Je connais pas particulièrement python (en fait je commence mon premier proj python actuellement, mais pour avoir vécu ce genre de situation en smalltalk (1 fois), ruby, java et c++, moi je suis convaincu. En java et c++ (et je pense en typage statique en général) ça revient souvent à réecrire beaucoup de choses (voir pire, jai déjà vu un rattrapage d'archi en AOP).
                          Bien sur je troll, ce sont des cas particuliers, et pour le projet st que je prend en exemple, je suis persuadé que tout aurait foiré si les devs avaient manqué de rigueur et n'avaient pas codé les tests.

                          • [^] # Re: Le titre est trop long

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

                            En java et c++ (et je pense en typage statique en général) ça revient souvent à réecrire beaucoup de choses (voir pire, jai déjà vu un rattrapage d'archi en AOP).

                            Et ? Où est le problème ?
                            Si on refactorise l'architecture, il est normal d'avoir à rattraper pas mal d'endroits dans le code.

                            Un code python qui va continuer à fonctionner après avoir refondu une architecture sans toucher du code à droite et à gauche, c'est plus un truc qui est tombé tout seul en marche qu'autre chose…

                            C'est pas parce que tu fais moins de travail que ton travail est meilleur et/ou plus robuste.
                            Les trucs du style « wé mais non regarde, pas besoin de toucher à ça, la magie python va faire que ça va passer quand même », c'est cool tant que la magie dure justement. Ça reste du passage aux forceps d'un truc prévu initialement pour un trou carré… qui est aujourd'hui rond, et demain triangulaire. Le jour où ça frotte juste un peu… ça se coince et généralement ça veut plus faire marche-arrière !

                            • [^] # Re: Le titre est trop long

                              Posté par  . Évalué à 2.

                              Et ? Où est le problème ?

                              Bien sur qu'il faut retaper, je prétends juste que la quantité de travail est beaucoup plus importante dans un cas
                              Le temps, le plaisir du dev, la complexité et surtout la méthode
                              comme j'indiquai dans le pire cas que j'ai vu, ça a finit en AOP dégueu plutôt qu'une belle réécriture. Bien sur ça peut arriver en dynamique, je prétends juste que c'est moins probable car beaucoup plus souple et facile.

                              Ceci dit ne croyez pas que je suis un défenseur pur et dur du dynamique, pour moi le dynamique à un énorme défaut: il faut être rigoureux, notamment sur la doc et les tests. Sur un gros projet, si ce n'est pas le cas, ça casse beaucoup plus vite que sur du statique.

                              • [^] # Re: Le titre est trop long

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

                                J'ai du mal à voir un cas où de la refacto sera plus facile à réaliser sur du dynamique que sur du statique.
                                Un exemple m'éclairera sûrement =)

                                En dynamique, on est de base pas aidé par l'IDE, même la refacto la plus simple (renommage attribut ou méthode) est un jeu de pifométrie aléatoire avec 0 certitude que le système fonctionne correctement après la refacto.
                                Aller, à la limite, l'introduction d'une super/sous-classe est effectivement plus simple en dynamique (rien à faire) qu'en statique (tout à faire).

                                Dès que tu ajoutes un attribut, une classe, que tu ajoutes un paramètre ou un polymorphisme, TOUS les endroits où était utilisé l'ancien code est à revoir.
                                Sauf qu'en dynamique, personne ne peut justement savoir où se trouve cette ancienne utilisation du code, vu que tout est dynamique justement.
                                À l'inverse, une analyse du code statique trouvera déjà la plupart de ces utilisations et les refactorera (c'est ce que fait la refacto Eclipse), et les non-vues déclencheront des erreurs à la compilation.

                                • [^] # Re: Le titre est trop long

                                  Posté par  . Évalué à 3.

                                  Un exemple m'éclairera sûrement =)

                                  La comme ça je n'ai pas tant d'exemple pratique, mais je pensai notamment à la déduplication (création d'héritage, de délegation, fusion de 2 chaines d'héritages), la possibilité d'utiliser des traits facilement et rapidement, etc…

                                  En dynamique, on est de base pas aidé par l'IDE, même la refacto la plus simple (renommage attribut ou méthode) est un jeu de pifométrie aléatoire avec 0 certitude que le système fonctionne correctement après la refacto.

                                  Oui ça peut être bordel et pas complètement automatisable, mais ça se fait bien si justement tu as un bon jeu de test, tu suis le flux de donnée, tu renommes automatiquement ta méthode, ainsi que d'éventuelles erreurs de ducktyping.
                                  Ce n'est pas aussi efficace qu'une analyse statique en effet, mais c'est compensé par les facilités que t'offre le duck typing.

    • [^] # Re: (le titre est trop long)

      Posté par  . Évalué à 10.

      De par sa nature même, un langage à typage dynamique interdit toute complétion automatique ou assistance à la refactorisation digne de ce nom. Cela ralenti énormément le développement.

      C'est clair, énormément. C'est dingue comme je code des fonctionnalités plus vite en C qu'en Python !

      • [^] # Re: (le titre est trop long)

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

        C'est sûr qu'il faut un bon IDE aussi :þ

      • [^] # Re: (le titre est trop long)

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

        Cela n'a pas grand chose à voir. C'est le langage le problème ici, pas seulement le typage. La vraie question est « développerais-tu plus vite si Python avait un typage statique » ?

        D'ailleurs, le typage de C, bien que statique n'est quand même pas le moins permissif qui soit… Rien à voir avec celui d'Haskell (qui est discuté dans le journal) ou d'Ocaml.

        • [^] # Re: (le titre est trop long)

          Posté par  . Évalué à 2.

          La vraie question est « développerais-tu plus vite si Python avait un typage statique » ?

          La question ne veut pas dire grand'chose. Si Python avait un typage statique obligatoire, ce ne serait plus Python. Par ailleurs, il est difficile de répondre sans faire l'expérience concrètement.

          • [^] # Re: (le titre est trop long)

            Posté par  (site web personnel) . Évalué à 0. Dernière modification le 08 juillet 2012 à 21:18.

            J'ai aussi du mal à me projeter dans un Python statique.
            Mais quand je vois le temps que peut me faire gagner un langage statique et un IDE bien configurer via sa complétion automatique ou ses outils de refactorisation, c'est juste monstrueux.
            Et après, le temps de chasse aux bugs, aux diverses erreurs de typo à la con, etc… Le rapport de Evan Farrer est assez éloquant là-dessus aussi.

            Sur un code « v1.0 », je pense que le seul gain sera celui nécessaire à la recherche des infos pour savoir quoi appeler, avec quoi en paramètre et pour quel retour.
            Pas folichon comme gain je pense, mais quand même (à vue de pif ~10% du temps).
            Dès une « v2.0 » ou du dev à plusieurs, au revoir Python !!!

    • [^] # Troll detected.

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

      De par sa nature même, un langage à typage dynamique interdit toute complétion automatique ou assistance à la refactorisation digne de ce nom. Cela ralenti énormément le développement.

      ROFLCOPTER ! T'as jamais utilisé slime pour faire du Common Lisp toi.

      Tiens, et aussi, de par sa nature même, un langage à typage statique interdit tout débuggage dynamique digne de ce nom. Cela ralenti énormément le développement.

      Ne te méprend pas sur mon opinion, ma précédente job, c'était du Common Lisp, et ma job actuelle, c'est du Haskell. J'aime les deux approches, je connais leurs points forts et faibles, et je ne verse pas dans le trolls statique/dynamique. Mais là, tes premières phrases, c'est des FOUTAISES !

      • [^] # Commentaire supprimé

        Posté par  . Évalué à 3.

        Ce commentaire a été supprimé par l’équipe de modération.

    • [^] # Re: Je soutiens

      Posté par  . Évalué à 1.

      Je soutiens vos propos.

      Un typage statique offre davantage de possibilité et permet une auto-documentation.
      Il permet notamment des optimisations statiques par le compilateur qui ne sont pas négligeables.

      Et si le système de type est bien conçue il prend en compte la notion de non nullité d'objets.

      Si le langage est bien conçue il offre un mécanisme d'assrtions.

      Les types, la non nullité et les assertions permettent une documentation complète, ou presque, d'une méthode, permettent une série de vérification renforçant grandement la fiabilité, la robustesse, la correction de l'application et son optimisation.

  • # Mettre la complexité dans le typage

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

    Je plussoie la plupart des affirmations du journal et des blogs cités.

    Pour faire du fonctionnel au quotidien, j'ai fini par comprendre qu'outre quelques bugs qui disparaissent du fait de l'interdiction des valeurs nulles, et autres erreurs de type, on peut très vite se retrouver avec beaucoup d'erreurs si on utilise assez mal( ou trop peu) le système de type des langages fonctionnels.

    Autrement dit, il faut toujours chercher à coder la difficulté dans le typage et non dans l'algorithme.
    Un exemple classique est la sur utilisation des chaines de caractères, qu'on va utiliser abusivement lorsqu'on échange avec la base de donnée. L'idéal est de typer au maximum pour profiter des capacité du compilateur de débusquer les erreurs qui se planquent dans le traitement.

    Les langages fonctionnels apportent en plus le typage somme, qui est un espèce d'Enum de java/C/… boosté aux stéroids, avec la capacité de pattern matcher dessus, tout en profitant de la capacité du compilateur de vérifier l'exhaustivité du switch case.

    Un exemple, en java

    public enum  connection_state {
     Connecting , Connected , Disconnected 
    }
    
    public class connection_info  { 
      connection_state state ; 
      inet_addr server; 
      time last_ping_time; 
      int last_ping_id; 
      string session_id; 
      time when_initiated; 
      time when_disconnected; 
    }
    
    

    Pour les camelistes

    type connection_state = 
    | Connecting 
    | Connected 
    | Disconnected 
    
    type connection_info = { 
      state:                   connection_state; 
      server:                  inet_addr; 
      last_ping_time:          time option; 
      last_ping_id:            int    option; 
      session_id:              string option; 
      when_initiated:          time option; 
      when_disconnected: time  option; 
    }
    
    

    Premier problème, en java, un certain nombre de champ peuvent être nulles. En Ocaml, avec le option, on a la garantie de relever les cas nuls à la compilation.

    La structure en Java est merdique car on doit maintenir des champs à Null ou à une valeur stupide car tous les champs ne servent pas : on se fiche du session_id lors qu'on se connecte ou qu'on est déconnecté.
    On a ainsi une structure à "champ libre", c'est à dire que c'est à l'algo de vérifier la cohérence des données .Le compilateur ne peut rien faire là dessus.

    Grâce au type somme disponibles dans les principaux langages fonctionnels (OCaml, Haskell, Scala), on va pouvoir disposer d'une structure de donnée logique, et plus facilement vérifiable :

    type connecting   = { when_initiated:  time; } 
    type connected    = { last_ping  : (time * int) option; 
                                     session_id: string; } 
    type disconnected = { when_disconnected: time;  } 
    
    type connection_state = 
    | Connecting   of connecting 
    | Connected    of connected 
    | Disconnected of disconnected 
    
    type connection_info = { 
       state:  connection_state; 
       server: inet_addr; 
    }
    
    
    1. L'algorithme travaille sur des données représentant réellement l'information telle qu'on la conçoit dans notre cerveau.
    2. La vérification de l'exhaustivité du pattern matching nous garantit qu'on traite tous les cas
    3. Les types ajoutés d'option nous garantissent le traitement des valeurs nulles.*

    Bref, certes oui, le statiquement typé permet de trouver quelques erreurs, mais ne remplace pas les tests unitaires, mais ce serait intéressant de refaire l'expérience, en restructurant les codes qu'il a étudié en véritable typage fonctionnel pour voir si le compilateur ne détecte pas de bugs intéressants…

    *
    Comment ça marche ?
    On définit une valeur d'une structure comme étant string option :
    type mastructure = { champ : string option }
    À partir de là mastructure.champ doit valoir, soit Some "Contenu de la chaine", soit None
    Si vous traitez qq part mastructure.champ, vous devez la pattern matcher :

    match mastructure.champ with
    | Some s -> code à exécuter avec s == "Contenu de la chaine"... 
    | None   -> On doit traiter l'erreur sinon le compilateur gueule
    
    

    « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

    • [^] # Re: Mettre la complexité dans le typage

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

      Je ne vois pas la différence avec un simple héritage :-/
      Classe mère connection_state (abstract)
      Classes filles: connecting, connected, disconnected…

      • [^] # Re: Mettre la complexité dans le typage

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

        Le problème est que tu vas devoir définir une variable dans laquelle on va mettre les 3 objets différends, à différends moments.
        Ça dépend de ton compilateur, mais il vont pas tous être capable de détecter que la méthode que t'appels après avoir affecté ta variable avec une certaine instance de classe est effectivement disponible dans ta classe… Alors même que ce n'est pas une bonne idée d'avoir un getSessionID dans la classe connecting ou disconnecting..

        Ça pose des problèmes de sous-typages : certaines méthodes abstraites auront lieu d'être dans certaines classes, pas dans d'autres.

        Bref, oui ça peut marcher, mais c'est pas génial.

        « Il n’y a pas de choix démocratiques contre les Traités européens » - Jean-Claude Junker

        • [^] # Re: Mettre la complexité dans le typage

          Posté par  . Évalué à 3. Dernière modification le 09 juillet 2012 à 14:26.

          Quand tu utilise ta variable en Haskel tu va faire du type checking (je crois que c'est comme ça que ça s'appelle) et pour chaque type de connection_state (je sais pas si j'utilise les bons termes), car ton compilateur va t'obliger à gérer tout les cas.

          En objet tu met tout ce qui n'est pas en option dans la classe mère et le reste dans une classe fille. Si tu as de la réflexion tu vérifie le type avant de transtyper puis d'utiliser les méthodes.

          Du coup tu t'appuie sur ton compilateur et je ne sais pas si le compilateur java le fait mais les outils d'analyse statique des IDE t'insultent si tu fait un cast sans vérifier le type avant.

          Bref, oui ça peut marcher, mais c'est pas génial.

          Si tu as de la réflexion, je ne vois pas de problème (après peut être que le C++ et sa méta-programmation peuvent avoir des solutions sur du point de vu du type et agréable une fois qu'on a caché la méta prog). Note que je suis d'accord que c'est moins beau qu'en fonctionnel.

          Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

          • [^] # Re: Mettre la complexité dans le typage

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

            C'est plus du pattern matching que du type checking.
            En typant, il va voir que t'as un objet de type A. Il a accès statiquement à la structure des objets de type A, et sait donc toutes les formes qu'ils peuvent avoir. Il vérifie ensuite que ton code couvre bien tous les cas possibles pour ton type.

            • [^] # Re: Mettre la complexité dans le typage

              Posté par  . Évalué à 3.

              C'est plus du pattern matching que du type checking.

              C'est de ça que je voulais parler :)

              Tous les contenus que j'écris ici sont sous licence CC0 (j'abandonne autant que possible mes droits d'auteur sur mes écrits)

  • # Trop facile

    Posté par  . Évalué à 7. Dernière modification le 09 juillet 2012 à 03:46.

    C'est sur que le système de type de Haskell est surpuissant et qu'il permet d'attraper pleins d'erreurs.

    Il aurait porté le code Python vers du C il n'aurait surement pas tiré les mêmes conclusions. (d'ailleurs, il le dit dans un de ces commentaires)

    Il y a en fait 3 systèmes de types : statique puissant (Haskell), statique pas puissant (C, Java) et dynamique (Python).

    A mon avis, Haskell et Python on essayé de résoudre le problème des systèmes de types pas puissant en ayant 2 approches différentes, Python en le rendant le plus invisible possible et Haskell en le rendant le plus puissant possible.

    Je n'ai pas trop d'avis sur Haskell vs Python mais je pense que Haskell et Python sont tout les 2 meilleurs que C et Java niveau système de types

    • [^] # Re: Trop facile

      Posté par  . Évalué à 4.

      Python sont tout les 2 meilleurs que C et Java niveau système de types

      Il est peut-être meilleur par certain coté, mais trouver des bugs à l'exécution plutôt qu'à la compilation c'est quand même un énorme inconvénient!

      • [^] # Re: Trop facile

        Posté par  . Évalué à 3.

        L'avantage est que le système de type ne te ralenti pas, il ne te ralentit peut-etre pas en Haskell mais en C et Java oui (surtout si tu écris des tests unitaires et que tu dois faire des interfaces et des factory).

        • [^] # Re: Trop facile

          Posté par  . Évalué à 3.

          L'avantage est que le système de type ne te ralenti pas, il ne te ralentit peut-etre pas en Haskell mais en C et Java oui (surtout si tu écris des tests unitaires et que tu dois faire des interfaces et des factory).

          De mon expérience (vécue et observée), le typage statique ne te ralenti pas dès lors que tu ne cherches pas à te "battre" avec le système de typage.

          Un des gains de temps est justement que tu as tout une classe de tests unitaires (tout ceux qui étaient là uniquement pour tester les erreurs de type) qui ne sont pas nécessaires (ce qui n'exclut bien évidement pas d'écrire les autres).

          Après, on peut effectivement regretter l'absence d'inférence de type en C ou en Java.

        • [^] # Re: Trop facile

          Posté par  . Évalué à 3.

          L'avantage est que le système de type ne te ralenti pas

          Bof, ce qui ralenti en C c'est surtout le coté bas niveau, en Java je dirais le manque d'inférence de type, les types nullable par défaut, les APIs compliquées (quand je l'ai utilisé c'est les librairies étaient buggées jusqu'à la moelle mais c'était il y a longtemps).

        • [^] # Re: Trop facile

          Posté par  . Évalué à 2.

          Sans compter l'absence de phase de compilation, justement.

      • [^] # Commentaire supprimé

        Posté par  . Évalué à 4.

        Ce commentaire a été supprimé par l’équipe de modération.

        • [^] # Re: Trop facile

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

          Si je peux me permettre (et faire de la pub, désolé). Mais voila une petite vidéo qui montre un gestionnaire de fenêtres en fonctionnement auquel on rajoute des fonctionnalités au vol. La recompilation est transparente. Le debugage peut se faire alors que le programme fonctionne.

          http://common-lisp.net/projects/clfswm/quick-hack.ogv

        • [^] # Re: Trop facile

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

          Il y a donc du pour et du contre des 2 cotés.

          Du côté statique, on peut faire du dynamique (par exemple en C++, on a QVariant ou boost::any). L'inverse n'est pas vrai.

          Le post ci-dessus est une grosse connerie, ne le lisez pas sérieusement.

    • [^] # Re: Trop facile

      Posté par  . Évalué à 5.

      Il y a en fait 3 systèmes de types : statique puissant (Haskell), statique pas puissant (C, Java) et dynamique (Python).

      Il y a surtout deux axes distincts : typage statique/dynamique et typage faible/fort. Sachant que tout n'est pas tout blanc ni tout noir (il n'y a deux catégories : fortement typé et faiblement typé mais tout un ensemble de situation).
      Et encore je ne parle pas des langages conservant des mécanismes introduisant des faiblesses de typage pour telle ou telle raison (généralement la rétrocompatibilité) mais que l'on cherche à éviter ou les langages à typage statique introduisant des traits de langages à typage dynamique (les variants ou autre)

      A mon avis, Haskell et Python on essayé de résoudre le problème des systèmes de types pas puissant en ayant 2 approches différentes, Python en le rendant le plus invisible possible et Haskell en le rendant le plus puissant possible.

      Ce sont réellement deux axes distincts et le typage dynamique est une autre vision du typage, pas une réponse aux typages statiques faibles (il existe des langages à typage dynamique faible)

      • [^] # Re: Trop facile

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

        Je pense surtout que le présupposé est faux : python n'a rien essayé de résoudre du point de vue typage. Ils ont pris ce qu'ils pouvaient, et basta. Les communautés Haskell, OCaml ou Scheme sont des communautés où il y a de la recherche en typage, depuis longtemps, et encore activement. En python, j'en doute.

        • [^] # Re: Trop facile

          Posté par  . Évalué à 5.

          python n'a rien essayé de résoudre du point de vue typage. Ils ont pris ce qu'ils pouvaient, et basta.

          Heu… Ils ont pris ce qu'ils pouvaient  ? Le typage de Python ne ressemble ni à Perl, ni aux langages fonctionnels classiques, ni au C, ni à C++, ni à Java…

          Haskell, OCaml ou Scheme sont des communautés où il y a de la recherche en typage, depuis longtemps, et encore activement. En python, j'en doute.

          Ce n'est pas parce qu'il n'y a pas de modèle mathématique formalisé derrière qu'il n'y a eu aucun effort pour définir le système de types.

          Le duck-typing associé à la notion de protocoles (le fait que len(x) appelle la méthode __len__ de façon sous-jacente, par exemple), ça ne se retrouve pas dans beaucoup de langages. Je crois que ça rejoint un peu les typeclasses de Haskell, ceci dit ?

Suivre le flux des commentaires

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