PROJET AUTOBLOG


Sam & Max: Python, Django, Git et du cul

Site original : Sam & Max: Python, Django, Git et du cul

⇐ retour index

Réduire la taille de pdf en ligne de commande

mardi 18 mars 2014 à 08:45

Use case : besoin d’envoyer une PDF par email et il fait plus que la taille de pièce jointe autorisée :

gs -dBATCH -dNOPAUSE -q -sDEVICE=pdfwrite -sOutputFile=sortie.pdf fichier.pdf

Au passage, ça peut servir à concaténer plusieurs fichiers pdf, même si pour bouger, retirer ou ajouter des pages, pdfmod est bien plus pratique.

flattr this!

Ca y est, on peut coder en Python 3

lundi 17 mars 2014 à 12:29

Python 3.4 vient de sortir, et avec cette release, je peux enfin recommander aux gens de se mettre à Python 3 plutôt que Python 2. Tout simplement parce que maintenant, en plus d’avoir énormément de libs qui ont migré, on a l’expérience de la bestiole. C’est stable, les perfs sont bonnes, la conversion de code d’une version à l’autre est bien documentée et maitrisée.

Et surtout, la 3.3 et la 3.4 viennent avec tout un tas des goodies super green.

Voici tout ce dont vous pouvez profiter avec Python 3 que vous ne pouvez pas faire avec Python 2.

Des classes classes

Les classes sont des new type classes en Python 3. Pas besoin d’hériter d’object:

# Au revoir !
class TouteMoche(object):
    pass
 
# Bonjour !
class PropreEtNette:
    pass

Les metaclasses ne se définissent plus comme un attribut spécial :

# Au revoir !
class TouteMoche(object):
    __metaclass__ = UnTruc
 
# Bonjour !
class PropreEtNette(metaclass=Untruc):
    pass

Super Super()

Franchement, qui se souvient de la syntaxe pour appeler proprement la méthode parente d’une classe ?

# Au revoir !
class FranchementHein(object):
 
    def __init__(self):
        super(FranchementHein, self).__init__()
 
# Bonjour !
class FranchementHein:
 
    def __init__(self):
        super().__init__()

Meta meta programmation

Le module inspect permet maintenant de récupérer des infos très très précises sur la signature des fonctions :

    >>> from inspect import signature
    >>> def foo(a, *, b:int, **kwargs):
    ...     pass
 
    >>> sig = signature(foo)
 
    >>> str(sig)
    '(a, *, b:int, **kwargs)'
 
    >>> str(sig.parameters['b'])
    'b:int'
 
    >>> sig.parameters['b'].annotation
    <class 'int'>

Et comme vous pouvez le voir, les annotations sont de la partie.

Les classes ont également un nouvel attribut __qualname__, qui, comme on peut s’y attendre, est le qualified name de la classe :

>>> class C:
...   def f(): pass
...   class D:
...     def g(): pass
...
>>> C.__qualname__
'C'
>>> C.f.__qualname__
'C.f'
>>> C.D.__qualname__
'C.D'
>>> C.D.g.__qualname__
'C.D.g'

Ca marche aussi pour les fonctions.

Enfin pour les gars qui sont vraiment tordus, on a une nouvelle méthode pour les metaclasses, __locallookup__, qui permet d’influencer le MRO à la volée.

Un yield qui yield

Bon, mon titre ne veut rien dire, c’était pour la continuité.

yield a maintenant un petit frère, yield from, qui permet de déléguer l’itération à un itérable sous jacent :

def generateur():
    yield from "123"
    yield from (str(x) for x in range(4, 7))
    yield from ("7", "8", "9")
 
for i in generateur():
    print(i)
 
## 1
## 2
## 3
## 4
## 5
## 6
## 7
## 8
## 9

Là ce n’est pas très utile, mais sur des générateurs complexes, c’est sympa. Surtout que yield from passe aussi les valeur avec send(), fait remonter les exceptions proprement et est détecté par les events loops du module asyncio, dont on parlera plus tard.

Batteries included, with charger

Pip et virtualenv sont livrés avec la 3.4 ! Rien de plus à faire, rien à installer ! Enfin !

Malheureusement pas virtualenv wrapper, mais c’est déjà pas mal.

Un nouveau format, le wheel, permet de faire des paquets binaires qui n’auront pas besoin d’être compilés sur la machine cible. Ca veut dire bientôt du numpy / scipy sans avoir à compiler quoi que ce soit. C’est un remplacement du egg plus simple et sans les problèmes de compatibilités. Il ne vise pas la distribution de projets Python standalones, comme le egg qui a notamment eu le problème de vouloir tout faire en même temps.

Pour ce dernier, le pyz est en discussion.

