apluggedinlife.com

Préambule

PHP5.3 est sorti le 30 Juin 2009 et son adoption semble commencer à progresser chez les développeurs notamment grâce à la bascule des architectures de frameworks populaires tels que Symfony ou Zend Framework. La sortie de Symfony2 qui est prévue courant mars 2011 devrait, entre autres, participer à cette transition de PHP5.2 vers PHP5.3.

Vient donc le moment pour les developpeurs de mettre à jour leurs connaissances, si ils n'ont pas anticipé ce changement. C'est aussi, peut-être, l'occasion de profiter de cette évolution pour être un peu plus curieux et s'ouvrir à une autre culture de développement.

Dans ce billet, je vais donc tenter de vous présenter Django, un framework web écrit en Python, comme alternative aux frameworks PHP les plus courant.

Pour ce faire, et dans le cadre de plusieurs fonctionnalités basiques d'une application web communautaire, je vais essayer de procéder à une petite étude comparative des frameworks suivants :

  • Django (Python),
  • Zend Framework (PHP),
  • symfony1 et Symfony2 (PHP),

N.B. : malgré une certaine connaissance de Django et de son ecosystème et donc un certain parti pris pratique pour ce framework, cette comparaison se veut objective. Elle s'appuie sur des cas d'utilisation concrets qui peuvent être transverses entre plusieurs applications. Le but étant à la fois de couvrir parfaitement l'ensemble des fonctionnalités nécessaires mais aussi d'être le plus productif possible dans l'élaboration de cette application web afin de se concentrer davantage sur des fonctionnalités à plus haute valeur ajoutée.

from PHP to Python 1

Fonctionnalités

1. La gestion de mots clés (tags)

Besoin : taguer n'importe quel type de ressources : article, commentaire, lien, vidéo, etc.

  • Django : les applications django-taggit et django-tagging permettent de taguer chaque objet présent en base de données au sein d'une seule et même table.
    Bon à savoir, en plus django-taggit s'intègre mieux à l'admin que django-tagging avec un simple champs texte.

  • Zend Framework : la fonctionnalité doit être implémentée si l'on choisit l'ORM embarqué Zend_Db.

  • Symfony : le plugin sfDoctrineActAsTaggablePlugin peut être utilisé avec un projet symfony1 et l'ORM Doctrine1.x. Ce plugin rajoute un comportement qui permet de rattacher des tags à n'importe quel objet Doctrine1. L'extension Doctrator permet, quant à elle, de rajouter un comportement similaire à chaque objet Doctrine2.

Inadéquation : sur cette fonctionnalité Zend Framework ne couvre que partiellement les besoins.

2. Recherche full-text

Besoin : effectuer une recherche sur l'ensemble du contenu et des ressources de l'application.

  • Django : l'application django-haystack supporte, entre autres, le serveur de recherche Solr, le moteur de recherche Xapian et un mode de recherche simple au sein de la base de données ;

  • Zend Framework : la fonctionnalité est à implémenter par le développeur en utilisant, par exemple, Zend_Search_Lucene;

  • Symfony : au sein d'un projet symfony1, les plugins sfSolrPlugin ou tjSolrDoctrineBehaviorPlugin permettent une interaction avec le serveur de recherche Solr ;
    Des bundles commencent peu à peu à émerger sous Symfony2 comme ZetaBundle ou SearchBundle. Cependant, ils ne semblent pas aussi complets que leurs équivalents sous symfony1 car ils n'offrent pas d'abstraction au-dessus des modèles.

Inadéquation : des solutions existent pour Zend Framework et Symfony2. Néanmoins, des développements supplémentaires semblent être à prévoir (quid de la productivité ?).

3. Gestion des utilisateurs

