PROJET AUTOBLOG


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

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

⇐ retour index

Mise à jour

Mise à jour de la base de données, veuillez patienter...

Est-ce la fin de jQuery ?

dimanche 12 octobre 2014 à 09:42

Avec un report massif des usagers sur des mobiles, la plupart sous un navigateur Webkit powered, on peut tabler sur un bien meilleur support de Javascript et ses APIs. Cela signifie qu’on a moins besoin d’utiliser des libs pour combler les trous, mais aussi la possibilité d’utiliser des frameworks comme AngularJS, MeteorJS, etc.

Est-ce pour autant la fin de notre bien aimé jQuery, qui nous a sorti de l’age sombre, et nous a tenu la main pendant cette dernière décénnie ?

Non.

Bien entendu, on utilise moins jQuery. On utilise parfois des choses plus légères. Parfois des choses plus lourdes. Parfois du JS pur.

Et il faut avouer que les projets parallèles à jQuery comme jQuery Mobile et jQueryUI n’ont jamais décollé. Merci Bootstrap et le responsive design.

Néanmoins, il reste des tas de choses pour lesquelles jQuery est utile.

Certes, il y a les versions light qui font “presque la même chose mais avec beaucoup moins de ko”. Mais c’est le “presque” qui finit par vous faire ajouter plein d’autres dépendances, pour finalement vous retrouver avec un truc qui fait “presque” la même taille que la lib que vous vouliez éviter, et qui ne sera probablement pas en cache. De plus, la documentation disponible n’est pas du tout comparable.

Et certes, il y a les outils bazooka, qui font tout, même le café. Mais les solutions comme Angular ne permettent pas une dégradation gracieuse du site, pèchent en référencement, et massacrent l’accessibilité. Les apps sont des bons candidats pour une “one page navigation”, mais pas les sites orientés contenus, quant aux hybrides…

Pensez aussi que même si vous codez pour des browsers modernes (donc pas IE8 qui limite ses sélecteurs à css 2.1), les APIs haut niveau comme querySelector et querySelectorAll sont très loin d’être aussi pratiques et puissantes que le bon vieux $(). Je ne parle même pas de la gestion des événements et d’Ajax qui sont toujours à chier en 2014.

Donc jQuery permet de rajouter cette petite touche de dynamisme à votre site statique, ou de faire un outil moderne sans sacrifier les aveugles et le PR. C’est un compromis entre puissance et simplicité. Et quand vous sortirez du cas standard, contrairement aux versions au bifidus actif allégé, la lib vous permettra de sauter le pas avec ses centaines de features, ou ses milliers de plugins.

Sans compter l’immense base de projets existants utilisant le bouzin, et qu’il va bien falloir maintenir. Bonne chance à ceux qui veulent porter un site avec jQuery vers un autre truc. N’oubliez pas non plus l’inertie technique. Et le temps de formation de la population de dev aux nouvelles technos. Surtout qu’en ce moment, avec l’avalanche de nouveaux trucs à tester/apprendre/valider, il va falloir gérer ses priorités. Ajoutez à ça la baisse drastique du niveau des devs sur le marché du travail :)

Bref, bien que j’apprécie et utilise les nombreuses alternatives à jQuery, il ne va pas disparaitre cette année, et probablement pas l’année prochaine.

Pas Hexactement

samedi 11 octobre 2014 à 12:50

Je préfère utiliser le terme francophone que français pour le public du blog. D’ailleurs, quand je retweet des offres d’emploi, je le fais pour les pays limitrophes à la France, et également le Canada ou l’Afrique du Nord et de l’Ouest.

Ce n’est pas un hasard. En effet, si on regarde les stats du blog :

France 	5,135
Belgium 	302
Canada 	130
Switzerland 	129
United States  States	105
Luxembourg 	64
Tunisia 	44
United Kingdom  Kingdom	40
Bulgaria 	39
New Caledonia	33
Algeria 	32
Réunion 	28
Morocco 	24

302 + 130 + 129 + 64 + 32 + 24 = 681 vues qui viennent de pays francophones, soit plus de 10 %. Le français est beaucoup plus parlé dans le monde qu’on ne le croit. Sans parler des expats, évidement.