Enfin les scripts Python supportent maintenant l’équivalent du shebang, mais sous Windows. Ceci vient avec l’introduction de la commande py qui permet de lancer toutes les commandes Python (pip, venv, etc.) pour une version de Python installée spécifique.

Ah, non, pas “enfin”, j’ai oublié un truc :

python -X faulthandler votre_script.py vous permet maintenant d’obtenir une stacktrace sur les scripts utilisant ctypes \o/. Et le module tracemalloc permet d’enquêter sur l’allocation mémoire.

Tout un tas de trucs que les codeurs Java vont adorer

Il y a des Enums, et ça vient sous toutes les formes :

from enum import Enum, IntEnum
 
# La version de feignasse :
Animal = Enum('ant bee cat dog')
 
# La version 'anal retentive'
class Animal(IntEnum):
     ant = 1
     bee = 2
 
# et tout ce qu'il faut entre les deux pour les centristes

Pour les nostalgiques de l’overloading, on peut maintenant spécifier que le code d’une fonction est différent selon le type des arguments qui lui sont passés :

from functools import singledispatch
 
@singledispatch
def fun(arg):
    print('Comportement par défaut, teddy')
 
@fun.register(int)
def _(arg):
    print("Tu m'as passé un int, jonhy !")
 
class Cacatoes:
    pass
 
@fun.register(Cacatoes)
def _(arg):
    print("Tu m'as passé un Cacatoes, billy !")
 
 
fun('Do')
fun([])
fun(1)
fun(Cacatoes)
 
## Comportement par défaut, teddy
## Comportement par défaut, teddy
## Tu m'as passé un int, jonhy !
## Tu m'as passé un Cacatoes, billy !

Et puis le module abc pour faire des classes abstraites, même si ça a été backporté en Python 2.7, donc un peu hors sujet.

Les built-in ont un peu changé

Pour le texte, c’est de l’unicode partout, avec utf8 par défaut pour les conversions. Ca veut dire plus de u devant les chaînes de caractère, plus de déclaration de l’encoding en haut des fichiers de code. Moins de decode / encode.

Mais ça veut dire aussi que open a besoin obligatoirement d’un paramètre encoding, dont la valeur par défaut est bien entendu utf8.

Attention cependant, le built-in bytes n’est pas l’exacte équivalent du type str en Python 2 puisqu’il ne possède plus certaines méthodes de manipulation de texte comme replace:

>>> "Trololo".replace('o', 'a')
'Tralala'
>>> b"Trololo".replace('o', 'a')
Traceback (most recent call last):
  File "<ipython-input-5-f7e93d6f629e>", line 1, in <module>
    b"Trololo".replace('o', 'a')
TypeError: expected an object with the buffer interface

C’est un peu chiant quand on manipule des protocoles binaires, et les mecs de mercurial ont un peu gueulé. Donc il est possible que ça change. J’ai mis beaucoup de fois le mot “peu” dans cet article, ce qui est stylistiquement très laid. Mais je suis trop paresseux pour éditer cet article qui fait maintenant 3 km.

Pour les nombres, on n’a plus à se soucier du type long, qui n’existe plus. / est maintenant la division ordinaire et // la division entière.

Pour les fonctions built-in, pas mal de changements avec bien entendu, print() qui devient une fonction, mais aussi toute ce qui est zip, map, etc, qui retournent des générateurs au lieu de listes, tout comme dict.items et consorts. Ah oui, et import est maintenant absolu par défaut.

Quelques libs en plus

Marre du module os ? pathlib permet de donner un petit goût d'objet à vos manipulations de FS, comme path.py. Ca reste moins bien, mais c'est mieux que rien.

Raz-le bol de recoder la fonction moyenne, médiane, etc ? Le module statistics a été ajouté pour ça.

Enfin, le fameux module mock, qui permet de simuler tout un tas de trucs sans tout casser :

>>> from mock import patch
>>> with patch.object(os, 'listdir', return_value=['file2.txt', 'file2.text']):
    print(os.listdir('/etc/'))
...
[u'file2.txt', u'file2.text']
>>> os.listdir('/etc/')[:2]
[u'environment', u'hosts.allow']

Tout est bien rangé

Les fichiers bytecode Python sont maintenant tous groupés dans un dossier appelé __pycache__. Finis les .pyc qui trainent partout. Et en plus prefixés de l'architecture avec laquelle ils ont été générés. Toujours utile.

En prime pas mal de noms ont été normalisés : tous les modules sont maintenant en minuscule, tous les modules liés à IO sont groupés dans le module io, urllib 1 et 2 ont été mergés, et l'arborescence des exceptions pour les erreurs d'IO a maintenant beaucoup plus de sens :

