Python et Django, retour d'expérience après deux ans

Un joli manège, youpla !

Il y a un poil moins de deux ans, j'écrivais ici-même un billet dans lequel j'expliquais pourquoi j'avais décidé de laisser tomber Symfony premier du nom pour voguer vers de plus vertes terres pythonesques. La bataille qui fit rage dans les commentaires ferait passer la plus épique scène du Seigneur des Anneaux pour une querelle dans un jardin d'enfants, et ce billet reste à ce jour l'un des plus vus sur Miximum. Le temps a passé, et j'ai pensé qu'il pourrait être intéressant de proposer un petit retour d'expérience sur cette migration. Alors, Python, Django, c'est bien, ou c'est très bien ?

Avertissement : j'en vois déjà parmi vous qui salivent à l'odeur d'une bonne grillade de troll. Point de ces bacchanales aujourd'hui. Mon intention n'est nullement de crâcher dédaigneusement sur mes outils d'hier, mais de décrire d'une manière subjective ces terres lointaines afin que d'autres puissent décider en conscience d'effectuer la traversée ou non. Il faut également être clair sur le fait que je n'ai pas testé Symfony 2, et que je n'ai aucune idée dont a pu évoluer le projet.

Je partirai du principe que les lecteurs du billet sont novices en Django et / ou Python. Dans le cas contraire, passez votre chemin, vous n'apprendrez pas grand chose.

Python, un langage qui a du mordant

Lorsque j'ai décidé de donner sa chance à Django, je n'avais que superficiellement testé Python. Je ne connaissais ni le langage, ni les outils, ni les bonnes pratiques en vigueur, ni l'état de la communauté.

À première vue, Python ressemble à un jouet. L'indentation qui sert à définir la structure logique du code ? Pas d'accolades dans tous les sens ? La possibilité de créer un module simplement grâce à un fichier vide à la racine d'un répertoire ? Non mais allô, quoi ?!

Et puis à l'usage, on découvre que cette simplicité apparente est la source même d'une puissance impressionnante. On parvient à écrire du code efficace tout en restant propre, concis, et facile à relire. Et puis, les conventions de codage documentées au niveau du langage même ? Les tests intégrés directement dans la structure du langage ? La console Python ? Les environnements virtuels ? Wow ! Just wow !

Python, c'est un peu un langage « pour les grands » (Qui a crié « pour les glands ! » ? Il sera fouetté avec une queue de panda roux !). Un langage qui ne cherche pas à vous cadrer à tout prix dans une structure figée. Qui ne vous force pas à définir des restrictions de portée sur chaque attribut pour que votre code ressemble à un manuel de POO. Python, c'est un langage qui vous dit « Tu es un adulte responsable, maintenant. Tu peux tout casser et faire n'importe quoi si tu en as envie, mais tu en assumera les conséquences. Tes collègues aussi sont responsables. Si ce n'est pas le cas, vous devriez d'abord en discuter entre vous. ».

Python, ce n'est pas un langage pour les universitaires puristes qui ne jurent que par les concepts théoriques de la POO, ce n'est pas un langage pour les consultants qui pensent qu'une incrémentation de variable doit se faire dans une classe, c'est un langage pour les professionnels, les vrais, les pragmatiques, ceux qui lisent et écrivent du code tous les jours pour vivre. Et j'aime ça.

Je ne suis pas sectaire. Je ne dédaigne pas écrire du Java de temps à autre, je reconnais que Javascript est plein de qualités, etc. Mais Python possède cette double qualité qu'il favorise l'écriture de code robuste et professionnel tout en étant agréable à utiliser. Client content. Freelance content. Tout le monde est content.

Python est-il parfait ? Non ! Chaque langage vient avec ses écueils. Par exemple, la bibliothèque standard qui permet d'effectuer des requêtes HTTP est pour le moins… douteuse (mais heureusement, il y a Requests). La gestion des encodages est également un point générateur de bug (ce qui a été pris en compte pour le développement de la v3 du langage). Mais ce sont les seules choses qui me viennent à l'esprit sur le moment.

Du code et des hommes