Donc à tout ceux qui ne sont pas de l’hexagone, coucou !

Je suis assez épaté du chiffre Bulgare ceci dit.

L’équation du nichon

vendredi 10 octobre 2014 à 14:46

Alors que je remontais l’Ecosse en stop avec un vieil ami, nous nous sommes faits ramasser par des Suisses. On a terminé dans un village au dessus d’Inverness. Un de nos hôtes, bien pinté, nous confie de but en blanc avec son accent de Genève qu’il aime quand les femmes lui roulent la bite.

Je sais, ce n’est pas facile à expliquer sans geste. Vous voyez les brulures indiennes ? C’est le même principe, mais à la verticale, et sur sa teub.

Enrichi de cette révélation, j’ai compris à quelle point la diversité des plaisirs était vaste. Ici, parlant de la queue d’un inconnu suisse dans le décor de flashback de Highlanders, et surtout de la prise en main qu’il préférait, et qui me paraissant, à moi, parfaitement désagréable.

Malgré cela, je continue d’être surpris par la variété de manières de toucher des nibars.

Ma maman (avec laquelle je parle beaucoup de cul, allez comprendre mon évolution psychique plus tard) m’avait toujours dis qu’il fallait y aller tout doucement.

Mais sur le terrain, le manuel de formation ne sert plus à rien. Il y a celles qui aiment qu’on les caresse. Celles qui aiment qu’on les suce. Celles qui aiment qui les mordille. Les morde. Les prenne en main. Les malaxe. Les tire. Les tord. Les pince. Les giffle. Ou qu’on leur souffle doucement dessus.

Une meuf m’a sorti une fois qu’elle demandait à un copain boulanger de lui bouler les seins, comme les miches de pain, et qu’elle adorait ça.

Il y a les sensibles, et celles qui ne voient pas l’interêt. Les fragiles, et les masos. Les amoureuses de têton, et les fans de la colerette.

Et toutes s’attendent à ce qu’on sache quoi faire parce que “c’est pas bien compliqué”.

Bref, ayant hier couché avec une meuf qui adore qu’on lui tire-bouchonne les tétés, la mémoire de la précédente qui avait mal dès qu’on posait la main dessus m’est revenu en mémoire.

L’équation du nichon a trop d’inconnues pour être résolue a priori. Il faut de la data pour pouvoir en faire quelque chose. De la collecte IRL, avec une mise à jour régulière.

Aussi, en ce jour, je poste cet article solidaire de tous les hommes qui, une fois qu’ils ont retiré le soutif, doivent se lancer dans une étude empirique pour savoir quoi faire avec ces nouvelles mamelles.

Petite astuce cependant, apprenez à retirer un soutien-gorge d’une main, quitte à vous entrainer seul. Ca coûte rien, et c’est la classe.

Bien nommer ses variables en Python

jeudi 9 octobre 2014 à 11:42

There are only two hard things in Computer Science: cache invalidation and naming things.

Phil Karlton

Utiliser des bons noms est le geste de documentation le plus important d’un code. Je ne parle pas de bien formater le nom des variables. Pour ça, il y a le PEP8 et ce qu’il recommande tient en 3 lignes :

C’est tout.

Non, je parle de choisir un nom adapté et descriptif.

Le post est long, et vous savez que quand le post est long, je vous mets une musique d’attente.

Explicit is better than implicit

En Python, il n’y a pas de déclaration de type. Le nom d’une variable a donc d’autant plus d’importance pour expliquer ce qu’il y a dedans.

Prenez cet exemple :

best = []
for k, v in data.items():
    if v > top:
        best.append(k)

Quand on lit ce bout de code, on se demande :

Maintenant, avec des noms explicites :

best_players = []
for player, score in data.items():
    if score > top_score :
        best_players.append(player)

On comprend tout de suite de quoi il est question. L’algo n’a pas changé, seul le nommage a changé.

Et si on passe à une écriture plus compacte, le gain est encore plus net :

best = [k for k, v in data.items() if k > top]

VS

