Archive
Apache Maven, 2eme édition
Cet été (si loin déjà!), Pearson m’a envoyé un exemplaire gratuit du livre Apache Maven 2 et 3, 2eme édition, grâce à la sympathique entremise d’Arnaud Héritier et Nicolas de loof.
Bien que j’ai dévoré le livre dès réception, la présente critique a été retardée par un déménagement/changement de taff. Ceci dit, mieux vaut tard que jamais, et maintenant que le contexte a été posé voyons pour une critique sans faux semblant…
Alors, que dire d’Apache Maven 2 et 3? Pour les pressés, en quelques mots: si vous sentez débutant/intermédiaire en Maven, foncez. Si vous êtes expert et cherchez à tuner votre Maven, passez votre chemin.
Pourquoi foncez? Tout simplement parce que le livre réussi à bien mettre en avant tout l’intérêt et la force de Maven, abordant les multiples domaines d’usage, sans sombrer dans le guide de référence infâme et soporifique (et supplanté par internet depuis que l’ADSL existe), le tout avec un mode narratif franchement agréable passé la surprise initiale (il s’agit en effet de Nicolas et Arnaud narrant comme telle ou telle personne ont eu tels soucis et comment cela a été résolu). Et comble du raffinement, nos deux comparses fournissent en chemin des trucs et astuces pour des problèmes "courants" qui, perso, m’ont bien servi depuis.
Certes, tout un chacun trouvera des aspects qu’il aurait souhaité voir plus approfondi, mais c’est également une des forces du livre: il pousse à aller de l’avant, tout en donnant les bases pour qu’on se sente capable de le faire. A l’inverse, il ne cache pas certains aspects encore perfectibles de Maven, tout en fournissant assez d’info pour que le lecteur ne soit pas démuni.
Je ne ferai qu’une critique négative de taille: les auteurs tentent de rassurer sur le futur de Maven, entre Sonatype et la fondation Apache. Et perso ils ont produit tout l’effet contraire. En effet, si on lit bien que les deux organisations sont faites de personnes pleines de bonne volonté, on devine également aisément que des tensions sont présentes, sans en avoir le détail, tout en voyant de façon évidente les contradictions des deux approches, entre le rythme mesuré de la fondation Apache et de ses règles et le dynamisme zélé (et intéressé) du papa de Maven et son équipe.
J’ai également ressenti un certain flou sur les produits Sonatype. Comment s’intègrent ils avec le reste? Où commence le domaine payant? Quelle stratégie est suivie par Sonatype dans tout cela?
Bref, ça manque de vision d’ensemble, à mon sens, ainsi que d’une présentation claire et sans ambages des tensions présentes (ou passées, j’en sais rien moi) histoire de poser le cadre.
Avec le recul, toutefois, cette critique s’atténue pour laisser place à la gratitude de se servir au quotidien des conseils et de l’inspiration générées par ce bouquin. Aussi, vue la période, je concluerai simplement: un parfait cadeau de Noël pour geek ou geekette!
Allez, bonne lecture à tous et encore merci à nos deux auteurs!
++
joseph
Wicket: fournir des données JSON via Ajax
[Article also available in English]
Il y a quelques semaines, nous devions retourner des données sous forme JSON suite à des appels JavaScript. N’étant pas familier avec la chose, nous étions partis sur une page ne retournant qu’un contenu JSON. Quelque chose comme ça:
@Override
protected void onRender(final MarkupStream markupStream)
{
try
{
OutputStream outputStream = getResponse().getOutputStream();
outputStream.write(jsonData.getBytes());
outputStream.flush();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
}
L’url de cette page était fournie au code JavaScript via cet appel:
RequestCycle.get().urlFor(jsonPage);
Bien évidemment, l’appel et la gestion de cette page étaient encapsulés, histoire de ne pas polluer chaque utilisateur avec ces subtilités.
Toutefois, bien que fonctionnelle, cette solution n’est pas parfaite. En effet, cette page supplémentaire implique un contexte différente où les infos doivent être amenées. Rester au sein même du composant/contexte pourrait être plus plus sympa (c’est certes toujours possible, mais bien moins propre et requérant plus de travail). Cette solution est également plutôt verbeuse.
Le bon côté de la chose est que cette page, avec peu de contenu, prend également peu de place une fois sérialisée, ce qui arrive souvent avec Wicket. Je vous l’disais, rien n’est parfait
Cependant, plus récemment, je cherchais une façon de coordonner un Behavior Ajax Wicket avec une fonction jQuery, les deux se déclenchant sur le même événement JavaScript. En chemin, j’ai trouvé cette "astuce" de Richard Wilkinson dans une conversation nommée Wicket, Ajax and JSON. Et devinez quoi: c’est tout simple de faire interagir du JavaScript et un Behavior via des données JSON (ou quelque contenu de votre choix).
Voici le code de Richard:
AbstractAjaxBehavior behaviour = new AbstractAjaxBehavior()
{
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
public void onRequest()
{
//get parameters
final RequestCycle requestCycle = RequestCycle.get();
final PageParameters pageParameters = new PageParameters(requestCycle.getRequest().getParameterMap());
//do something using nice json library to produce a string of json
String json = .......
requestCycle.setRequestTarget(new StringRequestTarget("application/json", "utf-8", json));
}
};
add(behaviour);
Pour accéder à l’url de ce Behavior, il suffit de procéder ainsi:
behaviour.getCallbackUrl(true)
Ma première implémentation tourne nickel, même si je ne suis pas sûr de toutes les implications du booléen fourni pour obtenir l’url, dont la JavaDoc est:
* @param onlyTargetActivePage
* if true the callback to this behavior will be ignore if the page is not the last
* one the user accessed
Quoiqu’il en soit, au final, l’essentiel est dans la facilité avec laquelle tout cela est faisable. Finies la page et les lignes de code supplémentaires, ainsi que de passer des infos à travers tout ce petit monde. Ce Behavior résout tout cela joliment.
Bien sûr, l’intégration de JavaScript avec le côté serveur est toujours un travail conséquent, mais au moins Wicket fournit vraiment des outils efficaces pour cela !
++
joseph
PS: dans sa réponse, Richard parle également de l’intégration de jQuery dans Wicket, via le projet anciennement nommé wiQuery et récemment intégré dans wicketstuff-core en tant que "jquery" project. Quelqu’un l’a t il déjà utilisé ? Des retours d’expérience ?
PS2: Plus d’info sur Richard sur son blog Out for a duck, all about Wicket, sans nouvelle entrée depuis quelque temps malheureusement.
Camel case: comment gérer les acronymes et abréviations en majuscules ?
[Article also available in English.]
Rapide article à propos d’un sujet qui s’est présenté plusieurs fois dans l’équipe: les acronymes doivent ils rester en majuscules lorsqu’ils font partie d’un nom en camel case ? Autrement dit, faut il écrire XMLFileName ou XmlFileName ?
Pareillement, que faire des abréviations? Si un composant concerne le Front Office, et que ce même Front Office est souvent référé en tant que FO (ou Fo), ce composant doit il être nommé FoFileName ou FOFileName ? Et un autre SomeDataFODisplay ou SomeDataFoDisplay ?
Bon, je l’avoue, ça parait un peu inutile comme discussion. On développe des logiciels, le choix des noms n’est pas forcément le plus critique. Ceci dit, avec Eclipse et son auto complétion prenant en compte le camel case, comme le dialogue d’ouverture de type, il est requis de savoir quelle est la convention retenue. Aussi, il suffit de se mettre d’accord au niveau de l’équipe et, à priori, basta.
Ceci dit, nous ne nous sommes pas penchés pleinement sur le sujet, vu qu’il est limite accessoire, et la solution retenue, frisant l’arbitraire, n’a convaincu personne. Aussi, je me suis dit que je devrai creuser un poil le sujet
Aussi, armé d’un redoutable éditeur de code, voici ce que je constate:
- tout garder en majuscules:
+ colle au plus près des acronymes. C’est XML et pas xml après tout.
- devient illisible quand des acronymes sont combinés. FOXMLRMIConfig est plutôt confus par exemple.
- inapproprié pour les noms de variables. Comment gérer le commun "private Foo foo" ? Aller pour "private FOXMLData FOXMLData" ? Arg. "private FOXMLData fOXMLData" ? Encore pire ! "private FOXMLData foXMLData" ? Un peu mieux, mais toujours pas génial AMHA. - ne garder que la première lettre en majuscule:
+ les noms de variables deviennent naturels. "private FoXmlData foXmlData" a tout simplement l’air comme il devrait être.
+ Peut être combiné à volonté. FoXmlRmiConfig est lisible.
- étrange au premier regard. Comme dit plus haut, c’est HTML et PDF, pas Html et Pdf !
Aussi, il semblerait que ne garder que la première lettre en majuscule soit la bonne solution.
Vu que je ne voulais pas ignorer l’état de l’art, j’ai essayé de trouver des recommandations officielles sur le sujet. Ma pêche a été maigre, seul Microsoft en fourni sur le sujet, à la page Capitalization Conventions, dans le paragraphe "Capitalization Rules for Acronyms".
En quelque mots, le contenu peut être traduit et résumé à:
- Abréviations:
ne pas en utiliser sauf pour ID et OK, qui "dans des identifiant Pascal-cased devraient apparaitre en tant que Id et Ok. Utilisés en tant que premier mot d’un identifiant camel case, ils devraient apparaitre en tant que id et ok." - Acronymes:
- si longs de 2 caractères: les laisser en majuscules, "excepté pour le premier mot d’un identifiant camel case". Ce qui veut dire d’écrire "private IOFile ioFile".
- si plus de 2 caractères, ne garder que la première lettre en majuscule, excepté pour le premier mot d’un identifiant camel case. Ce qui revient à "private XmlFile xmlFile".
Cette règle des 2 caractères m’a pas mal surpris en fait. Cela peut sans doute aider à satisfaire tout le monde, ceux pour le tout majuscule et ceux pour l’autre option. Ceci dit, je trouve cela un peu exagéré. Et, franchement, "private DBXml dbXml" ne me semble pas des plus naturels.
Si vous avez la version Java/Sun/Oracle sur le sujet, je suis preneur
Au final, cette règle des 2 caractères me semble bien superflu. Perso, je reste sur la règle du "seule la première lettre en majuscule".
Je suis preneur de toute opinion différente.
Allez, suffisamment dit (voir trop) sur le sujet: direction dodo !
++
joseph
Petites astuces Wicket
[This article is also available in English.]
Ces dernières semaines, j’ai pas mal utilisé Wicket.
Voici quelques petites astuces rencontrées en chemin
- Si vous utilisez un AjaxButton, surchargez onError et ajoutez un FeedbackPanel à ce qui sera réaffiché! En effet, un AjaxButton déclenche la validation du formulaire auquel il est rattaché. Et si cette validation échoue, il est fort probable que des FeedbackMessage soient créés en chemin. Il serait dommage de ne pas les afficher
. - Connaissez et utilisez Component.setRenderBodyOnly(boolean renderTag).Cette petit méthode permet de ne pas afficher le tag html auquel le composant est attaché, tout en affichant son contenu. Ca peut paraitre anodin, mais cela s’avère bien pratique lorsqu’on veut afficher de façon optionnel le fieldset entourant un composant.
- FormComponent.updateModel() n’est effectif que si le nouvel objet rattaché au modèle n’est pas égal au précédent.En effet, FormComponent.updateModel() appelle Component.setDefaultModelObject() avec le nouvel objet. setDefaultModelObject vérifie alors que le nouvel objet ne soit pas égal au précédent. Il fait cela afin d’éviter de créer une version non nécessaire de la page (qui sera ensuite gardée dans la PageMap). Ceci dit, si votre equals() n’est pas approprié, cela peut amener certains changements à ne pas être pris en compte (sans raison évidente). Pour éviter cela, il suffit de surcharger Component.getModelComparator() et de fournir un comparateur correspondant. Par exemple un comparateur ne vérifiant que l’égalité des références.
J’espère que cela pourra aider !
++
joseph
Utilisation de MongoDB chez Hot Potato
[Traduction autorisée de "Hot Potato Infrastructure: MongoDB", publié sur le blog d'Hot Potato par lincolnh le 5 mai 2010.]
Chez Hot Potato, nous utilisons MongoDB depuis 6 mois avec de grands résultats.
J’ai le sentiment que le positionnement de Mongo, parmi les technologies de stockage, est assez unique et correspond bien à ce que nous faisons. Les choses que j’apprécie particulièrement de Mongo sont:
- Très bonne documentation et excellent support. L’équipe Mongo soutient réellement la communauté et va jusqu’au bout pour aider les personnes à résoudre leurs problèmes. Voyez par vous même sur le groupe utilisateur ou le channel IRC #mongodb.
- La base de données ainsi que les drivers spécifiques à chaque langage sont open source.
- Le stockage sans schéma rend les choses simples et flexibles.
- Support très complet des requêtes ad hoc (NdT: requêtes assemblées à l’exécution).
- Mongo est rapide et supporte un large choix d’opérations atomiques.
- Utlisation de Map/Reduce (NdT: principe consistant à d’abord agréger les données à traiter, autrement dit "mapper", puis à les filtrer, soit les "réduire") pour l’agrégation.
- L’administration est vraiment simple et utilise une interface très complète en ligne de commande, avec support natif du JavaScript.
- Conçu pour la montée en charge.
Beaucoup d’autres personnes sont également impressionnées par Mongo et ont écrit à ce sujet:
- Why I think Mongo is to Databases what Rails was to Frameworks
- MongoDB: A Light in the Darkness!
- Notes on MongoDB
Cependant, personnellement, je ne pense pas que la capacité de Mongo à monter en charge ait suffisamment retenue l’attention. Par montée en charge, j’entends le processus d’optimisation graduelle pour plus de charge au cours du temps, au fur et à mesure que vos schémas et cas d’utilisations sont découverts et évoluent. Les fonctionnalités de Mongo et leurs interactions sont attirantes car souples et capables de s’adapter aux changements, tout en permettant, toujours, une montée en charge simple et efficace, sans prise de tête. C’est particulièrement utile dans les start up, mais certainement applicable à tout projet où les spécifications sont peu claires.
Prenez par exemple quelques étapes typiques qui doivent être suivies pour permettre à une base de données relationnelles (BDR) de monter en charge:
- A un certain moment, votre application commence à montrer des signes de faiblesse et la première chose que vous remarquez est que vous êtes écrasé par les lectures. Comme les temps de réponse de votre application ne doivent pas être instantanés, vous ajoutez une couche de cache externe, devant votre BDR – quelque chose comme memcached. Bien que plus compliqué, avec un grand nombre de lectures, vous pouvez aussi opter pour des esclaves en lecture seule.
- Bien que généralement les applications web ont un ratio lecture/écriture élevé, après avoir optimisé vos lectures, à un certain point, les opérations d’écriture commencent à poser un problème. En réponse, vous augmentez verticalement votre matériel, en termes de processeurs, mémoire vive et entrées/sorties. Cette étape est souvent couteuse.
- Même avec votre cache frontal et/ou vos esclaves en lecture seule, au fur et à mesure de la montée en charge, vous remarquez que de nombreuses lectures prennent plus de temps que vous ne le voudriez et sont généralement trop couteuses. Vous ne voulez pas ajouter du matériel ad eternam pour résoudre votre problème alors que vous savez que votre application pourrait encore être optimisée. Aussi, vous commencez à dé normalisez vos données. Au début, vous copiez stratégiquement de petites quantités de données pour éviter les jointures. Toutefois, avec le temps et la charge croissante, vous finissez par suivre cette route bien plus loin que prévu, dé normalisant de partout et éliminant toujours plus de jointures. En cours de route, vous ne cessez de modifier vos définitions de table et devez gérer les complications induites.
- Vous avez optimisé les lectures et les écritures, mais vous continuez à monter en charge. Vous constatez que la charge de vos machines accueillant votre BDR augmente de façon inquiétante. En réponse, vous éliminez autant de logique que possible de la base de donnée, tuant autant de triggers et de procédures stockées que possible. Parallèlement, vous pré matérialisez vos requêtes les plus complexes, qui, du fait de leur complexité, ont résisté à toutes vos tentatives de dé normalisation.
- Enfin, mais non des moindres, il se peut que les écritures commencent à être des goulets d’étranglement, même avec du matériel dopés aux hormones. A ce moment là, vous pouvez tenter de partitionner horizontalement vos données. Ceci n’est pas, pour la plupart des moteurs relationnels, géré de façon transparente par la base de données. Il faut donc gérer la chose depuis votre application. Ou vous supprimez vos index secondaires. Vous commencez alors à construire et gérer vos propres index secondaires, là où ils sont requis. A ce moment là, votre application doit être plus intelligente sur quand et comment accéder ses données.
La fin de partie de ce petit jeu est que, au final, vous utilisez vos données comme des paires clés/valeurs. Malheureusement, désormais, les fonctionnalités, structures, relations et les transactions d’une BDR sont autant d’obstacles. Des choses comme la rigidité du schéma ou les transactions ne font qu’ajouter du poids mort à chaque opération, même si la majorité, voir toutes, ne font désormais plus appel à ces fonctionnalités.
Comparons maintenant ce processus avec l’équivalent lorsqu’on travaille avec Mongo.
- Avec Mongo, pour commencer, les lectures sont sacrément rapides. Elles peuvent bien sûr être cachées de façon externe comme avec une BDR, mais d’après notre expérience cela tend à venir bien plus tard quand on utilise Mongo. Pourquoi ? Mongo utilise des fichiers stockés en mémoire, vous pouvez donc jeter de la RAM à votre instance Mongo et votre OS l’utilisera de façon efficace pour cacher les données. Aussi, même si vous en arrivez là, ce n’est pas un désavantage en soi de Mongo. De plus, Mongo a été construit depuis le début pour supporter le sharding (NdT: partitionnement en fonction des lignes et non des colonnes, chaque ligne pouvant être sur une machine différente, permettant lectures et recherches parallèles sur de plus petites unités), qui devrait être prêt pour la production d’ici peu. Ainsi, parallèlement à un ajout de RAM ou de cache frontal, vous pouvez faire des partitions horizontales et répartir vos lectures sur plusieurs machines.
- Pour les écritures, Mongo est également, d’entrée de jeu, sacrément rapide, vu que les transactions et autres niveaux d’isolations ne sont pas supportés. De plus, comme solution complémentaire à la montée en puissance matérielle, le sharding vous permet de monter en charge horizontalement d’une façon prévue par la base de données. L’application n’a pas à se soucier de la chose, il suffit de choisir les bonnes clés de partitionnement.
- Mongo ne fait jamais de jointure car elles ne sont pas supportées. Cela peut être vu comme un inconvénient. De l’autre côté, vu que Mongo est sans schéma, il est très facile de copier des données de ci de là et de découvrir graduellement la meilleure structure. Et chemin faisant, pas de mise à jour, modification et gestion (avec retour arrière occasionnels) de votre schéma, car il n’y en a pas.
- Map/Reduce est l’outil de Mongo pour la démarche d’optimisation consistant à pré matérialiser. L’aspect sympa est que les opérations de map/reduce sauce Mongo peuvent utiliser le sharding de la même façon que des lectures ou écritures classiques. Les batchs map/reduce s’exécuteront donc en parallèle et pourront ensuite être combinés. C’est la raison pour laquelle Mongo exige que le mapping et la réduction retournent la même structure. Faire tourner périodiquement une fonction de map/reduce est ainsi une façon très souple et performante de pré matérialiser vos requêtes et de pré agréger vos données.
- Enfin, Mongo supporte les indexes secondaires tout comme une BDR. En général, le même processus d’optimisation d’index peut s’appliquer avec Mongo qu’avec une BDR. Soit de les supprimer graduellement au cours du temps une fois que les changements de votre application permettent de faire sans. Comme Mongo est sans schéma, les changements qui résultent nécessairement de cette démarche de suppression/restructuration peuvent se faire sans se soucier de la définition du schéma et des éventuels retours arrières. De plus, les index sont également shardés. La FAQ de Mongo à propos de sharding aborde les détails, mais, sommairement, vu que les clés des shards déterminent quels shards une requête va accéder si votre index contient une clé de shard, alors vous pourrez mettre en oeuvre des requêtes qui:
- impactent le minimum requis de shards,
- obtiennent leurs données directement d’un index de ces shards.
J’aime les compromis de Mongo entre les fonctionnalités des base de données relationnelles et les structures clés/valeurs. Cela permet une montée en puissance graduelle sans nécessiter de connaissance préalable sur la façon exacte dont votre application va fonctionner. Et le partitionnement horizontal n’y est pas une verrue ou une rustine à posteriori.
Si vous voulez en savoir plus à propos de Mongo et rencontrer des personnes qui l’utilisent, vous devriez considérer d’assister à MongoNYC (NdT: événement passé au moment où je traduis ces lignes, mais Mongo propose régulièrement des événements, notamment en Europe). Vous pouvez utiliser le code "hotpotato" à l’enregistrement pour une réduction de 25%. J’y serai aussi, passez donc me dire bonjour.
Livre : The Pragmatic Programmer: From Journeyman to Master
[This article is also available in English.]
Par le passé, j’ai lu des livres tels que My Job Went to India: 52 Ways to Save Your Job ou Practices of an Agile Developer et, hum, j’ai préféré ne pas en parler…
Avec The Pragmatic Programmer: From Journeyman to Master, c’est différent. L’essentiel est dédié à comment augmenter ses compétences en programmation, au sens large (comment débugger, orthogonalité, utilisation des exceptions). Chemin faisant, il fournit des conseils de bonne qualité. Si vous sentez que vous pourriez faire mieux sans savoir vraiment où demander/chercher des conseils, alors ce livre est susceptible d’aider. Dans l’absolu, de bons livres techniques, tel Effective Java, ont ma préférence, mais de façon plus générale, presque en termes de méthodologie et d’approche, The Pragmatic Programmer: From Journeyman to Master peut aider.
Certes, je ne suis pas 100% d’accord avec ce qui est écrit. Je ne suis toujours pas un expert emacs et je n’envisage pas de l’être. La génération de code n’est pas que du bonheur, surtout si fait de façon statique (c’est à dire à un autre moment qu’à l’exécution). Mais cela n’enlève rien de la facilité et du plaisir de lecture global. Les chapitres vont droit au but sans pontifier. L’aspect pragmatique est, j’ai trouvé, ressenti.
Il est à noter que depuis la parution de ce livre, en 1999, et des suivants (susnommés), le web présente bien des ressources intéressantes sur le sujet. Par exemple le wiki 97 Things Every Programmer Should Know (qu’un google translate devrait pouvoir rendre accessible à des francophones purs, à défaut une traduction doit pouvoir se trouver voir même s’envisager). De telles ressources ont un intérêt similaire.
Au final, je ne pense pas que des livres, à eux seuls, puissent permettre de progresser réellement et efficacement en solitaire. Dieu merci, il existe désormais internet où il possible de trouver de bons programmeurs (cf Igor Vaynberg par exemple), voir même parfois de pousser la chose jusqu’à bosser avec eux… D’ailleurs, ne dit on pas "Qui ose gagne" ? lol
++
joseph
ps : lorsque je cherchais à remettre la main sur cette page avec ces 97 astuces, je suis tombé sur ça en chemin : 97 Things Every Software Architect Should Know. Et j’ai vraiment apprécié celle là : "Simplicité avant généralité, utilisation avant réutilisation". A méditer !
Wicket et ses fonctionnalités de templating
[This note is also available in English.]
Wicket fournit des fonctionnalités de templating. Rien de bien folichon, mais c’est tout de même bien pratique, surtout quand il faut intégrer du JavaScript.
Ces fonctionnalités sont cependant très peu discutées voir même, je suspecte, globalement inconnues. Aussi, creusons un peu la chose!
Comme tout système de templating, tout tourne autour de texte contenant des variables, définies par ${variable} et dont les valeurs sont données via Java.
Voyons un exemple simple, un fichier de template nommé javascript.tpl:
alert('${variable}');
Wicket permet d’aisément accéder à ces templates en tant que ressources mises dans des packages Java, via la classe PackagedTextTemplate:
public PackagedTextTemplate(final Class clazz, final String fileName)
Par exemple:
PackagedTextTemplate jsTemplate = new PackagedTextTemplate(this.getClass(), "javascript.tpl");
Ainsi, le template se trouve à côté de la classe Java et de l’html l’utilisant, rendant le tout aisé d’utilisation.
Les variables sont fournies au moyen d’une simple Map:
Map parameters = new HashMap();
parameters.put("variable","test working");
Au final ce template trônera certainement au milieu d’html. Aussi Wicket fournit plusieurs options pour cela:
- contribution au header html:
add(TextTemplateHeaderContributor.forJavaScript(jsTemplate, new Model((Serializable) parameters)));
- accolé à des éléments du body html:
Java:Label myScript = new Label("myScript", new JavaScriptTemplate(jsTemplate).asString(parameters)); myScript.setEscapeModelStrings(false); add(myScript);Html :
<wicket:container wicket:id="myScript"></wicket:container>
Vous avez sans doute remarqué que, dans chacun des cas, je ne fournis pas le tag qui devrait entourer le tout. Pas d’inquiétude à avoir, Wicket le fait pour vous.
L’html résultant est en effet:
<script type="text/javascript"><!--/*--><![CDATA[/*><!--*/
alert('test working');
/*-->]]>*/</script>
Si le template contenait plutôt du CSS, il faut juste utiliser un CssTemplate au lieu du JavaScriptTemplate.
Quelques info supplémentaires sont disponibles sur le wiki wicket: Including CSS resources.
++
joseph
Pourquoi cet intérêt pour les scriptlets et autres taglibs ?
[this article is also available in English.]
Les articles présentant le framework XYZ ou "comment choisir son framework web" abondent.
Une chose me surprend souvent : l’importance apparente accordée aux "bonne tag lib" et autres "super langage de scriplet". Soyons clair : il ne peut pas y avoir de bonnes tag libs ou de bons scriplets. Certains peuvent être bien codés, mais ça ne change rien: l’idée même est mauvaise dès le départ. Et dire "mettre la logique métier dans les scriplets est une mauvaise pratique", comme le fait la documentation Grails, ne suffit pas à changer la chose.
Pourquoi une opinion aussi tranchée ?
Voyons voir…
Encore un nouveau langage à apprendre.
Oui je sais, nous devrions tous apprendre un nouveau langage de programmation chaque matin. Mais je préfèrerai que de tels langages apportent des nouveautés, tels des concepts inusités. Concernant les scriptlets et autres taglibs, c’est à chaque fois la même chose, seule la syntaxe change. N’en n’attendez pas des découvertes, si ce n’est de mauvaises. Comme par exemple que personne ne sache comment utiliser le tag XYZ de telle bibliothèque dont la documentation n’a jamais été vue. A propos, vous pouvez très certainement oublier aussi la javadoc et les outils similaires…
Scriplets et tag lib ne sont pas orientés objet.
Oubliez la programmation objet. Déclarer des classes et des interfaces est souvent à peine possible, et encore moins utilisé. C’est encore pire concernant l’héritage. Est ce important ? Hum, essayez un peu le cobol et on parle à nouveau ! Plus sérieusement, oubliez les design patterns et assimilé. Vous êtes dans le royaume de la programmation procédurale, pas de l’Orienté Object, et tant pis pour tout ce que cela apporte!
Même le meilleur support par un outil est… boiteux!
L’une des meilleures intégration avec laquelle j’ai travaillé est Visual Studio et ASP.Net. Ce que l’IDE fournit est essentiellement l’auto complétion. C’est déjà bien mieux que rien, mais cela manque tout de même d’aide à la navigation telles que "montrer la hiérarchie", "montrer les références" et autres "ouvrir les appels". Et puis, quand vous avez écrit votre scriptlet, que deviennent ces "extraire méthode", "renommer" et autres outils de refactoring? Oubliez les aussi, vous faites des taglibs et scriptlets, bienvenu à l’âge de pierre. Bien sûr, tout cela ne doit pas faire oublier que, si jamais de tels outils venaient à apparaitre, qu’en serait il de l’intégration avec le langage utilisé pour tout le reste coté serveur ? De toutes façons, malgré l’ancienneté des scriptlets et autres taglibs, de tels outils n’existent toujours pas…
C’est le bazar !
Où mettez vous vos scriplets ? Au milieu d’html. Il y a quoi là déjà ? Facile : des tags html, du texte, du css et très certainement du javascript. Et vous voudriez ajouter, par dessus le tout, des petits scriplets et encore d’autres tags ? Génial ! Les designers n’y comprendront certainement rien, pas plus que le prochain développeur devant utiliser la chose… Quelle belle façon de communiquer vos intentions dans le code, brrr…
De la logique métier pourrait bien se glisser dans vos pages.
Nous savons tous que c’est une mauvaise pratique. La logique métier devrait être dans une couche métier. Sans duplication. Clairement présentée, facile à trouver et à modifier. Ceci dit, allez, "je n’affiche pas les éléments dont les parents contiennent Foo, on ne les veut jamais de toutes façons!". Combien même, malgré l’envie d’aller vite et les erreurs d’inattentions, vous vous tiendriez à cette ligne, qu’en est il du prochain développeur ? Comment vérifier que personne ne franchit cette ligne ? Souvenez vous, votre IDE ne vous aidera guère. J’imagine qu’il ne reste plus qu’à lire chacune de ces belles lignes de code, une à une. Ça fait un peu châtiment infernal non ? En tout cas je le souhaite à personne !
Au final, les scriptlets et taglibs me font vraiment l’impression d’une fausse bonne idée que nous devrions nous dépêcher d’oublier. Ils sont difficiles à développer, dur à personnaliser (tags) et à généraliser (scriptlets), illisible et une réelle gageure à maintenir. Perso, tous les frameworks web les supportant me font froid dans le dos. Des tags spécifiques pour se rattacher au côté serveur ? Oui, bien sûr, c’est quasi inévitable de toutes façons. Mais pas plus. Dès que je vois des "if", "while" et le reste, c’en est trop. Et cela devrait être le cas pour tout le monde je pense !
++
joseph
(Petite) Astuce wicket : ne pas caster sa classe Application
Salut
Fréquemment, il m’arrive du voir du code wicket tel que
((MyApplication)Application.get()).myApplicationSpecificMethod();
Perso, cela me pique toujours un peu les yeux. Or, il y a tout simple, à savoir définir dans MyApplication quelque chose comme:
public static MyApplication getWebApplication() {
return (MyApplication) Application.get();
}
on peut alors écrire :
MyApplication.getMyApplication().myApplicationSpecificMethod();
Cela peut s’applique également à la Session, pour sûr.
voilà, trois fois rien, clairement, mais un pas de plus vers un code propre. Ca en vaut donc la peine (et ça m’évitera de me répéter sur le forum wicket développez.com, even better
).
++
joseph
Livre : Effective Java, 2nd edition
Comment dire… Pour faire simple, pour moi, ce livre devrait être obligatoire pour tous les développeurs Java. Rien de plus, rien de moins, simple non ?
Au lieu des habituels "comment faire une boucle", l’auteur y aborde comment utiliser au mieux les différents éléments constituant le langage Java, en justifiant et expliquant le tout, permettant au lecteur de bénéficier de son ample connaissance du langage. Le sommaire donne d’ailleurs une bonne idée de l’ampleur des thèmes abordés.
Pour ma part, cela m’a vraiment donné une meilleure vision du langage et des problématiques objet en général. On comprend dès lors mieux les forces et faiblesses, tout en ayant ce qu’il faut pour en tirer le maximum.
Ainsi, pour peu que vous vous posiez des questions en codant, ce livre se dévore et permet vraiment un approfondissement du langage. Personnellement, j’en suis à ma deuxième lecture…
Enfin, en écrivant cette critique, je me suis rendu compte que des pointures tels James Gosling ou Heinz M. Kabutz (de Java Specialists) partageaient pleinement mon opinion.
Pour conclure : foncez l’acheter !
Plus de détails sur JavaBook.
Première parution de cette critique sur developpez.com.