# Au revoir !
from errno import ENOENT, EACCES, EPERM
 
try:
    with open("document.txt") as f:
        content = f.read()
except IOError as err:
    if err.errno == ENOENT:
        print("document.txt file is missing")
    elif err.errno in (EACCES, EPERM):
        print("You are not allowed to read document.txt")
    else:
        raise
 
# Bonjour !
 
try:
    with open("document.txt") as f:
        content = f.read()
except FileNotFoundError:
    print("document.txt file is missing")
except PermissionError:
    print("You are not allowed to read document.txt")

Asyncio, la prog asynchrone rebootée

Une des raisons pour laquelle je tape sur javascript aussi fort, c'est aussi la jalousie. Ils ont tous les derniers joujoux asynchrones hi-tech, meh !

Avec Python on était obligé d'installer tornado ou twisted pour ça, et c'était un peu dommage :)

Avec la 3.4, la prog asynchrone fait peau neauve (adieu l'horrible module asyncore) et propose de la prog asynchrone plus simple, plus légère, plus facilement intégrable : asyncio.

Si vous lisez ce PEP, ça ne va pas vous parler, alors je vais potasser tout ça et faire un petit article.

Mon seul regret avec asyncio, c'est que c'est un module uniquement bas niveau, alors que tulip, le prototype de la lib, contenait des mobiles haut niveau comme par exemple un client http bien foutu. Du coup ça a donné ce genre de discussion sur le blog, avec des gens qui ne comprenaient pas que je m'attendais à un peu de haut niveau et eux qui ne voyaient que le bas, et donc s'attardaient sur de la sémentique d'implémentation de la prog non blocante.

En conclusion

Le code Python 3 est plus court, plus cohérent, avec moins de surprises, moins de dépendances externes et plus de flexibilité. Des comportements par défaut sains un peu partout, des outils en plus, et comme d'habitude vous n'en utiliserez pas la moitié tellement il y a à faire.

Python 3.4 est vraiment un très bon cru, honnêtement, avec toutes ces améliorations, le langage parvient à se maintenir au niveau des petits jeunes et de leur hype, sans sacrifier sa solidité et sa cohérence.

C'est pour ça qu'on a attendu 5 ans. C'est pour ça que la migration a été lente et prudente.

Parce que la communauté Python fait vraiment les choses bien.

Les exemples du blogs seront donc à partir de maintenant en Python 3.

flattr this!

Un coup de langue sur l’Oculus Rift

dimanche 16 mars 2014 à 20:17

Complètement par hasard, j’ai pu passer quelques minutes avec un Oculus Rift.

Le casque est léger et pas inconfortable, et isole très bien du reste du monde, allant dans le sens de l’objectif d’immersion du produit. L’image n’est pas en haute résolution, et comme l’écran est très proche des yeux, on voit les pixels assez grossièrement, surtout en comparaison des écrans HD des dispositifs mobiles actuels. L’image est également un peu saccadée.

Il faut dire que j’étais sur un prototype destiné aux dev.

Mais si on met de côté ces problèmes qui sont naturels sur un dispositif en cours d’élaboration, le résultat est très prometteur. Malgré une vision loin des 180° (on est plus proche du casque de paintball), l’angle est asez confortable et on ne se sent pas trop bridé. Tourner la tête fait changer l’angle de vision de manière naturelle et fluide, et l’expérience est particulièrement bluffante quand on se retourne pour regarder derrière soit.

Le plus fun, c’est la sensation de vitesse. Une accélération avec pour seul repère les lunettes donne vraiment ce sentiment grisant qu’on a IRL.

Qui dit nouvelle techo dit nouvel apprentissage. Le corps perd en effet complètement ses repères. D’une part, on ne voit pas ses propres membres bouger. D’autre part, on voit un mouvement que l’oreille interne ne subit pas, et je paries sur des bonnes nausées pour les gens sensibles au mal des transports.

Désolé, je n’ai pas d’image de la scène. Comme je le disais, ça s’est fait vraiment à l’arrache, donc j’avais rien sur moi pour immortaliser le moment.

Dans tous les cas, mes fantasmes d’utilisation du dispositif comme station de travail portable ont été tués dans l’oeuf. On ne peut clairement pas dev avec ça pour le moment.

Par contre, pour un FPS ou un survival horror, ça peut donner un truc fantastique.

flattr this!

10 trucs que je déteste en Python

samedi 15 mars 2014 à 07:52

Il faut savoir être honnête dans la vie, et puisque j’ai tapé sur le JS dans le dernier article, on va rappeler que rien n’est parfait et que chez les Pythoneux aussi y a du boulot.

Le piège des paramètres par défaut mutables

C’est le “ne pas faire” le plus connu en Python. Mais même en étant au courant on se fait TOUS baiser un jour.

def transfert(source, res=[]):
	# faire un truc qui passe des élement de
	# source à res

Ce code va remplir res d’appels en appels, qui ne sera donc plus une liste vide dès le second appel.

It’s a feature, not a bug, mais c’est pourtant rarement ce qu’on veut.

L’opérateur pour les tuples est la virgule, pas les parenthèses

C’est pratique car ça permet de rendre l’unpacking propre et élégant. Mais c’est aussi un coup à se tirer une balle dans le pied :

>>> t = ("a") # ceci n'est pas un tuple !
>>> type(t)
str
>>> t = "a", # grrrr
>>> type(t) 
tuple
>>> t = () 
>>> type(t) # WAIT WAT ?
tuple

Et comme les string sont itérables, la boucle for marchera toujours, silencieusement, jusqu’à ce que bug s’en suive.

Pas de set literal vide

On peut faire set(), on peut faire {1}, on peut faire () mais on ne peut pas faire {} puisque c’est un dico, ni {,} puisque c’est une syntax error. Ces deux lettres à taper en plus pèsent sur ma conscience.

Le packaging

Packager un programme Python est une grosse galère. Créer un setup.py est facile, mais savoir comment le créer, c’est une autre histoire. En fait le seul tuto valable sur la question est celui de ce blog, et il commence à être vieux. Vous savez pourquoi ? J’ai pas la foi de le mettre à jour car ça veut dire de nouveau passer des heures à me renseigner sur ce qu’il faut faire maintenant.

En fait un exe ou un deb devrait se faire en une ligne de commande.

Les modules inutiles de stdlib

Vous saviez qu’il y a un module pour lire les fichiers WAV dans la stdlib ? Sérieusement, qu’est-ce que ça fout dans la lib standard ?

La convention de langage, pas respectée dans la stdlib

Même après le nettoyage de Python 3, des libs existent qui utilisent le camelcase pour les noms de méthodes comme par exemple unittest. Le code de ces libs lui-même n’est pas PEP8, ce qui craint dès qu’on veut voir comment c’est fait à l’intérieur.

La concaténation automatique fonctionne à côté de l’opérateur virgules

J’adore le fait que :

("1"
"2")

Se concatène automatiquement.

Mais ça devrait lever une syntax error quand c’est déclaré à côté de virgules pour éviter cette merde :

var = (
"1",
"2"
"3"
)

Combien de fois je me suis fait niquer avec ça dans settings.py

On n’a pas accès au bloc de code dans un with

Il y a des tas de context managers géniaux qu’on pourrait faire si on avait accès au bloc de code exposée dans la close with comme on pourrait le faire avec lisp. Cette limitation m’a frustré plus d’une fois.

Pas de plug de code à chaud

Je rêve de cette feature.

Ecrire du code parallèle, concurrent ou non bloquant est lourd

Syntaxiquement c’est pas top, surtout qu’on doit contourner souvent le GIL. Une grosse amélioration pour l’io async arrive avec la 3.4 mais elle sera surtout bas niveau.

Y a pas de point 10

Ce langage est fantastique.

Ce qui n’est PAS un problème à mes yeux

Le passage à Python 3

A mon sens, brillament exécuté. Je sais que les gens pensent que ça prend un temps fou et que ça a foutu la merde, etc. Mais en vérité, c’est un des rares langages qui ait géré la transition aussi bien : largement documentée, outillée et suivie, bien soutenue par la communauté, avec tout le temps qu’il faut pour la transition mais une direction ferme de la part du BDFL. En plus il est POSSIBLE d’écrire du code qui fonctionne dans les deux versions alors qu’elles sont supposément incompatibles. C’est assez fou quand on y pense.

Il y a d’autres langages qui n’ont jamais réussi ce genre de changements, comme PERL (qui en est mort) ou PHP (qui a avorté).

Les espaces significatifs

Best. Feature. Ever.

Les lambdas sur une ligne

Ne pas toujours pouvoir faire des fonctions anonymes pour les callback, c’est un peu moins élégants, mais sinon, ça ne me manque pas.

L’encoding

Les gens râlent sur la gestion de l’encoding Python parce qu’ils ne comprennent pas ce qu’ils font. Mais personnellement je trouve excellent que le langage te force à gérer CORRECTEMENT tes encodings ou te lève une erreur. J’ai vu tellement de bases de données corrompues, de scripts qui affichent des hiéroglyphes, des “?” plein les pages Web, que je me dis que trop de personnes ignorent juste complètement la question. Et le jour où ça merde, ils passent un mois à réparer.

En 2.7, cette gestion était assez verbeuse par contre, et je suis bien content que ça change en 3.4.

flattr this!

Un gros Troll de plus sur Javascript

jeudi 13 mars 2014 à 21:02

Un commentaire très pertinent de Kontre m’a interpellé dernièrement : si Javascript est si pourri, pourquoi tout le monde s’y intéresse ?

TD;DR :

L’inertie technique.

Il faut bien comprendre que PERSONNE ne s’intéresse à Javascript directement. Les gens s’intéressent passionnément à la programmation Web. Et il se trouve que, concernant la programmation côté client, il y a QUE Javascript de disponible.

Quand Ajax est arrivé, des mecs brillants ont rendu le Web plus interactif. Et ils ont utilisé ce qui était implémenté partout : Javascript. Pas parce qu’ils aimaient Javascript. Pas parce que Javascript était un bon langage.

Parce que c’était la seule solution dispo.

Avant, personne ne s’intéressait à ce truc. C’était un langage de script kiddies pour faire des flocons de neige sur les pages HTML. Et donc tout le monde se foutait royalement que ce soit de la merde. IE l’avait implémenté parce que Netscape l’avait fait. C’était alors un gros hybride qui tentait de rassurer les codeurs C et Java. Javascript était marketing, jusque dans le choix du nom. Puis IE6 a gardé le pouvoir pendant 10 ans, et du coup, tout le monde a suivi.

Personne n’a réfléchi. Personne n’a vu venir l’explosion du Web. Personne ne s’est dit “les gars faudrait peut être faire attention, le status quo pue la merde”. A cette époque, ça n’avait pas d’importance, on a mis les efforts de guerre ailleurs.

L’heure du Web 2.0 a alors sonné, et là les business ont eu besoin de puissance de feu. Mais c’était trop tard, il n’y avait plus qu’un seul truc hideux de dispo pour la prog…

Google a utilisé massivement les pages dynamiques, et devant le constat des performances misérables de la seule techno qu’il y avait a dispo, il a pondu chrome, et sa VM Javascript ultra performante. Si on avait appliqué la même techno à n’importe quelle autre langage, on aurait obtenu 10 fois cette vitesse.

C’est quand Google a enfin pu donner des perfs décentes – c’est à dire celles qu’ont d’autres langage depuis une décennie – à Javascript que les gens ont envisagé de l’utiliser sur le serveur. Encore une fois, pas parce que Javascript était une techno dont ils étaient fondamentalement amoureux.

Parce qu’ils voulaient éviter d’écrire deux fois le même code côté client et côté serveur et que toute tentative de générer du Javascript n’a pas été satisfaisante. Et aussi parce que le besoin de faire de l’asynchrone se faisait sentir et que les Dev clients n’avaient pas envie d’apprendre un autre langage. Ben oui, l’asynchrone, vous croyez que pas que ça existe que sur JS quand même ? C’est aussi vieux que les premiers compilateurs. Les Devs clients connaissaient déjà le JS, et ça faisait du DRY, alors pouet.

Personne. J’ai bien dit, personne ! Ne s’est jamais extasié devant l’incroyable ergonomie de Javascript. Devant sa facilité de debuggage. Devant la qualité de sa doc.

Dessin humoristique sur la recherche de travail

Cherche Dev Javascript pour travailler sur projet innovant dans une start up à fort potentiel de croissance.

Ruby est un langage innovant and fun.

Python est un langage ergonomique and riche.

Php est un langage avec une super doc et une communauté noob friendly.

Lisp est un langage puissant avec un paradigme fonctionnel de référence.

Go est un langage propre avec une gestion de la concurrence très performante.

Javascript est juste là par hasard. Il ne dépasse aucun des langages ci-dessus en terme de ses qualités propres. Sa bibliothèque standard est risible. Il ne sert absolument à rien sans un framework côté serveur, et côté client il est parfaitement improductif sans une lib pour gommer les incompatibilités entre les implémentations.

Les docs sur JS sont éparpillées sur le Web. Les tutos sont déchirés entre tant de versions et de frameworks qu’on se croirait dans un script des frères wachowski.

Des notions de base comme les closures sont encore obscures pour la plupart des codeurs Javascript, alors qu’elles peuvent ruiner les perfs de votre programme ou créer des bugs énormes. Les projets innovants en Javascript sont tous faits par des gens hyper compétents parce qu’innover dans ce langage, ça demande une discipline de dingue tellement il offre d’opportunité de merder.

Javascript est un hack qu’on se traine.

C’est un bug legacy.

C’est un virus préinstallé dans les navigateurs.

Photo du film le dictateur

Ma Fureure, vous ne voulez pas utilisez le C# plutôt ? Naïne, toutes nos troupes sont déjà tatoués sur la fesse gauche, on va devoir y aller comme ça.

Oui il y a des produits à base de Javascript fantastiques. Oui les innovations techno Web actuelles intéressantes tournent toutes autour de Javascript de près ou de loin. Et oui, vous devez définitivement mettre les mains dedans parce que le monde du dev avancera en dépit de vos goûts. En tout cas, en dépit des miens, j’en ai bien conscience.

Mais ceci ne se fait pas grâce à Javascript. Ceci se fait en dépit de Javascript. Malgré le fait que c’est un langage au typage pourri, malgré son scoping dégueulasse, malgré l’absence des facilités modernes les plus basiques comme le passage d’arguments avancés ou un slicing décent.

Parce qu’il y a des gens très (TRÈS) bons qui ont eu Javascript comme contrainte, et qui en ont tiré le meilleur. Et c’est pas faute d’avoir essayé autre chose (Flash, GWT, Haxe…). Ces mecs sont incroyables, ce sont des Dieux vivant, Amen to them, mais Javascript reste à chier.

Et on va se le coltiner encore très, très longtemps.

Au cas où vous ne l’aurez pas encore compris, je vomis sur Javascript. Mais je code avec, et j’offre même des formations dessus, car je suis pragmatique. Les besoins de l’industrie, l’inertie technologie et le contexte social / technique / économique dictent bien plus souvent les standards que nous utilisons que leurs qualités intrasèques. Sinon nous n’aurions pas utilisé le format .doc ou les VHS.

En fait, je ne détesterais pas autant Javascript si je n’en avais pas besoin quotidiennement. Je le hais du plus profond de mon âme justement parce que c’est non seulement une contrainte inamovible de mon métier, mais en plus une tumeur que les chercheurs annoncent voir grossir de jour en jour. Avec le sourire, les connards !

Le VB est peut être pire que le JS, mais je m’en branle, je n’ai pas à y toucher.

Après cet argumentaire, je précise que je ne mettrai pas de tampon sur les commentaires, parce que je comprends bien que je ne peux pas lâcher une caisse et demander à tout le monde de respirer à fond et ne pas se plaindre.

Néanmoins, puisque cet article à des vocations thérapeutique – vous êtes tous un peu mes psy au fond (la confidentialité bloggeur / lecteur, ça marche ?) – voici un listing de tout ce que j’abhorre dans le Javascript.

)