Yummy Snake 7/52

Un langage, ce n'est pas qu'une syntaxe. Il y aussi les outils, les ressources disponibles, la communauté, etc. À vrai dire, j'avais vraiment l'impression qu'elle était inexistante, cette communauté ; baignant dans l'univers PHP, j'avais l'impression que PHP était l'univers. Il n'en est rien. La communauté est bien présente, elle est dynamique, et elle est loin de coder avec les pieds. En passant de PHP à Python, j'ai eu un peu l'impression du grand collégien de 3ème qui se retrouve avec les petits lycéens de 2nde, et qui est bien obligé d'arrêter de faire son kéké.

C'est un constat que j'ai fait très rapidement : les ressources et outils disponibles dans l'univers Python sont d'une qualité globale très homogène et plutôt élevée. Dans mes souvenirs, chaque fois que je cherchais une librairie ou un composant logiciel pour un projet PHP, je pouvais tomber sur n'importe quoi, le meilleur comme le pire. C'était amusant, un peu comme une loterie (« Le million ! Le million ! HOOoooo… »). Mais pour le développeur pragmatique et pressé, c'est un peu embêtant. Je n'ai pas retrouvé cet effet avec Python. Quand j'ai besoin d'un truc, je cherches rapidos sur le ouaibe, je trouve le nom du composant qui fait ça, je tape « pip install trucmuche » et hop ! le tour est joué. Il est assez rare que je tombe sur un composant populaire qui ne soit pas testé extensivement.

Évidemment, PHP est le langage « grand public » par excellence. Globalement, sur le web, les débutants, les bidouilleurs, les incompétents (pardonnez-moi, mais il y en a) font du PHP. J'ai également l'impression (ce n'est qu'une impression) que de plus en plus de développeurs qui montent en compétences « s'échappent » vers d'autres écosystèmes. Ce qui explique l'hétérogénéité de l'existant, et la difficulté à séparer le bon grain de l'ivraie dans l'univers PHP. Cela n'enlève rien à la qualité des très bons outils qui existent.

La communauté est compétente. Ai-je dit qu'elle était sympa ? Je ne m'étendrais pas là dessus, mais je tiens juste à signaler que les rencontres Django, l'année dernière, c'était sur la plage, et on a mangé de la brasucade. Il vous faut un dessin ?

Bon, et Django, ça vaut le coup ?

[Portrait of Django Reinhardt, Aquarium, New York, N.Y., ca. Nov. 1946] (LOC)

Venons-en à Django, maintenant. Faire un comparatif point à point des deux frameworks ne m'intéresse pas, surtout que sf1.x est mort alors que Django continue à évoluer. Ça n'aurait pas beaucoup de sens. Par contre je peux vous donner mon ressenti (subjectif) d'utilisateur intensif depuis deux ans, et le constat est plutôt très positif.

Fonctionnellement, Django est très complet, et fourni (pratiquement) tous les outils qu'on attend d'un tel framework. L'orm, les (vrais) templates, la configuration des urls, la gestion des formulaires, le générateur d'admin, etc. Tout y est !

La documentation est claire, pratique, bien référencée (il n'y a pas 150 versions concurrentes dont on ne sait laquelle choisir) et très complète.

Django est un framework tout en un. Il vient avec son orm maison, son moteur de template maison, son framework de formulaires maison, etc. Chacun de ses outils est à la hauteur du reste : clair, facile à utiliser, suffisament complet pour couvrir la majorité des besoins. Toutefois, le couplage est assez fort, et il ne sera pas facile de remplacer l'un de ces éléments par un autre (mais pour ça, il y a Flask, framework Python minimaliste diablement sexy).

Au début, la façon de structurer son projet est un peu déroutante. Plutôt que de fonctionner en applications / modules, Django ne propose qu'un découpage par applications (sachant que la modularité native de Python est largement suffisante pour les besoins d'architectures plus complexes). Une app est « une application Web qui fait quelque chose — e.g. un système de blog, une base de données d'enregistrement plublics, ou un simple système de sondage ». Toutefois, la documentation manque à mon avis de clarté et d'exemples de bonnes pratiques sur la façon de structurer un projet web complexe, et sur la granularité qu'il faut viser dans son découpage architectural.