best_players = [player for player, score in data.items() if score > top_score]

Parfois, on veut la concision, mais faute de nommage, on doit se retourner vers les commentaires :

# Get players with the best scores
best = [k for k, v in data.items() if k > top]

Néanmoins, si on doit faire le choix entre commenter et bien nommer, le nommage doit avoir priorité. Le commentaire est important, mais c’est le dernier recours d’un code qui n’est pas explicite. Avoir un code clair doit être l’objectif premier. Ensuite, seulement, on le commente (abondamment toutefois, faut pas être radin).

Si vous avez suivi, je nomme mes variables en fonction de leur nature, pas leur type. On peut utiliser les règles de l’orthographe pour encore plus de précision, par exemple le pluriel.

fruits = ["kiwi", "banane", 'poire']
for fruit in fruits:
    print(fruit)

J’utilise le pluriel pour une liste de données, qui va donc potentiellement contenir plusieurs fruits. Mais j’utilise un singulier dans la boucle pour le fruit en court.

L’utilisation d’adjectifs est aussi le bienvenu :

fruits peut devenir, après un traitement filtered_fruits, indiquant que la liste a subit un filtrage. Les mots en “ed” en anglais aident beaucoup à la qualification.

On évite au maximum les variables courtes. Certains cas sont néanmoins tolérés. Le premier est l’utilisation de i, x, yet z pour des indices.

for i, fruit in enumerate(fruits):
    # faire un truc

Les indices sont quelque chose de tellement courant en informatique qu’on ne va pas se gaver à l’appeler “indice” à chaque fois.

Le second est dans le cadre scientifique. On a souvent des variables pour un algo, des coordonnées, des valeurs géométriques ou mathématiques, qui n’ont pas de dénomination. Dans ce cas, inutile d’essayer d’inventer une nomenclature tordue. Exemple typique, l’algo pour pondre un MD5. Mais il faut compenser par des commentaires, sinon on s’y perd.

Il ne faut pas avoir peur des noms longs. Si, j’ai un jeu de données, que je filtre plusieurs fois, il est de bon ton de distinguer les différents jeux avec des noms détaillés :

sample = range(10)
squares = [x * x for x in sample]
even_squares = [x for x in squares if x % 2 == 0]
even_squares_tail = even_squares[-3:]

Faire des noms de plus de 10 caractères n’est pas sale. On est pas sur un tableau des scores d’une borne d’arcade des années 80.

J’utilise bien entendu des noms en anglais, ce qui est toujours préférable, mais si vous devez en mettre en fr, évitez à tout prix les accents malgré la possibilité de les utiliser en Python 3.

Conventions

Il existe quelques noms qui sont toujours utilisés de la même façon en Python.

self et cls sont les plus connus, en j’en parle déjà dans le dossier sur la POO.

Il y a args et kwargs, qu’on utilise avec l’opérateur splat, dont je parle ici.

Et puis il y en a de plus discrets.

_ est utilisé pour une variable qu’on ignore. Certaines opérations, comme l’unpacking, supposent la création de plusieurs variables. Si on n’est pas intéressé par l’une d’elles, on peut le signaler. Par exemple, l’ORM django permet d’obtenir un objet, et si il n’existe pas, de le créer. Cette fonction retourne un tuble (objet, bool), l’élément indiquant si l’objet a été créé ou non. Si cette information nous intéresse :

user, created = User.objects.get_or_create(username="sam")

Si cette information ne nous intéresse pas :

user, _ = User.objects.get_or_create(username="sam")

Ainsi le lecteur saura qu’il peut ignorer cette variable quand il parcourt le code.

Il y a aussi les alias. On ne peut pas utiliser certains noms comme list ou id qui sont des fonctions existantes en Python.

On s’arrange généralement en trouvant un synonyme, mais si ce n’est pas pratique, on change une lettre. list devient lst (rappelez vous que list est un nom déjà assez pourri, nommez plutôt le contenu), class devient klass, dict devient dct, etc.

