lundi 6 mai 2013

Play Framework : pourquoi j'ai migré de V2 à V1

Introduction

Utilisateur mordu de Play Framework, il y a plusieurs mois, j'ai migré mon projet en cours de V2 à ..... V1 ! L'information a un peu circulé, j'ai pu en parler ici ou là, et on m'a souvent demandé de partager mes raisons, ce que je vais faire dans ce post. 

Avec le temps, j'ai un peu oublié toutes les raisons qui m'ont poussé à cette migration, je m'en excuse par avance, mais les principales sont là !


La découverte

Courant 2010, je découvre Play Framework 1.x (dans ses premières versions). Je fais quelques essais "Hello world !", c'est vraiment nouveau, ça semble cool, c'est magique !

A la base, Play est conçu par les développeurs pour les développeurs, avec une volonté de faire plus simple que les usines à gaz JEE ou Spring, avec lesquels, finalement, on assemble toujours à peu près les mêmes briques, et ça nous prend un temps fou.

Facile à télécharger et à installer, Play permet tout de suite de créer le squelette du projet ("play new myapp") et de lancer le serveur play ("play run") pour avoir déjà une page d'accueil. La suite est un régal notamment grâce à quelques points forts :

  • La présence par défaut de toutes les briques nécessaires : connexion base de donnée, mapping, rendu HTML, modèle MVC, ...
  • Une gestion des erreurs bien travaillée qui indique clairement dans la page HTML l'origine du problème
  • Une recompilation à la volée et rapide qui permet de voir immédiatement le résultat d'une modification simplement en sauvegardant le fichier et rafraîchissant la page WEB
  • Plein de modules disponibles pour étendre les fonctionnalités de Play, et notamment 2 modules essentiels : "secure" pour la sécurisation d'accès aux page, et "crud" pour avoir une génération automatique de pages d'administration des données
  • Déploiement facile sous forme de WAR
  • Un site très didactique et une document très bien faite; et pleine d'exemples de code
  • etc .... (j'en oublie certainement qui sont devenus évident pour moi)

Bref, un gros coup de coeur que j'ai ainsi résumé à l'époque : simplicité, rapidité, productivité ! L'application est toujours utilisée et maintenue sous Play V 1.2.5.

Première véritable application

Eté 2010, je démarre un nouveau projet perso, application SaaS WEB, donc je pars sur Play. Et là, bonne surprise, le framework n'est pas cool que dans une phase de découverte "Hello world", il l'est également sur un véritable projet. La productivité est vraiment impressionnante, j'arrive à faire pas mal de choses (simples) en quelques heures.

Au final, je passe plus de temps sur la partie IHM et JavaScript, d'autant plus que Play me facilite la partie serveur.

Je déploie mon application en 1 clic sous forme de WAR sur une plateforme PaaS gratuite.

Nouveau projet

Début 2012, je décroche un contrat pour développer une application SaaS pour un client final. Play V2 est sorti depuis quelques temps, et on en parle beaucoup. Je sais qu'il n'y pas compatibilité entre les 2 versions, mais pour un nouveau projet, ça n'est pas gênant. Et je me dis que les gars qui avaient fait Play1 avait fait un truc tellement génial, que Play2 ne peut être que mieux, puisqu'ils auront tiré de l'expérience Play1 tout ce qui pourrait permettre de faire un truc encore mieux ! 

Je décide donc de partir sur Play2 en développant mes contrôleurs en Java, je n'ai pas la possibilité de me lancer dans Scala (pour l'instant). J'ai commencé par la V 2.0.1, puis 2.0.2 et enfin 2.0.3.

Les débuts se passent bien,  l'adaptation à la V2 est sans problème, je retrouve mes petits et mes habitudes : la structure MVC, le style de développement, les fichiers de configuration, de messages, etc ...

Et l'utilisation de Scala dans les templates de vues n'est pas un problème, malgré une légère complexité supplémentaire dans les déclarations et la syntaxe.

Le désenchantement

Mais petit à petit, divers problèmes sont apparus me faisant perdre de plus en plus de temps. Je vais en passer en revue quelques uns dans le désordre.

Mapping base de données

