BodySplash.fr

Aller au contenu | Aller au menu | Aller à la recherche

vendredi 17 septembre 2010

Frameworks productifs

J'aimerai ici faire un billet pour faire une petite mise au point. Les frameworks "productifs" type RoR, Grails, Play! et j'en passe ont clairement le vent en poupe. L'idée au combien louable, est bien sûr d'automatiser au maximum les tâches rébarbatives du développeur lorsqu'il s'attaque à une application web. J'imagine que toute cette mouvance a pu naître d'un écoeurement bien naturel vis à vis des piles ou frameworks plus anciens, comme Struts, toute la pile JEE et même ASP.NET avec ses bons vieux WebForm.

Ce qui me chagrine dans l'histoire, c'est que philosophiquement, je suis de tout coeur derrière ces idées de simplifications : je n'ai jamais pu encadrer le xml au kilomètre de Spring à l'époque, les Web Form me faisaient faire des cauchemars tant leur opacité était grande et je n'ai jamais été pour une multiplication des couches sans une grande nécessité.

Ceci dit, ne jetons pas le bébé avec l'eau du bain. Je m'explique. Pour paraphraser Eric Evans dans DDD, la complexité d'une application réside dans le métier qu'elle tente de représenter. Comment cela se traduit? Pour moi, cela veut dire que quelque soit les frameworks que j'utilise, ils ne devront jamais entamer ma capacité à modéliser le métier. Le succès, la richesse et l'efficacité de mon application dépendent essentiellement de ma capacité à capter la subtilité du métier. Comment mettre le maximum de chance de mon côté? En développant le modèle en isolation de tout autre considération, à l'aide d'une approche objet, d'un bon framework de tests unitaires et de bons outils de refactoring. La présentation, la persistence, le cache, tout le reste est superflu et doit le moins possible, voir pas du tout, impacter mon domaine.

Bref, après autant de blabla, voilà donc enfin ce qui me chagrine dans ce que j'ai pu voir des quelques frameworks productifs que j'ai essayé : ils sont invasifs. Le choix d'Active Record pour la persistance est une friction dans le développement du métier, car la persistance n'est alors plus transparente. Pour respecter le principe de responsabilité unique, vu que les "entités" gèrent la persistance, nous devons développer les véritables objets métier à part, et ils doivent agréger alors ces entités. Cela implique une complexification non négligeable du développement du domaine. Du coup, beaucoup des exemples que j'ai pu observer se contentent de montrer une application CRUD, avec un métier anémique contenu dans les contrôleurs, mais aucune application n'est réellement du CRUD au final.

La véritable productivité est liée à la maintenabilité, et la maintenabilité est très liée à l'isolation du métier (et aux tests bien sûr :) ). Oui du coup, avec cette philosophie en tête sur Tiron, nous n'avons pas choisi un de ces beaux frameworks à la mode, et nous avons du construire notre propre pile (jQuery/Restlet/Freemarker/Hibernate pour les curieux), et je pense que notre productivité actuelle en considérant la complexité du métier que nous devons gérer n'a pas à pâlir face à la concurrence.

P.S : je ne suis pas un expert de ces frameworks je l'avoue. Si quelqu'un peut me démontrer le contraire de ce que j'avance, j'en serai très heureux.

mercredi 24 juin 2009

Structure et frameworks

Voilà un titre bien obscure. Alors de quoi allons parler aujourd'hui? De la manière la plus simple que je vois actuellement de commencer une application web en java. Il y a quelques semaines effectivement un ami me demandait finalement quoi utiliser pour démarrer un projet de 0 e, avec comme postulat de base que finalement, tout était bien compliqué. Je vais donc décrire ici mes environnements/outils/frameworks favoris qui à mon sens, permettent de s'en sortir dans la grand majorité des cas, et tout en fournissant une base à la fois solide et extensible.

L'environnement

Avant même de commencer à développer, mieux vaut savoir comment nous allons développer. Je pense maintenant qu'il y a une base indispensable à tout projet avant même de penser conception et développement.

Build

Avec quoi construire notre appli? Ca a l'air bête comme question, mais ce n'est en fait pas si simple dans le monde de java, ou tout n'est pas aussi intégré et monolithique que dans le monde .NET.

Par défaut, à peu prêt tout le monde utilisait Ant. Personnellement, je n'en peux plus: xml au kilomètre, dépendances gérées à la main, pas user friendly, bref, une horreur à mes yeux. Si vous lisez de temps en temps ce blog, vous devez vous douter que je vais proposer Maven. Avec maven, il va être possible en 2 lignes de xml d'avoir un projet entièrement compilé, testé, packagé. Les dépendances sont téléchargées depuis un entrepôt central, et il les gère en cascade, donc on ne passe plus des heures à linker ou mettre à jour les libs externes, c'est géré. Si on suit ses conventions, c'est bien simple maven permet de faire oublier une grande partie des tâches techniques de base d'un projet.