Les experts recommandent d’éviter la moitié du langage

Il y a tellement de merdes dans JS que les plus grands experts s’accordent sur le fait que la première chose à faire est d’apprendre la liste des choses à ne PAS utiliser.

En fait, Douglas Crockford lui même a écrit un bouquin complet rien que sur le sujet.

Je n’ai pas tout en tête, mais en vrac…

Ne pas utiliser l’opérateur ==, parce que :

''        ==   '0'           // false
0         ==   ''            // true
0         ==   '0'           // true
false     ==   'false'       // false
false     ==   '0'           // true
false     ==   undefined     // false
false     ==   null          // false
null      ==   undefined     // true
" \t\r\n" ==   0             // true

Notez que même === ne retire pas toutes les ambiguïtés :

> var a = { "abc" : 1 }
> a[[[["abc"]]]] === a["abc"]
true

Ne pas utiliser parseInt sans préciser la base sinon :

> parseInt('06')
6
> parseInt('07')
7
> parseInt('08')
0
> parseInt('09')
0
> parseInt('10')
10

Bien se souvenir d’utiliser var partout. En fait activer use strict dès que possible pour éviter l’insertion de ; automatiques.

Et ne pas utiliser la syntaxe de déclaration de variable sans var. Cependant, faites gaffe quand vous convertissez du code parce que :