Le stockage de données ne se fait plus par Hibernate mais par Ebean. Ça n'est pas un problème, surtout que les entités sont annotés avec JPA. En fait, j'ai eu des difficultés avec des mapping un peu plus complexe, et j'ai surtout perdu du temps avec le système de scripts d'évolution du schéma de la base : ce système est puissant mais m'était totalement inconnu. Pour ce point, c'est plus mon manque de compétences qui m'a gêné mais la documentation du framework n'était pas au RDV, et la V2 étant relativement nouvelle, les forums donnaient plutôt des solutions pour la V1, d'où pas mal de confusion et de galères.

Et en fait, la V2 fonctionne par défaut avec Ebean, mais on peut faire de l'Hibernate. Et sans m'en rendre compte, et par manque de documentation, je me suis retrouvé à plusieurs reprises avec un mélange des deux apportant encore plus de difficultés !

Lenteurs

Dès le début, j'avais noté que le serveur V2 était plus long à se lancer. Mais là où ça devenait pénalisant, c'était pour la recompilation à la volée qui prenait beaucoup plus de temps qu'avec la V1 : un changement dans une vue et dans un contrôleur, sauvegarde des fichiers, rafraichissement de la page et ..... une attente bien longue ... Combien ? Je ne sais plus exactement, mais peut-être parfois près d'1 minute. OK, c'est moins long que la relance d'un serveur Spring ou JEE, mais par rapport à mes habitudes avec la V1 où une telle opération prenait environ 5", la productivité n'était plus du tout la même !

Documentation

Depuis la sortie de la V2, le site avait été refait, je le trouvais plutôt sympa. Mais à l'usage, surtout pour trouver de la documentation, ça n'est plus la même histoire ... OK, la V2 supporte Java et Scala pour les contrôleurs, donc la documentation à produire et maintenir est double, mais la V2 apportait pas mal de nouveautés qui étaient très peu documentées, souvent juste quelque lignes et un tout petit exemple de code. J'ai vraiment galéré sur certains points (cf Ebean précédemment), et les forums et mailing-list n'étaient pas d'un grand secours (ils le sont beaucoup plus maintenant, d'ailleurs il est plus difficile de trouver maintenant des infos sur la V1 ....).

Modules

