• [^] # Re: Pitoyable

    Posté par . En réponse au message de la puissance de (beep) pour trouver un truc simple en 2 minutes. Évalué à 3.

    Dans le même temps, je suis horrifié par le code des outils de la Mandrake, *objectivement* très peu documenté et lisible. Ça me fait sincèrement chier de voir l'effort nécessaire pour les maintenir, à côté des outils de la Fedora, certes pas aussi avancés mais limpides à parcourir, et en plein boom.

    Pour Fedora, on verra ce que ça donnera, mais jusqu'à présent les outils d'aide à la configuration de Mandrake sont plus nombreux et plus puissants alors que les développeurs sont moins nombreux (ils sont un peu plus buggés je le concède, mais globalement ils marchent très bien).

    Maintenant, la question de la documentation du code ne se résume pas à un principe qui tient en deux lignes. En particulier, il faut tenir compte du niveau du/des programmeurs, du taux de "turnover" dans l'équipe de développement (Mandrake c'est pas une SSII), du style qu'adopte une équipe de développement (en connaissant le style on comprendra mieux le code), du besoin de maintenance et d'ajout de fonctionnalité du code (il n'est pas le même dans chaque code/projet : par exemple ce que tu documenteras le mieux sera l'API, les exemples de plugin). Bref, mon point de vue sur la question s'étale en anglais ici :

    http://zarb.org/~gc/html/documenting-code.html(...)

    Et sur ce je vois ton journal, dont le ton est, sinon agressif, très provocateur : une merveille d'un côté, quelque chose de forcément bien plus long et plus chiant en Python de l'autre... avoue que tu y es pas allé de main morte !!

    Euh ce n'est pas parce que mon journal est provocateur (mais pas insultant à part peut-être "chiant" mais bon faut pas pousser) que j'ai le droit de me prendre : "t'as gagné t'es le meilleur" "un super pro comme toi" (plusieurs fois) "trucs plus importants à faire" "un demi-dieu comme toi" "bravo champion" bon j'arrête mais bon tu situes : au premier ça va je rigole, au deuxième je me dis que t'as l'air chaud, au cinquième j'en ai franchement marre.

    je suis absolument persuadé que ce que tu prônes, c'est pour moi un exemple à ne pas suivre.

    Je ne prône que l'utilisation d'un langage de script élégant et puissant pour les "petites tâches vite fait", rien de plus, dans cet article tout du moins. Je sais que le code ci-dessus est illisible, mais son propos n'est pas d'être relu et encore moins d'être conservé ; c'est juste d'avoir un outil permettant de faire rapidement une tâche unique.

    dis-moi ce que tu penses de l'équivalent en python... tu n'es pas tenté ?

    Non. Python pour moi a des avantages indéniables, mais ils sont massacrés par trop d'erreurs. Je te liste les plus importantes que j'ai découvertes lors de mes essais (parfois forcés) avec Python :

    fonctions anonymes castrées

    On se trouve relativement souvent en face d'une situation dans laquelle on veut appliquer une transformation assez simple à un ensemble de données, et les fonctions anonymes sont indispensables pour pouvoir le faire élégamment (elles le sont aussi entres autres pour brancher un callback dans un système de programmation évenementielle).

    Par exemple, j'ai une liste d'entiers, je veux obtenir à la fois la somme de ceux-ci, et la liste avec les entiers doublés. En Perl on le fait comme cela :

    @nouvelle_liste = map { $somme += $_; 2*$_ } @liste

    Ca pourra te paraître imbitable si tu ne connais pas le Perl et sa variable implicite $_, mais une fois que l'on connaît Perl ça devient très lisible. C'est comme si on disait que l'indentation horizontale de Python rend le code imbitable parce qu'on est habitués aux accolades - c'est juste une particularité du langage, qui une fois connue n'est pas un obstacle à la lisibilité.

    En Ruby on le fait comme cela :

    somme = 0
    nouvelle_liste = list.map{ |e| somme += e; 2*e }

    C'est très élégant aussi, on peut discuter entre $_ et |e| qui oblige à nommer la variable locale mais ça n'alourdit quasimment pas.

    En Python on doit définir une fonction, ou bien utiliser un for... in..., mais on ne pourra plus utiliser d'autre appel fonctionnel derrière, ce qui est génant ; si on veut vraiment le faire fonctionnellement on devra écrire :

    somme = 0
    nouvelle_liste = map(lambda e:globals().update({'somme':globals().get('somme') + e}) or 2 * e, liste

    Pour moi c'est un énorme problème de Python, qui m'empêche d'écrire du code fonctionnel. Et au passage, en terme de qualité, réutilisabilité et maintenabilité, le code fonctionnel est d'une utilité fantastique car il force à écrire des fonctions sans effets de bords.

    Sur ce point-là, je suis d'accord que ce n'est pas ce qu'un programmeur débutant fera, mais par contre au bout d'une certaine expérience de programmation le fonctionnel s'impose ; ce qui alimentera pour partie ma future conclusion sur Python.

    message d'erreur totalement cryptique

    Si tu écris cela :

    class Foo:
    def __init__(self):
    print "Foo"

    class Bar(Foo):
    def __init__(self):
    super(Bar, self).__init__()
    print "Bar"

    b = Bar()

    Tu te prends comme message d'erreur :

    File "foo.py", line 7, in __init__
    super(Bar, self).__init__()
    TypeError: super() argument 1 must be type, not classobj

    Si ça t'intéresse, je te laisse tenter de comprendre le sens du message et de trouver d'où vient ce problème, je donne la solution plus bas au [1].

    Bien sûr, ce n'est qu'un exemple et ça ne veut pas forcément parler d'un langage en général. Mais franchement, j'ai burlingué auprès de quelques langages maintenant, et je n'ai pas souvenir d'avoir eu avec d'autres langages que Python un message aussi débile (à part peut-être les messages de g++ quand il y a un problème emmêlant les template, les namespace... et heureusement qu'il n'y a pas de multiple dispatch en plus).

    interpolations

    Il n'y a pas d'interpolation dans les chaînes de caractères. Quelque chose de si pratique disponible dans tellement de langages de script (même Tcl !) et qui n'existe pas en Python, je trouve ça vraiment très dommage. On pourra me dire que ça rend le programme plus lisible, mais au contraire, devoir passer "de droite à gauche" comme on le fait dans un format en C ne rend que le programme moins lisible. C'est un détail mais c'est prodigieusement agaçant quand on programme avec Python.

    objet ? pas objet ?

    On fait la publicité de Python comme langage objet. Mais pourquoi n'ont-ils pas fait les choses jusqu'au bout ? C'est objet mais pour avoir la longueur d'une chaîne, là où Ruby a fait le boulot correctement (chaine.length) en Python c'est len(chaine). Conversion d'une chaine vers un entier ? En Ruby je fais chaine.to_i en Python rebelote je dois faire int(chaine).

    Notons que je n'affirme pas que Perl est mieux là-dessus, Perl est une catastrophe pour l'objet (on peut quand même être heureux d'avoir l'héritage multiple en Perl, surtout quand on fait du Java par ailleurs) ; mais plutôt que si on veut un langage de script élégant, moderne, où tout est objet, il faut vraiment choisir Ruby sur Python.


    Et voilà ma conclusion sur Python, je disais que l'absence de fonctionnel l'alimenterait ; les points ci-dessus aussi. Je vais te choquer certainement si tu aimes bien Python, mais je le dis car je l'argumente : pour moi, Python est un bon langage pour mauvais programmeur. Il est parfait dans ce cas-là car il interdit beaucoup de choses élégantes et/ou puissantes car trop compliquées et "imbitable/illisible". Je suis d'accord qu'avec Python il est facile de relire le programme d'un autre, du coup. Mais par contre quand je programme en Python, je m'arrache les cheveux en ayant l'impression d'être castré comme chez Java. Il est bon pour les mauvais programmeurs car tu es sûr qu'ils ne te feront pas quelque chose d'aussi dégueulasse que si ils avaient programmé en Perl ou en C++. Mais je trouve, en tant que programmeur expérimenté (ça sonne prétentieux je sais mais bon ça fait un certain temps que j'en fais, je connais quelques trucs, il m'en reste plein à apprendre et je rencontre souvent des gens qui m'apprennent des choses insoupçonnées, mais je suis expérimenté quand même na), qu'utiliser Python restreint trop l'expressivité de mes programmes et par là-même la vitesse de développement, sans apporter de vrai bénéfice de maintenabilité (on peut faire aussi maintenable en Perl et en Ruby en suivant des consignes cohérentes de style de programmation, qui sont de toutes façons indispensables avec n'importe quel langage quand on développen en équipe).

    En deux mots, Python suxor :).


    [1] solution : remplacer "class Foo:" par "class Foo(object):" ; j'ai eu de la peine à comprendre le rapport entre le message d'erreur et ça (le "super argument 1" c'est Bar, pas Foo, que je sache !?) et encore moins la différence entre les deux définitions de classe, je ne vois pas trop ce qu'une "classe" peut être d'autre qu'un objet et donc je pensais sincèrement qu'elle héritait implicitement de la top-class object, mais bon apparemment non ; d'ailleurs dans ton code plus haut tu n'hérites pas d'objet, attention à ne pas te heurter un jour à ce problème