> a = 1
1
> var a = 1
undefined

Encore une connerie. Mais vous avez l’habitude :)

Ah oui, et ne pas utiliser les mots clés new ou with pour vos propres libs. Si, si, on bannit carrément des mots clés, c’est écrit dans le livre.

Phot d'un gant de vaisselle avec des pansements

Ce gant est fantastique, si vous ignorez tous les trous il vous permettra de faire la vaisselle aussi bien que tous les autres gants. Comme ça vous êtes jardinier ? Remarquez, j'avais créé le produit pour faire des touchers rectaux à la base, donc il est adaptable !

Faire du JS propre présuppose l’utilisation de design patterns

En l’état, on ne peut pas écrire du JS propre. Écrire la plus simple instruction Javascript est déjà écrire du code sale car toute variable devient globale. Il faut tout foutre dans un conteneur quelconque, souvent dans une fonction anonyme immédiatement appelée, mais il y a d’autres techniques (services avec injection de dépendance dans angularjs par exemple).

Pour être honnête, on commence à peine à savoir écrire des grosses applis Javascript propres côté client depuis quelques années. Ca a pris un temps fou de trial / error pour gommer petit à petit tous les aspects guedin de la techno et obtenir un socle utilisable.

Un autre truc : personne ne s’est mis d’accord sur l’utilisation des objets : prototypage, simulation d’héritage, instanciation ou pas, composition uniquement ? En tout cas vous devez en choisir un, et ne pas le merder.