Contrairement à la V1, la V2 est sortie avec peu de modules disponibles, sachant qu'il n'y a pas compatibilité entre les versions pour les modules. L'équipe de développement comptait peut-être sur la communauté déjà acquise à la cause Play ? Et notamment, pas de module "CRUD" sur lequel je comptais pour faire rapidement et simplement le back-office pour mon application. OK, c'est pas bien compliqué, mais les 2h prévues pour faire ça se sont transformées en quelques jours :-(

Compilation Eclipse

J'utilise Eclipse, je l'aime bien et j'assume ! ;-)

Tout comme pour la V1, une commande "play eclipsify" permet de préparer un projet à importer facilement dans Eclipse. La grande nouveauté dans la V2 est la compilation des template de vues qui sont écrites avec un mélange de Scala et d'HTML, puis compilées. L'appel à la vue depuis le contrôleur est donc typé, ce qui limite grandement les risques d'erreurs pour le passage de paramètres entre le contrôleur et la vue.

Dans le principe, c'est une bonne chose, même si avec la V1, j'ai rarement eu de gros problèmes à cause de ce passage de paramètres contrôleur-vue. Le problème dans mon cas était que lorsque je modifiais une vue dans Eclipse, la recompilation ne se faisait pas (ou pas bien) et je me retrouvais avec du rouge de partout, notamment dans le contrôleur puisque les appels n'étaient pas bons. Et pourtant, l'application fonctionnait bien puisque le serveur Play devait certainement recompiler l'ensemble. Et parfois, après certains rafraîchissements dans Eclipse, les erreurs de compilation disparaissaient.

Au début, je me suis dit que ça n'était pas gênant et que je pourrais faire avec, mais à la longue, c'était devenu très pénalisant !

Tests unitaires

Pour moi, ce fut le gros points noir au quotidien. Je suis un inconditionnel des tests unitaires et je développe en TDD le plus possible. Ce qui veut dire, pouvoir lancer toutes les 10" le test sur lequel je travaille actuellement (voir utiliser infinitest). 

Mais je n'ai jamais réussi à configurer correctement Eclipse pour pouvoir y lancer les tests unitaires. Des fois, ça a fonctionné, mais la plupart du temps, j'étais dans une situation où il m'était impossible de lancer une classe de test. La seule solution était de lancer les tests en console, mais la commande ne permet de lancer que l'ensemble des tests, donc un certain temps d'attente à chaque fois, et les éventuelles erreurs étaient noyées dans la masse d'informations tracées, et qui plus est, les erreurs n'étaient pas retranscrites clairement, à peine le nom du test en échec sans la raison et les valeurs concernées. Donc impossible de travailler en mode TDD !

La migration  (downgrade)

Je commençais donc à me rendre à l'évidence : pour moi, la V2 était beaucoup moins bien que la V1. Mais je n'arrivais pas à y croire. Je me suis accroché pendant pas mal de temps, j'ai fait des recherches sur internet, et lancé des appels sur des mailing-list ou sur Twitter. Cela ne m'a pas vraiment apporté de solutions. Par contre, je commençais à me rendre compte que je n'étais pas le seul déçu de la V2, ce qui n'était pas pour me rassurer.

Et un jour, me rendant à l'évidence des pertes de temps que j'accumulais, et de mon manque de productivité, j'ai décidé de repasser mon projet en cours sous la V1. Les 2 versions en sont pas compatibles, mais à ma grande surprise, la migration n'a été ni longue ni très compliquée (quelques jours de boulot, très vite rentabilisés !).

J'ai alors retrouvé la simplicité et l'efficacité de la V1, le plaisir de développer (que je commençais à perdre) et une réelle productivité : aujourd'hui mon projet est sous V 1.2.5 et je ne le regrette pas !

Conclusion

Mon impression est que l'équipe qui a sorti la V2 a fait des choix techniques pour apporter de la scalabilité à Play, et peut-être certaines innovations, mais au détriment de ce qui, à mes yeux, faisait la force de Play1 : simplicité, efficacité et productivité.

Je ne développe pas des applications visant des millions d'utilisateurs, avec des calculs nécessitant de répartir les actions sur des clusters de serveur via des "agents" (la fameuse scalabilité). Par contre, je veux aller vite sur les choses simples et mettre mes efforts sur les points à valeurs ajoutées (IHM et JS).

Aujourd'hui, lorsqu'on me demande quelle version de Play je conseille, je réponds ainsi :

  • Tu veux découvrir un framework novateur et cool, et tu veux tester concrètement Scala, just for fun : prends la dernière version de Play V2
  • Tu dois développer une grosse application, visant des millions d'utilisateurs, avec des traitements lourds, probablement à répartir sur plusieurs machines : regarde du côté de la V2, c'est certainement préférable
  • Tu veux développer une application modeste ou "classique", la charge sera normale et pourra être supportée par un serveur sur le cloud, mais tu veux te faire plaisir, aller vite pour la partir serveur, aller très vite pour des pages d'administration (via CRUD) et te concentrer sur l'IHM : prends la dernière version V1 (1.2.5) et régale toi !


18 commentaires:

  1. Concernant la V2 il est possible de lancer qu'un seul test. C'est en fait du SBT standard, la documentation est ici http://www.scala-sbt.org/release/docs/Detailed-Topics/Testing.

    Tu fais "~test-only models.MyClassUnderTest" et zou...

    Nicolas

    RépondreSupprimer
    Réponses
    1. Salut,

      Merci pour l'astuce !

      Mais ça ne remplace pas le lancement dans l'IDE avec accès direct par clic au test en échec, affichage comparatif des valeurs, stacktrace si problème, etc ....

      Supprimer
    2. Tu peux tout à fait lancer tes tests unitaires directement dans Eclipse. Je le fais tous les jours. Il faut juste créer une FakeApplication, mais c'est tout à fait faisable et cette partie est plutôt bien documentée.

      http://www.playframework.com/documentation/2.1.x/JavaTest

      Supprimer
  2. Intéressant, ce qui est rassurant c'est que les points que tu remontes sont principalement liés à la jeunesse du framework : manque de doc, manque de modules, concepts pas encore familliers par rapport à la v1 etc.

    Après avoir beaucoup utilisé la v1 j'utilise la 2(.1) désormais et j'en suis vraiment content. Les choix qui ont été faits et qui ont pu me surprendre au début ont finalement du sens et le framework a gagné en cohérence/propreté je trouve.

    Je vais essayer de te donner mon ressenti par rapport à chaque point.

    - Je pense que la doc de Play2 est meilleure que celle de Play1 en 2007 donc il y a de l'espoir :D (idem pour les modules)

    - Pour Ebean, comme tu le dis on peut utiliser JPA si on préfère (il ya des exemples dans les samples apps), sinon c'est aussi très intéressant de regarder du côté d'Anorm (et Slick) qui va avec l'API Scala.

    - Pour la vitesse de compil je suis d'accord. C'est d'ailleurs le seul point que je trouve moins bon qu'avec Play1. Mais depuis Scala 2.10 (Play 2.1) ça va déjà mieux, et ça devrait encore s'améliorer... Une autre possibilité : lancer le serveur avec ~run pour activer la compil instantanée, ça fait dejà gagner du temps.

    - Pour Eclipse ça s'est pas mal amélioré récemment avec ça : http://scala-ide.org/blog/play-0.1.0-announcement.html

    - Une autre technique pour les tests, en lançant avec ~test on active une sorte d'infinitest (ils seront relancés à chaque modification de code)

    Bref ça devrait aller en s'améliorant et peut être que tu pourras repasser bientôt à Play 2 avec plaisir. En tout cas j'espère que Play 1 semble sur le point de mourrir et son fork Yalp n'a pas l'air de décoller...

    Enfin, pour les nouveautés apportées par la V2 elles ne sont pas mineures, surtout quand tu te penches, surtout sur ce qui touche à l'"asynchronisme", au push etc. Pour ça l'API Java est sympa, et l'API Scala (Iteratee) est ultra puissante.
    Le côté "tout typesafe" est appréciable aussi, ou encore les possibilités offertes autour de JSON... Comme tu le dis en conclusion il y a de quoi s'amuser.

    RépondreSupprimer
    Réponses
    1. Salut Loïc,

      Merci pour ton retour !

      Effectivement, j'ai utilisé Play2 assez tôt, dans une phase d'optimisation active, d'où certaines difficultés qui se sont estompées depuis.

      Comme je l'ai dit, le côté TypeSafe est sympa, mais dans la pratique, c'est très rarement là (entre contrôleurs et vues) que j'ai eu des problèmes ou mauvaises surprises. Et je trouve que cet aspect a un coup (compilation des vues, etc ....)

      Et l'asynchronisme est certainement très intéressant mais pas dans tous les contextes (voire : encore peu de contexte pour l'instant). J'ai le souvenir d'une équipe que j'ai accompagnée et qui est partie sur Play2 (peu de temps après moi, sinon, je leur aurai conseillé Play1). Un développeur devait faire une requête vers un Web Service et galérait avec un code Java d'environ 10 lignes alors qu'une seule suffisait dans son cas : ce code était asynchrone (inutile pour lui) et venait de la doc Play2 (pas d'autre code plus simple proposé ...)

      Par contre, c'est sûr, je le redis, pour faire du WEB avec du Scala, Play2 est excellent. Et il a probablement gagné en maturité depuis ...

      Supprimer
    2. Le côté asynchrone est vertueux car il permet de garantir les perfs et ça aide à comprendre ce qu'on fait.
      Avec Play (1 et 2) tu as un nombre de threads limités pour limiter la consommation de ressources (en play1 : nb threads = nb processors + 1 en mode PROD). Donc si tu fais appel long et bloquant à un webservice externe tu peux potentiellement bloquer les autres utilisateurs.
      Le fait que Play2 te force à le faire en asynchrone/non bloquant en poussant l'éxecution sur un pool de thread séparé évite de faire des bêtises :)

      Supprimer
  3. "Je ne sais plus exactement, mais peut-être parfois près d'1 minute. OK, c'est moins long que la relance d'un serveur Spring ou JEE"

    On appelle ça du troll, je crois. Ou alors tu bosses avec un Pentium 75.
    Sur mon projet (spring) actuel, le redémarrage du serveur, c'est 16s (c'est déjà beaucoup), et essentiellement à cause d'hibernate.

    RépondreSupprimer
    Réponses
    1. Salut Alexis,

      Merci pour ta réaction !

      Ma machine n'est pas ancestrale mais pas non plus un monstre de puissance. Mais attention, je parle bien du temps entre la demande de rafraîchissement dans mon navigateur et l'affichage du résultat à l'écran, donc pas seulement une relance d'un serveur. Pour "1 minute", j'ai dit "parfois" .... ;-) ... mais c'était souvent (trop) long, et bien plus long qu'avec Play1 c'est sûr !

      Supprimer
  4. Bien d'accord avec Alexis sans compter que tu n'es pas tjs obligé de redémarrer le serveur ou l'appli (même sans JRebel) tant que tu ne modifies pas les méthodes.
    Et même avec une grosse application un serveur JEE ça démarre sacrément vite, nous perdons plus de temps à charger notre cache qu'à lancer l'application en elle-même (mais c'est un choix d'archi que de ne pas être en mode lazy sur ce point).

    RépondreSupprimer
    Réponses
    1. Salut Emmanuel !

      Vois ma réponse à Alexis : je parle bien du temps pour avoir le résultat de ce que je viens de modifier, méthodes comprises !

      Par exemple, dans mon appli, j'ai une info-bulle en HTML renseignée avec du texte récupéré par requête Ajax. Je modifiais le code (par exemple pour ajouter des données ou modifier un peu la mise en forme) et je remettais ma souris sur l'élément : l'info-bulle apparaissait en quelques secondes avec le nouveau texte ! Assez bluffant ! Mais ça c'était avec Play1, difficile à imaginer avec Play2 ...

      Supprimer
  5. Bonjour Xavier,

    Je partage beaucoup de ta déception sur Play 2.0.

    J'ai fait divers tests de la version 2.0, 2.1
    il faut un temps d'apprentissage des vues et aussi sur la syntaxe scala.
    La documentation se complète petit à petit.

    Je reste bloquer sur un certain nombre de module qui n'existe pas en version 2,0.
    par exemple : GAE .. Search .. Morphia
    J'ai eu aussi des problèmes avec la partie base.

    Il manque un module, une extension qui permette de faire des applications hybrides, comme entre struts 1,0 et struts 2,0.

    J'ai fait un constat, avec Play 1.X, je pense les applications plus vite et mieux, et je suis plus productif (HTML, JS). J'ai du mal à revenir vers du Spring, du Hibernate, des couches et des couches.
    Je construis des applications plus simplement et je simplifie.

    @ bientôt


    RépondreSupprimer
  6. Bonjour Xavier, je passe par ici après avoir lu ta réponse au billet de Damien...

    Je ne pourrai faire de comparatif Play 1 vs 2, ne connaissant que le second ! De mon côté c'est la découverte de Scala qui m'a incité à regarder du côté Play2 et non pas un projet en clientèle: donc pour le moment aucun réel objectif d'améliorer ma productivité !

    Je suis formatté Java/Spring; et, je dois dire que Play m'a séduit par sa relative simplicité.

    Mon constat:
    - monter en compétence (seul dans son coin) sur Scala n'est des plus faciles.
    - l'intégration avec Eclipse (Scala & Play) sont insufisantes pour un travail productif:
    - côté Play, il faut tjrs lancer le serveur en dehors de l'IDE.
    - impossible de créer un projet Scala et/ou play directement depuis l'IDE
    - le parcours de l'arborescence des types parfois impossibles... c'est très pénalisant voire rageant :(
    - j'ai aussi conataté des mauvais rafraichissement dans Eclipse.
    - la 'relative' lenteur : je n'ai pas l'impression d'être plus productif avec la compilation/test à la volée qui est proposée par Play.

    Il faut espérer que l'intégration dans IntelliJ soit bien meilleure.

    Au passage: Typesafe vient de produire une appli web standalone pour le démarrage d'appli Play2. Opéreation séduction (si l'appli était fonctionnelle avec IE) mais pourquoi s'orienter dans cette direction au lieu de mettre un maximum de ressource sur l'intégration de Play dans les différents IDEs ! Je me vois mal développer une appli depuis mon navigateur...

    a+
    Philippe

    RépondreSupprimer
  7. Bonjour Xavier,

    Comme toi je suis passé par la phase de déception de l'après V1 et ce pour plusieurs raisons :
    Tout d'abords j'adorais la V1.2.4 et j'avais mes repères.
    Quand la 2 est sortie il y a eu beaucoup de confusion, nous avons décidé de migrer un projet interne en cours de 1 vers 2 et on a pas mal souffert.

    Tout d'abord je pense que la V2 n'est pas une v2 mais la V1 d'un autre framework (certes inspiré mais qui n'a rien a voir) le fait que ce soit une v2 nous rend plus exigeant quant à la maturité du projet.
    Je pense que psychologiquement le 2 est mal venu et ne tient pas ses promesses.

    La première chose que nous avons été obligé de faire sur notre projet était de repasser en hibernate car ebean ne gérait pas les relation sur les classes abstraites et on avait un modèle avec pas mal d’héritage -> frustration la v2 fait moins bien
    Cela dit il faut mettre les choses en perspective la V1.2.4 embarque une version d'hibernate buguée sur ce sujet j'avais du la patcher à la mano et entrer dans l'enfer des dépendances de play

    Bref tout cela pour dire que je comprend ta frustration j'avais le sentiment que la V2 de play était inachevée et que sa sortie était surtout due au calendrier de devoxx => conférence driven programming ?

    Enfin pour finir j'ai voulu faire un peu de js dans la V2.0 et fournir à mes contrôleurs angularJs les url des services en fonction des habilitations. Et là : grosses colère : le reverse routing n'était accessible qu'en scala pas en java : les boules ! l'impression que java est second plan et qu'il n'est là que pour drainer vers scala les dev captifs...

    Et depuis :
    Ben j'ai insisté (je suis têtu) et je doit dire qu'ils ont réussi à me mettre à scala et que je regrette pas. La V2.1 s'est vachement améliorée et j'ai trouvé mes marques

    Qu'est ce qui a le plus changé ? probablement moi
    En effet la doc reste très superficielle (bien pour débuter et donner envie mais on est vite bloqués sur des vrais sujets
    Les forums ? çà se complique entre les réponses qui ne marchent plus sur la V2.1 les changement d'api les réponses dans les deux langages...
    Pourtant çà va mieux : beaucoup grâce à scala

    Quand la doc manque : j'ai le source => c'est con mais c'est le critère actuel
    je pense que pour s'en sortir en étant un pur javaiste çà doit toujours être dur

    J'adhère vraiment à la vision du projet (çà aide pour s'investir) et je pense que c'est un mal nécessaire : il n'y a pas beaucoup de framework sur lesquels je pourrait faire ce que je fait actuellement => et clairement pas la V1

    Bref je pense que tu y reviendras, quand tes écorchures seront guéries, sans t'attendre à une V2, et là tu verras là lumière ;)

    A+

    Fred

    RépondreSupprimer
    Réponses
    1. Bonjour,
      je viens de commencer à travailler avec play framework,je veux installer le module siena et gae sans passer par la commande: play install siena car j'arrive pas

      Supprimer
  8. Bonjour Xavier,

    Ton article date du 6 mai 2013... Nous sommes bientôt un an plus tard.
    Je partage les grandes lignes de ton article.

    Nous sommes à la version 2.2.2, et peu ou pas de passerelle depuis la version 1.2.5.
    J'ai l'impression que la version 1.2.5.X retrouve une petite santé (maven vers play, des nouveaux modules).
    J'aimerai avoir ton avis actualisé.

    RépondreSupprimer
  9. Bonjour,

    Comme le commentaire précédent, pourrai-tu nous dire si tu as eu l'occasion de retravailler avec la version 2, et si oui quels en sont tes commentaires …

    Merci

    RépondreSupprimer
  10. Pour Play 2, y'a pas photos, utilisez IntelliJ ;-)

    RépondreSupprimer