Une question qui peut venir et savoir comment organiser son projet dans maven: Multi module ou mono module? l'avantage du multi module est qu'il va garantir une séparation entre les couches, là ou le mono module si on ne fait pas attention peut entraîner un certain mélange. Ceci dit, la complexité du multi module au début ne compense pas ce risque hypothétique, et mieux vaut de toute manière enseigner qu'interdire. Donc, jusqu'à le projet atteigne une complexité trop importante, je préfère la simplicité du mono module tout en faisant attention à ne pas mélanger les couches.

SCM

Même si vous êtes seuls, il vous faut quelque chose pour conserver et versionner votre source, ne serait-ce que par sécurité et pour avoir la possibilité de revenir en arrière. Git a beau être une star montant, je ne le connais pas, et je vais donc me contenter de conseiller subversion: simple, efficace, et non intrusif (pas de lock par défaut sur les fichiers).

IDE

Certains puristes vont certainement dire qu'un éditeur de texte suffit pour développer, mais à mon avis, on est loin d'une productivité optimale. Voilà à mes yeux ce que doit ABSOLUMENT faire un IDE:

  • intégrer les test unitaires : pouvoir les lancer facilement, et naviguer rapidement dans le code incriminé par un test rouge,
  • refactoring : c'est à mon sens l'outil ultime de productivité et de qualité. Sans aides au refacto il est trop facile, par manque de courage ou de temps, de ne pas faire des changements pour clarifier le code. Pourquoi renommer une classe si ça nous prend 10mn de faire le tour de l'appli pour trouver ceux qui l'utilise? Pourquoi extraire une super classe et centraliser du comportement si c'est un long travail fastidieux de copier/coller? Voilà pourquoi je pense qu'il est juste indispensable qu'un IDE intègre un certain nombre de refactorings assistés
  • auto-complétion, coloration, indentation: c'est la base, mais il est bon de le rappeler
  • navigation rapide dans le code: il doit être possible d'ouvrir rapidement des types ou des fichiers, mais aussi depuis une classe par exemple d'aller directement dans le code d'un objet qu'elle inclue.

Il y aurait être d'autres choses à ajouter, mais c'est déjà pas mal. Les trois IDE les plus connus du monde java (Eclipse, NetBeans, Intellij Idea) assurent tous ces fonctionnalités en plus d'une intégration à Maven indispensable dans notre cas. Je ne vais pas rentrer dans des débats religieux sur lequel est le mieux, mais personnellement j'utilise Eclipse.

Intégration continue

Je pense que l'intégration continue doit être en place dans le premier jour du projet, il ne faut pas attendre de commencer à avoir des soucis pour la mettre en place. Le minimum est bien sur de compiler l'application et de faire tourner les tests.

Il existe maintenant pas mal de solutions gratuites, mais je dois avouer ma nette préférence pour Hudson, grâce à son esprit "on déploie et ça marche". C'est très simple à mettre en place, il marche très bien avec Maven, et il peut être étendu à souhait avec pas mal de plugins. Que demander de plus?

Les technos

Bien, nous avons la base pour commencer à développer, c'est bien, mais ça ne nous dit pas quels frameworks utiliser pour bâtir notre application web. Au risque de spoiler un petit peu, je vous annonce tout de suite que je ne vais pas conseiller JEE, même en version "simple" en n'utilisant que servlet/jsp.

Restlet

Voici un framework qui mériterait un billet à part entière, mais je vais essayer de faire un résumé. Le but de restlet est de servir de base pour produire et consommer des ressources conformément à l'approche Rest. Ce qui est bien avec ça, c'est que l'on peut commencer très simplement, en faisant une application "à l'ancienne" avec des pages html entièrement générées côté serveur, puis commencer à si on veut à faire plus du RIA, avec GWT, Flex, Dojo, peu importe, les ressources restent les mêmes, on négocie juste une représentation différente.

Comme je le disais, Restlet est très simple à mettre en place, pas besoin de conteneur de Servlet ou autre, il peut démarrer son propre serveur web en une seule ligne de code. Les ressources et la configuration se fait également entièrement dans le code, avec quelques recours très discret aux annotations. Bref, Restlet est une base idéale pour toute application web: il est multi-paradigme, peut grossir en même temps que votre application sans vous forcer une grande complexité dès le début, bref, je suis fan. Ah vous de choisir au début si vous voulez faire une application à l'ancienne, du GWT, du flex etc etc, Restlet supporte tout le monde de toute manière. Suivant ce que vous avez décidé, vous pouvez ensuite par exemple utiliser Freemarker ou Velocity pour générer la représentation html de vos ressource selon une approche MVC bien connue.

Hibernate