Au fait, vous avez déjà essayé d’expliquer le prototypage à quelqu’un ? Bonne chance !

Non seulement c’est du typage faible, mais en plus c’est du typage con

J’ouvre Firefox, je tape:

> {} + {} // Ceci n'est effectivement PAS un nombre
NaN
> {} + [] // logique IMPARABLE
0
> [] + {} // fuck la commutativité
"[object Object]"

Et après on va me dire que c’est juste l’API DOM qui est incohérente selon les implémentations. Mais non, tenez, même ça c’est cohérent. Je fais la même chose sous Node 0.8 (sur lequel j’ai par ailleurs déjà râlé):

> {} + []
'[object Object]'

On pourrait continuer longtemps avec ces saloperies, mais je finis sur un exemple qui résume bien tout le merdier :

> '5' + 3
'53'
> '5' - 3
2
> "Vous en étiez à... peau de couilles je crois ?" + 1
'Vous en étiez à... peau de couilles je crois ?1'
> "Vous en étiez à... peau de couilles je crois ?" - 1
NaN

Et vous pouvez toujours vous dire que si vous faites attention, vous n’aurez pas de problème, mais ça a des répercussions sur TOUT le langage, dans les recoins les plus vicieux :

> Math.min(null, 1234)
0
> Math.min('null', 1234)
NaN
> Math.min('1', 1234)
1