La configuration se fait directement en Python, ce qui est fort pratique, mais peut également dérouter le néophyte habitué aux fichiers de config en yaml (qui a crié « En XML ! » ? Cette fois, ça commence à bien faire !). Le concept d'environnement de production (developpement, recette, production, etc.) n'est pas directement intégré au framework, mais se gère en Python, un peu comme chacun décide de le faire.

Django est une techno pragmatique : les outils proposés sont adaptés à des cas d'utilisation réels, et ne se mettent pas en travers de votre chemin quand vous voulez les contourner. En deux ans, je ne crois pas avoir été bloqué une seule fois par un élément du framework que je n'aurais pas pu remplacer ou adapter, et qui m'aurait obligé à d'horribles copier-coller pour ne modifier qu'une petite portion du code (bon, pour être honnête, ça m'est arrivé une fois, mais ce n'était pas la mer à boire). Au final, c'est un outil qui couvrira 90% des besoins en développements web sur mesure.

Ma langue de vipère

Django n'est pas une techno parfaite, loin de là. Voici à mon avis les points qui pourraient bénéficier d'une amélioration. Il y en a sûrement d'autres, mais ce sont les écueils que j'ai rencontré.

Le gros point noir réside dans le manque de consensus sur les bonnes pratiques de déploiement en production. Déployer un projet PHP, c'est relativement facile. Tous les hébergeurs proposent du PHP, et le processus est clair : on installe mod_php, on créé un VirtualHost, et vogue la galère (oui, ok, je sais que c'est plus compliqué). En Python, pléthore de possibilités, pas de consigne claire, pas de référence documentaire unique. Au premier déploiement, le nouveau djangonaute se retrouve comme un cancre devant un tableau noir. Je sais, on peut utiliser Heroku, mais c'est de la triche.

D'ailleurs, ce n'est pas le seul élément du framework qui est laissé à la discretion de l'utilisateur (ACLs, configuration, etc.), ce qui me semble violer l'un des principes élémentaires du Zen of Python : « There should be one — and preferably only one — obvious way to do it ».

Au niveau des tests, la gestion des fixtures me parait fastidieuse et difficile à maintenir sur les projets au long terme, et l'utilisation de fixtures dynamiques nécessite la mise en place d'applications tierces.

Nativement, Django ne permet pas de concevoir des Apis réellement RESTful. La dernière fois que j'ai eu besoin d'une api REST, je me suis trouvé bloqué, il n'y avait pas de consensus sur la meilleure app à utiliser, et il était tout simplement plus simple de passer par une autre techno. Il existe maintenant des solutions, mais je n'ai pas eu l'occasion de les tester.

Django n'est pas non plus adapté pour développer des applications temps réel. Il existe bien évidemment des solutions, mais là encore je n'ai pas eu l'occasion de tester. Bon, il n'est pas vraiment pensé pour ça à la base, on ne peut donc pas vraiment lui reprocher.

Nativement, Django ne permet pas de gérer les permissions par URL (via des expressions régulières, par exemple). Il reste toutefois assez facile d'implémenter son propre système maison.

Ce sont les éléments auxquels je pense en ce moment. Des points noirs assez embêtants quand on tombe dessus, mais jamais rien d'insurmontable.

Envie de réécrire vos vieux projets Symfony ?

La conclusion de tout ça, c'est que je ne regrette pas la migration vers Python et Django. Ce sont des outils de travail qui favorisent réellement la production d'un travail de qualité, et qui restent très agréable à utiliser au quotidien. Django n'est pas un framework qui promet des montagnes, c'est simplement un outil qui fait ce qu'il dit et dit ce qu'il fait (et qui le fait plutôt bien). Ce sera un choix pertinent pour 95% des projets Web.

Si vous vous posiez encore la question de savoir que faire de vos vieilles bases de code en sf1.4, n'hésitez plus ! Passez-moi un coup de fil pour discuter d'une migration sous Django ;)