Besoin : offrir un système complet d'authentification (connexion, déconnexion, validation du compte utilisateur, récupération du mot de passe, etc.), de gestion de groupes d'utilisateurs et de permission.

  • Django : deux possibilités s'offrent :
  • Zend Framework : la fonctionnalité est à développer en utilisant les composants Zend_Auth et Zend_Acl.

    Zend_Auth fournit toute une API pour l'authentification avec différents adaptateurs pour se connecter à une base LDAP ou à base de données relationnelle via l'adaptateur Zend_Auth_Adapter_DbTable qui utilise l'ORM Zend_Db.

    Zend_Acl fournit des méthodes pour manipuler des permissions, avec des notions d'héritage de droits pour les utilisateurs et les groupes. Par exemple, le groupe Administrateur héritera des droits du groupe Redacteur.
    Ce composant n'a pas d'adaptateur pour récupérer les permissions au sein d'une base de données, il faudra donc le développer.

    On pourra s'inspirer des ateliers de Julien Pauli qui montre la manière de mettre en place un système basique d'authentification ;

  • Symfony : le plugin sfGuardPlugin permet d'ajouter la connexion, la déconnexion, les groupes d'utilisateurs, les permissions et une abstraction complète des sessions utilisateurs dans un projet symfony1. Néanmoins, l'inscription et la récupération du mot de passe restent à mettre en place.
    Le bundle UserBundle semble être un équivalent à sfGuardPlugin pour Symfony2. Toutefois, du fait de la constante évolution de l'API du composant Security, on note pour le moment une certaine instabilité de ce bundle.

Inadéquation : la gestion des utilisateurs avec Zend Framework impose des développements supplémentaires.

4. Interconnexion avec d'autres plateformes sociales

Besoin : se connecter via des applications tierces et pouvoir partager des liens vers celles-ci.

  • Django : l'application django-social-bookmarking permet de partager un lien sur différentes plateformes sociales avec un compteur qui donne une indication sur le nombre de clics (indice de popularité).
    L'application django-socialregistration peut être utilisée pour se connecter à un site en utilisant un système d'authentification décentralisée comme, par exemple, Facebook, Twitter (OAuth) ou OpenId ;
    L'application django-social-auth fournit également une connexion à des systèmes comme Facebook, Twitter, OpenId ainsi que Yahoo ;
    Les applications django-tellafriend et django-mailfriend permettent d'envoyer un e-mail à un tiers avec le lien d'une page spécifique du site.
    L'application django-friends propose l'importation de ses contacts provenant de Google, Yahoo ou d'une vCard.

  • Zend Framework : la fonctionnalité est à implémenter à partir des composants Zend_OAuth et Zend_OpenId. A noter qu'il existe déjà quelques articles qui détaillent la procédure à suivre ici et .

  • Symfony : les plugins sfFacebookConnectPlugin, sfTwitterAuthPlugin et sfPHPOpendIdPlugin permettent une interconnexion avec respectivement Facebook, Twitter et OpenId pour un projet symfony1.
    Pour Symfony2, le bundle FacebookBundle ajoute une couche d'authentification supplémentaire au-dessus du composant Security de Symfony2 alors que le bundle TwitterBundle ne semble permettre de manipuler l'API de twitter que via des views helpers.
    Espérons que quelques initiatives seront prises du côté du bundle UserBundle pour reprendre ces fonctionnalités.

Au cours de mes recherches, je suis tombé sur OpenInviter qui, malgré l'exploit de rassembler un site horrible et du code spaghetti, parait être un composant assez complet d'importation de contacts en PHP.
De plus, le plugin lcOpenInviterPlugin semble reprendre les fonctionnalités de OpenInviter pour les inclure dans un projet symfony1.

Au niveau du Zend Framework, les composants Zend_Services, Zend_Gdata et Zend_Vcard permettent d'exploiter les différents services pour importer des contacts, mais cela suppose un assemblement des différentes ressources exploitables.

Inadéquation : aucune, si ce n'est qu'avec Zend Framework cela nécessite un peu plus de travail.

5. Ajouter des commentaires

Besoin : commenter n'importe quel type de ressource (article, vidéo, etc.) et modérer

  • Django : l'application comments permet de rattacher un commentaire à n'importe quel objet et de les modérer.
    Les applications django-mptt-comments et django-threadedcomments offrent l'affichage de commentaire hiérarchique.

  • Zend Framework : à implémenter.

  • Symfony : le plugin sfPropelActAsCommentableBehaviorPlugin, basé sur l'ORM Propel ajoute un comportement qui permet à chaque modèle d'ajouter des commentaires. Cette relation se traduit par une liaison entre le nom de la classe de l'objet et sa clé primaire en base de données.
    Quant à l'ORM Doctrine, le plugin sfSimpleCommentPlugin attache une table d'association entre l'élément auquel on veut ajouter un commentaire et la table de commentaire.
    Il n'existe pas encore d'équivalent pour Symfony2 mais, l'ajout d'un comportement sur l'ORM Doctrine2 copié sur Taggable de Doctrator pourrait faire le travail.