Si on ne peut pas le faire, la convention est de rajouter un underscore à la fin du nom : id devient id_, max devient max_… Mais faites l’effort, avant, de chercher un synonyme. Je vois trop souvent des from_/to alors que certains contextes permettent parfaitement de les nommer start/end ou source/destination.

A ne pas confondre avec l’underscore AVANT le nom, qui est une convention pour dire qu’une variable ne fait pas partie de l’API publique.

Ce sont des béquilles, le choix d’un nom judicieux et clair est toujours préférable, mais ce sont des béquilles utiles.

Savoir quand nommer

Au delà de donner un bon nom, il y a le fait de choisir quand il faut nommer, et quand il faut éviter de le faire.

Si seul le résultat final d’un traitement m’intéresse, alors, il vaut mieux utiliser une seule variable et mettre le nouveau résultat dedans à chaque fois :

fstab = [line.strip() for line in open('/etc/fstab') if line]
fstab = [line.lower() for line in fstab if not line.startswith('#')]
fstab = [line.split()[:3] for line in fstab]

il faut aussi savoir quand ne pas du tout créer une variable :

row = line.strip().split()
for col in row:
    # do something

ici, la variable intermédiaire est inutile :

for col in line.strip().split():
    # do something

L’inverse est aussi vrai :

for col in [int(x) for x in line.strip().split()]:
    # do something

La ligne devient beaucoup trop complexe, et ajouter une variable intermédiaire avec un bon nom va améliorer la lisibilité du programme :

numeric_col = [int(x) for x in line.strip().split()]
for col in numeric_col:
    # do something

On pourrait croire que je précise le type ici en utilisant “numeric”, mais je n’ai pas utilisé integer ou float. J’ai précisé la nature : des colonnes numériques. Il se trouve que pour des données aussi brutes, la nature se rapproche du type.

Si vous êtes du genre à utiliser des lambdas, cela s’applique aussi à vous.

Pour quelque chose de simple, une lambda inline est très lisible :

sorted(scores.items(), key=lambda score: score[1])

Mais pour quelque chose de complexe, une fonction complète est bien plus adaptée :

def calculate_rank(score):
    return sum(goals for sort, goal in score[1] if sort == 'A')
 
sorted(scores.items(), key=calculate_rank)

Plutôt qu’un horrible :

sorted(scores.items(), key=lambda x: sum(g for s, g in x[1] if s == 'A'))

Pourquoi je parle de lambda alors qu’on est sur du nommage ? Parce qu’une lambda est anonyme, alors qu’une fonction normale a un nom. Et ce nom exprime l’action de la fonction. Il documente.

Habitudes stylistiques

Ces règles là ne sont pas officielles, mais j’ai pu les constater dans nombre de bons codes.

La nom d’une fonction/méthode est aussi important, sinon plus, que le nom d’une variable. Il n’est pas rare que j’écrive des fonctions avec des noms bien dodus comme :

def get_last_downloaded_shemale_vids()

Si on oublie la docstring, on a déjà une bonne idée de ce que cette fonction fait. Cela n’empêche pas de docstringuer quand même pour annoncer des subtilités sur les types, les potentiels side effects, des choses à savoir sur le temps d’exécution, le format, les perfs, etc.

Mais il arrive souvent qu’une fonction ne fasse pas quelque chose d’aussi concret. Prenez par exemple une fonction dont le but est de sluggifier les strings d’une list.

Si la fonction transforme la liste, on va utiliser un verbe dans le nom :

slugify_items(data)

Si par contre la fonction retourne une liste avec les éléments modifiés, on va utiliser le participe passé :

data = slugified_items(data)

C’est subtil, mais la sémantique est différente. Dans le premier cas, on s’attend à un effet de bord. Dans le second cas, on s’attend à une nouvelle liste, ou comme souvent en Python, à un générateur.

Quand on a affaire à une méthode en Python, on utilise rarement le préfixe get_. Personnellement je l’utilise parfois pour des actions complexes, ou des méthodes de classe.

Mais généralement, on préférera utiliser directement le nom de ce qu’on veut récupérer. Exemple :

comments = blog_post.get_comments(spam=False) # NON
comments = blog_post.comments(spam=False) # Oui