Ah voilà un choix plus discutable n'est-ce pas quand on cherche à définir les frameworks les plus simples pour démarrer n'est-ce pas? Le plus simple pourrait-on me dire, serait de directement se connecter à la base, et de faire nos requêtes. Le soucis avec cette approche, c'est que jamais elle ne sera capable de gérer correctement une grande complexité. On se retrouvera nécessairement avec du code mort, de la duplication et une très faible réutilisabilité du code. Ceci dit, il doit y avoir plus simple qu'Hibernate non pour accéder à nos données? Sûrement, mais là je vais devoir avouer que je suis complètement perverti par DDD, et je ne conçois pas de ne pas d'abord penser objet, tester, puis seulement ensuite de faire apparaître la base. Seul un mapper O/R par metadata mapping permet d'utiliser cette approche à 100% , et hibernate est la meilleure solution open source gratuite que je connaisse pour atteindre ce but. Ah mes yeux, et pour une fois, l'effort d'écrire et maintenir tout ce XML me semble complètement être compensé par la valeur: pouvoir écrire un modèle du domaine testable et indépendant de toute considération technique. Le point discutable est sans doute, dans le cadre d'une application juste CRUD, est-ce que ça vaut le coup de sortir l'artillerie lourde? Ma réponse habituelle est que je n'ai jamais connu en 7 ans d'applications qui faisaient simplement du CRUD, donc j'ai le sentiment que ce n'est pas la règle mais le cas particulier. De plus, comment savoir à l'avance que l'application ne fera QUE du CRUD quand on la commence?

Quelques remarques

Il y a bien entendu des critiques à émettre sur le choix des technologies de base, notamment sur la productivité. Il y a peu voir pas du tout de travail prémaché dans ce que j'ai proposé, pas de composants déjà utilisables rapidement, ou de scripts pour générer rapidement les "échafaudages", sans doute parce que je ne suis fan d'aucunes des technologies proposant ces options, car trop de choix me déplaisent dedans (Ruby on Rails et Grails sont très contraignants sur pas mal de points, tant ils font de choix pour nous, Wicket, JSF and co sont orientés composants et modèle par page et ne tirent pas partie à mon avis des avantages du web; Spring MVC est déjà plus sympa, surtout en version 3, mais c'est déjà beaucoup plus lourd que Restlet...)

jeudi 18 juin 2009

Ruby

Voilà quelques temps que je m'intéresse à la nouvelle star montante des langages de programmation : Ruby.

Etant donné que je ne suis pas du tout encore un expert sur le sujet, je ne vais pas m'éterniser, mais laissez moi partager quelques remarques avec vous. La communauté Ruby se vante, souvent à juste titre, d'utiliser un langage très expressif, piloté par les bonnes pratiques de développement. Cependant, je n'ai pu m'empêcher de noter quelques éléments qui, je trouve, contredisent cette affirmation.

Le premier constat vient tout simplement des méthodes de conversion, les classiques toString, toInt etc etc que nous pourrions trouver dans d'autres langages. Plutôt que d'utiliser des noms complets, en ruby nous allons trouver des to_s, to_a, to_i. Pour un langage qui se veut expressif, je trouve ça excessivement choquant d'utiliser des acronymes pas nécessairement évident.

Deuxième constat, saviez vous qu'il existe une différence entre les méthodes eql? et equal? L'un compare sur le type et valeur, et l'autre sur la référence. Différencier ces deux comportements juste par une convention de nommage très bancale me semble juste aberrant. Un débutant ne peut juste pas faire la différence, et même les plus expérimentés peuvent facilement se laisser tromper. Ruby se vante également d'être entièrement orienté objet, contrairement par exemple à Java ou C# qui font tout deux la différence entre des types primitifs et les types références. Cependant, les libs globalement fournies avec Ruby sont tout simplement noyautées de méthodes statiques. Pourquoi se venter d'être Full OO si c'est pour s'appuyer aussi lourdement sur une approche procédurale?

Enfin, dernière remarque, Ruby ne supporte pas la surcharge de méthode: le nom d'une méthode doit être unique dans une classe. Du coup, si on veut utiliser la surcharge, qui est tout de même très pratique, on doit accepter en fait un nombre variant de paramètres, et à nous de tester tous les cas d'appels que l'on veut gérer. La complexité cyclomatique générée par cette approche est juste énorme. La liste pourrait s'allonger encore, tant finalement le langage est l'interpréteur sont bourrés de "petits trucs" qui sont juste impossible à deviner et peuvent briser votre programme si vous ne les connaissez pas. Par exemple, j'utilisez un "gets" pour lire une entrée en mode console, et quand je me suis à passer un paramètre à la commande, ça ne fonctionnait plus. Le côté souvent "magique" de certaines parties de ruby brisent à mon sens le principe de moindre surprise, et le gets en est un bon exemple.

J'essaye de faire la part des choses bien entendu, et je n'ai essayé ici de citer ici que ce qui me semble être de vrais soucis, et non pas des habitudes provenant d'autres langages. Un langage qui vaut la peine d'être appris doit changer note manière de penser, et Ruby m'a effectivement apporté beaucoup, et je l'apprécie. Ceci dit, après un tel buzz, je ne peux pas m'empêcher d'être déçu par ces détails qui sont mines de rien, pas si insignifiants que ça.