Inadéquation : Zend Framework ne semble pas combler ce besoin et requiert une implémentation.

6. Gestion d'avatars

Besoin : permettre à l'utilisateur de télécharger un avatar personnel afin de l'affecter à son compte ou utiliser un système décentralisé comme Gravatar.

Inadéquation : sur cette fonctionnalité Zend Framework et Symfony ne couvrent que partiellement les besoins. Il faudra la créer dans le cas du téléchargement de son propre avatar.

Spécificités pour les développeurs

1. Intégration des tests unitaires et tests fonctionnels

Besoin : tester toute l'application afin de rajouter des fonctionnalités sans pour autant avoir peur de casser l'existant.

  • Django : intégration complète via unittests ou doctests. Les tests sont compris dans la majorité des applications. Par conséquent, la qualité de ces dernières est, dans la majorité des cas, garantie.

  • Zend Framework : intégration partielle avec PHPUnit. L'intégration est laborieuse notamment du fait d'un manque de contexte. Des ressources comme ZendCasts permettent néanmoins de se forger son propre composant.
    Je vous invite à voir, par exemple, comment Matthew Weier O'Phinney, contributeur principal au Zend Framework, s'y prend pour tester son projet pastebin.

  • Symfony : intégration complète grâce à Lime pour symfony1 mais rendue obsolète et remplacée par PHPUnit dans Symfony2.

2. Héritage dans les templates (template inheritance)

Besoin : définir un template de base que l'on va hériter comme dans un contexte de programmation orientée objet. Ainsi, on affecte à son template des blocks qui peuvent être surchargés dans les templates enfants. Grâce à cette fonctionnalité, les intégrateurs peuvent préparer plusieurs templates de base pour hiérarchiser leurs layouts.

  • Django : l'héritage de templates (template inheritance) est une des principales fonctionnalités de son moteur de template, ce qui présente un avantage certain.

  • Zend Framework : la fonctionnalité est à implémenter avec les pistes que l'on peut trouver ici et ;

  • Symfony : la fonctionnalité n'est présente qu'à partir de Symfony2 ou via le moteur de template Twig directement inspiré de Jinja2.

3. Minification automatique des fichiers statiques (CSS/JS) sur un serveur tiers dédié

Besoin : compresser des fichiers statiques afin de réduire les requêtes HTTP et diminuer le temps de chargement de la page, les télécharger à la volée sur un serveur tiers dédié à cet usage afin de ne pas surcharger le serveur web principal et offrir une réactivité plus importante côté client (performance).

  • Django : l'application django-compressor permet de compresser des fichiers statiques (JS et CSS) dans un dossier séparé qui pourra ensuite être rendu par un serveur web léger dédié à cet effet.
    L'application django-css, qui est un fork de django-compressor, permet de compresser en plus des fichiers statiques lambdas (JS et CSS), des langages alternatifs utilisant des compilateurs séparés tels que Sass, HSS ou encore clevercss.
    L'application django-mediasync permet de déployer des médias sur un CDN. Par exemple, cette application peut concaténer, minifier et gzipper sur un service de type Amazon S3.

  • Zend Framework : la fonctionnalité peut être écrite avec minify et Zend_Service_Amazon_S3 ;

  • Symfony : le plugin sfDynamicsPlugin pour symfony1 peut servir à gérer les conflits entre les fichiers statiques, à les grouper et à les mettre en cache.
    Kris Wallsmith travaille actuellement sur le bundle AsseticBundle destiné à faciliter la gestion des médias dans Symfony2. A noter que ce bundle utilise assetic qui est un portage en PHP5.3 de webassets, une librairie de traitement de fichiers statiques écrite en Python.