Si on n’a pas besoin de passer de paramètre, alors une property est plus appropriée :

comments = blog_post.comments # Ouiiiiiiiiiiiiiii

J’en profite pour faire remarquer qu’il est très classe de prononcer plusieurs fois très vite “sans paramètre, une propriété est plus appropriée”.

Enfin, il arrive qu’on ait besoin de spécifier des rôles techniques et des interactions entre plusieurs bouts de code : hiérarchie, composition, dépendances, etc. Ce sont les choses les plus compliquées à comprendre quand on lit du code : voir le tableau au complet, ce qui lie les différents blocs.

Il ne faut pas hésiter à nommer ses éléments pour cela. Apprendre le nom des design patterns aide beaucoup, mais même si on n’est pas top moumoute niveau vocabulaire, on peut faire des choses aussi simple que :

class BaseAuthenticator(object):
    #...
 
class PwdAuthenticator(BaseAuthenticator):
    #...
 
class KeyAuthenticator(BaseAuthenticator):
    #...

Si vous lisez BaseAuthentificator, vous n’avez pas besoin de voir qu’elle est parente d’autres classes plus bas pour savoir que ce n’est probablement pas une classe instanciable, mais sans doute une classe interface ou une classe abstraite. De quoi se faciliter une lecture en diagonale.

FAIL

Voici quelques exemples de noms qui ratent complètement l’objectif de documentation :

 
def do_query_database():
    # ...
 
def query_database():
    # ...
    do_query_database()
    # ...

J’en croise dans le code source de Django, et ça me fait hurler. Sérieux ça veut dire quoi ? Qu’est-ce qui a été extrait ? Dans quel but ? On a plus de question APRÈS avoir lu le nom qu’avant, c’est encore pire qu’un mauvais nom, c’est un nom méchant.

Dans ce cas, il faut essayer d’expliquer au maximum ce que l’appendice – qui va me faire choper une péritonite – que vous avez mis de côté fait :

 
def excute_and_send_query():
    # ...
 
def query_database():
    # ...
    excute_and_send_query()
    # ...

Un truc également exaspérant, c’est l’usage d’un vocabulaire ambigu :

def make_best_player_list():
    # ...

On sait ce que ça fait, ça fabrique une liste des meilleurs joueurs. Le contexte nous permet d’évaluer le résultat le plus probable. Maintenant un cas beaucoup moins clair :

def make_query():
    # ...

Ca envoie la requête, ça construit la requête ou les deux ? Make est un mot qui peut vouloir dire fabriquer ou exécuter. Ici il vaut mieux utiliser un vocabulaire plus explicite comme :

def build_sql_query():
    # ...

ou

def send_db_query():
    # ...

Là on sait qui fait quoi. Quitte à faire :

def db_query():
    build_sql_query()
    send_db_query()

Et oui, diviser le travail en plusieurs sous unités bien nommées, puis les regrouper dans un bloc plus général est aussi une forme de documentation. Créer des fonctions n’est pas qu’une question de maintenance ou de perf.

Savoir bien nommer les choses vient avec de l’entraînement. Au début, il faut prendre le temps de le faire. Il faut s’arrêter, et se mettre à la place d’un autre dev qui n’a pas encore eu son café.

Allez, détendez-vous, ce blog est plein de code qui ne suit pas les conseils de cet article. Faites juste au mieux ok ?

Restauration des fonctionnalités

mercredi 8 octobre 2014 à 14:52

Après les iframes et la coloration syntaxique, le formulaire de contact, le flux rss des tweets et le planet Python fr sont de nouveau opérationnels.

Ça me fait penser que si vous connaissez des blogs fr sur Python, proposez les pour le planet.

Error happened! 0 - count(): Argument #1 ($value) must be of type Countable|array, null given In: /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php:428 http://ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/?89 #0 /var/www/ecirtam.net/autoblogs/autoblogs/autoblog.php(999): VroumVroum_Blog->update() #1 /var/www/ecirtam.net/autoblogs/autoblogs/sametmaxcom_a844ada43a979e3b1395ab9acb6afafb84340999/index.php(1): require_once('...') #2 {main}