L’élégance d’un chameau bourré à la villageoise

On se déchaîne

Ruby :

coucou = """Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !
Sur plusieurs lignes !
Et une autre !
Et une autre !
J'adore les sauts de ligne, c'est tellement lisible !!!
"""
puts coucou

Python :

coucou = """Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !
Sur plusieurs lignes !
Et une autre !
Et une autre !
J'adore les sauts de ligne, c'est tellement lisible !!!
"""
print coucou

Javascript :

var coucou = "Ceci est une looooooooooooooooooooooooooooooooooooooooongue chaine !" +
"Sur plusieurs lignes !\n" +
"Et une autre !\n" +
"Et une autre !\n" +
"J'adore les sauts de ligne, c'est tellement lisible !!!\n"
console.log(coucou)

C’est vrai que manipuler des chaînes, c’est pas la PUTAIN D’OPERATION INFORMATIQUE LA PLUS COURANTE DANS LE PUTAIN DE MONDE. PUTAIN.

Séquence émotion

Une autre opération qu’on fait 100 fois par jour : créer des séquences (fichiers, settings, données en base, etc), en récupérer une partie, itérer dessus, les transformer, etc.*

Soit la liste :

l = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

Récupérer les carrés des nombres paires de la moité supérieure de la liste ?

Python :

l = [x*x for x in l[5:] if x %2 == 0]

Ruby :

l = l[5..10].select{|x| x % 2 == 0 }.collect{|x| x * x}

Javascript (Ma que, gracieux comme oune popotamé):

var new_list = []
l.splice(0, 5)
for (var i = 0; i < l.length; i++) {
    if (l[i] % 2 == 0) {
        new_list.push(l[i] * l[i]);
    }
}
l = new_list;

Et encore, je suis cool, je mets un code JS qui utilise l.length directement dans la boucle et pas de variable pour l[i].

Array.map arrive avec JS 1.6 et les arrays comprehensions avec la 1.7, que vous pourrez utiliser sur tous les navigateurs d’ici 2056. Ou alors juste sur le serveur, mais si c’est pour pas avoir le même code sur le client ou le serveur, pourquoi ne pas utiliser un langage qui possède tout ça et bien plus depuis 5 ans ?

DéLire

Lire un fichier ligne à ligne ? Une opération vraiment rare et compliquée…

Python :

for line in open('fichier'):
    print line

Ruby :

File.foreach('/etc/fstab') {|x| print x }

En JS… Heu, enfin avec NodeJS:

var fs  = require("fs");
fs.readFileSync('./input.txt').toString().split('\n').forEach(function (line) {
    console.log(line);
});

Ah oui, il faut installer un MODULE SUPPLEMENTAIRE pour gérer tout autre encoding que les variantes d’unicode.

PASramètre

Comment on fait ça en Javascript ?