Courbe d'apprentissage

  • Django :
    • Points positifs : toute personne possédant la connaissance d'un framework et des bases en algorithmie est potentiellement un développeur Django en devenir. En effet, une connaissance des patterns principaux et une consultation de la documentation Django suffit pour se former très rapidement à ce framework.

      La documentation mise à disposition est très bien renseignée, très pratique (riche d'exemples) et d'autant plus assimilable dans le cadre d'une formation.

      Autre point, la communauté autour de ce framework est importante et dynamique : beaucoup d'applications réutilisables sont partagées par la communauté ;

    • Points négatifs : une courbe d'apprentissage très rapide mais qui devient plus lente pour des ouvrages plus complexes (apprentissage des fonctionnalités spécifiques à Python).

      En outre, il existe peu de développeurs avec Python en langage principal ou exclusif, davantage en langage secondaire.

      La difficulté à trouver des infrastructures disponibles pour mettre en production son application représente aussi un frein pour le débutant. Au niveau de l'hébergement, les infrastructures qui supportent Python ne sont pas aussi répandues. Néanmoins, on peut retrouver des initiatives comme webfaction et alwaysdata qui simplifient cette étape.

      D'autre part, le déploiement d'une application Python/Django peut nécessiter plus de compétences en administration système.

  • Zend Framework :
    • Points positifs : un framework développé en PHP, un langage populaire et rapidement compréhensible qui bénéficie d'une communauté de développeurs étendue. C'est un framework très modulaire, ce qui permet de se créer sa propre architecture et de la décliner.

    • Points négatifs : la documentation est pauvre, les exemples ne sont pas assez pratiques et on passe plus de temps à s'auto-former avec le code source des composants. De plus, la solution d'ORM ad hoc est insuffisante et on est obligé de se tourner vers des composants extérieurs (Doctrine, Propel, etc.) ce qui nécessite, encore une fois, une documentation autodidacte.

  • Symfony :
    • Points positifs : tout comme Zend Framework il partage les points positifs liés au langage utilisé. Le framework, bien documenté, possède beaucoup de plugins réutilisables et est simple à prendre en main.

    • Points négatifs : une courbe d'apprentissage très rapide mais on peut peut-être déplorer une dispersion des connaissances car il faut parfois fouiller sur plusieurs sites pour ne pas stagner.

Conclusion

Au regard de la comparaison des quatre frameworks par rapport aux quelques exemples de fonctionnalités décrits, un choix semble émerger.

Bien que Zend Framework 1.x et symfony 1.x soient des frameworks d'usage répandu et qu'ils bénéficient de l'appui d'une communauté conséquente de développeurs, ils ne semblent pas, dans leurs versions actuelles, couvrir totalement l'ensemble des exemples de besoins courants exprimés.

En ce qui concerne les tests unitaires, ces deux frameworks sont insuffisants. symfony 1.x embarque bien un outil de tests unitaires (Lime) mais il est obsolète et est remplacé par PHPUnit dans Symfony2. Quant à Zend Framework 1.x, son outil de tests unitaires est mal intégré et souffre d'un manque de documentation pouvant handicaper le développeur débutant dans sa progression.

Côté Zend Framework 1.x, les manques et donc les développements annexes à réaliser, sont également nombreux. Pour dépasser les limitations de son ORM par défaut, l'utilisation de ce framework nécessite, dans la majorité des cas, l'appel à une librairie externe (Doctrine 2 par exemple).

Pour finir cette étude, il est nécessaire d'aborder le sujet de la maintenabilité à long terme.
En effet, PHP 5.2.X arrive en fin de course. symfony 1.x et Zend Framework 1.x sont en train de changer totalement leur architecture. Par conséquent, commencer un projet majeur sous symfony 1.x (qui n'a pas d'interaction avec Doctrine 2 pour le moment) ou Zend Framework 1.x, peut donc s'avérer jusque là contre-productif (manque de recul).

Vous l'aurez donc compris, l'enjeu que représente l'ouverture à un ou plusieurs autres langages que PHP, notamment à Python, peut représenter un véritable gain.

S'appuyer sur des technologies en fin de course dont les migrations prochaines nous obligeront à basculer de nombreuses fois nos architectures suppose un réel effort de maintenabilité.
A partir de constat, une question se pose : allez-vous préférer vous appuyer sur des architectures mouvantes ou allez-vous faire le choix dans un premier temps de vous reposer sur des architectures pérennes qui offrent davantage de fonctionnalités ?

from PHP to Python 2

Bien entendu, si vous disposez de ressources supplémentaires concernant l'un de ces quatre frameworks, n'hésitez pas à commenter ce billet. Nous le mettrons à jour au fil des informations partagées.

Voilà, c'était un billet fleuve ! Merci à tout ceux qui ont eu le courage de nous lire et merci à letmecraft pour la relecture.

Aller plus loin

[Edit du 17/02/11]

Billet écho

blog comments powered by Disqus