def fonction(param, param2="valeur", **params):
    print param, param2, params
 
fonction(1, autre_valeur=2)

On fait pas. Du coup on se retourne vers la bonne vieille technique de “j’attends un objet en paramètre et je le fusionne avec un autre objet qui a mes valeurs par défaut”.

Photo d'un homme avec un chapeau giraffe

Dev JS qui essaye de comprendre pourquoi le callback anonyme de sa promise n'a pas rebindé correctement son this dans une closure . Oui cette phrase a parfaitement du sens en Javascript.

Javascript ça marche partout !

Node ne tourne pas sous Windows, excluant de sa pool d’apprentissage les 3/4 des foyers de la planète. Parce que je sais pas pour vous, mais moi, quand j’ai appris la programmation, j’ai pris le premier ordinateur qui m’est tombé sous la main et j’ai essayé. Parce que je n’y connaissais rien. Je ne me suis pas soucié de l’OS.

On me signale dans la comemntoreillette que j’ai dis une connerie.

Ah oui, et sans node, le Javascript on en fait quoi déjà ?

Ah mais il faut utiliser coffeescript !

Oui donc pas Javascript. Point made.

Le langage est tellement à chier qu’on a inventé un autre langage pour le générer et pas avoir à s’en soucier. Et ensuite, on a inventé des libs pour automatiquement faire cette compilation pour le dev, et les outils pour le déployer. Et on a inséré dans les navigateurs une nouvelle technologie : le source map, parce que sinon c’était trop chiant à débugger. Qu’il faut aussi déployer pendant le dev. Et former les gens dessus.

Vous trouvez ça normal ?

Vous trouvez que c’est le signe d’un BON langage ?

Ouai mais ça fait un seul langage côté server et client

Oui, c’est pour ça que les gens s’y mettent. Encore une fois, ça n’a rien à voir avec les qualités de Javascript. Ca reste de la merde en boîte, mais de la merde unifiée.

Et encore, car si on a bien le même langage, on est loin d’avoir le même code. Le code serveur et le code client est, sauf dans les frameworks avancés comme météorjs, très peu partagé au final. Surtout que vous n’avez PAS la même version du moteur Javascript côté serveur et côté client.

Les libs externes bien conçues marcherons de la même façon par contre, ce qui est un avantage.

Encore une fois, la question n’est pas “est-ce que les gens doivent utiliser Javascript ?” La réponse à cette question est oui. Pas le choix.

Mais on ne l’utilise pas parce que c’est un bon langage. On l’utilise parce que c’est le status quo. Qui est tout pérave.

Arrête de baver et donne nous ta solution !

J’ai pas de solution parce qu’il n’y en a pas. C’est trop tard. Le Javascript et là et on l’a dans le cul. D’où ma frustration. La 1.7 va dans la bonne direction, mais le temps qu’elle soit adoptée partout.

Par contre si ce n’est pas trop demandé, arrêtez de mettre du Javascript partout. Limitez la contamination. Vous n’avez pas vu “28 jours plus tard” ? Il faut isoler le problème avant que la pandémie ne dévore l’humanité. Il y a des tas d’alternatives : Python, Ruby, Clojure, Go, Lua…

Si vous faites un langage de scripting embarqué, si vous faites un outils de déploiement, si vous faites un premier binding pour votre outil… Ne donnez pas la prio à cette bouse. Quand je vois Gnome ou QT adopter le JS pour leur scripting, ça me met dans une rage folle. C’est de la connerie pure. Bordel, il y a un site appelé 99 bottles of beer avec des milliers de langages. Vous avez le choix !

C’est bien beau d’avoir le même langage partout, mais si c’est pour se trainer un boulet… Vous ne travaillerez pas plus vite.

D’ailleurs, vous n’aurez jamais le même langage partout. Vous aurez toujours à apprendre et utiliser 2 ou 3 langages. C’est un fait de la vie. Les humains ne parlent pas tous anglais ou chinois. Et les codeurs ne coderont jamais dans un espéranto, fusse-t-il fantastique.

Je sais, je sais, quand on vient du C, Javascript parait si facile, on se dit que c’est une amélioration de l’ergonomie au prix de la performance. Mais non, c’est comme acheter une 2 chevaux pour aller en ville à la place de son tracteur, alors qu’on vous avait proposé une smart ou une mini pour le même prix.

Par ailleurs, il y a une vie en dehors de la prog Web vous savez.

Si il n’y a pas de solution, ferme ta gueule alors

C’est mon blog, je fais ce que je veux. Na.

Photo d'un homme ayant son aspirateur coincé dans un ascenseur

Sam, passant directement du stade de la colère à la dépression dans son dueil de la programmation Web

flattr this!