Archive for the 'java' Category

Responsabilité et atomicité des fonctions

Le projet sur lequel je travaille comporte des problèmes d’architecture que j’ai déjà évoqué dans mon billet précédent. Aujourd’hui, je souhaite aborder un autre problème de conception, qui concerne la répartition des responsabilités dans une classe.

Craig Larman nous conseille de respecter le principe de forte cohésion lorsqu’on défini les responsabilités que doit implémenter une classe. A une échelle inférieure, une méthode doit également respecter une certaine cohésion.

Pour être concret prenons l’exemple d’une méthode qui s’appellerait isValide() et supposons que l’implémentation de cette méthode nécessite d’effectuer une itération sur une liste. La tentation est de profiter du parcours de cette liste pour effectuer des traitements annexes « à la volée », ce qui évite de parcourir la liste une deuxième fois. Dans notre cas, le contrat annoncé par la méthode isValide() consiste fournir la réponse à une question. Pour respecter la cohérence de la fonction, celle-ci doit se contenter strictement d’y répondre et rien d’autre. Tout traitement annexe vient polluer la méthode et rend son utilité moins évidente.

Le problème qu’on peut rencontrer est que cela peut aboutir à une duplication de code. Pour reprendre l’exemple d’une fonction qui implémente une itération sur une liste, on peut se retrouver à implémenter cette itération dans plusieurs méthodes pour respecter l’unitarité de chacune d’elle. Si cela pose des problèmes rédhibitoires de performance, la solution est de n’avoir qu’une seule itération et d’implémenter le pattern Observer pour effectuer plusieurs traitements sur les éléments de la liste.

La cohérence d’une fonction rend son utilité plus claire ce qui facilite la maintenance du code.

La gestion des dates en Java

Je travaille actuellement sur un projet dans lequel nous avons besoin de manipuler des dates. Le projet est assez ancien, il date de plus de quatre ans, et à l’évidence, ceux qui ont écrit cette appli ne maîtrisaient pas très bien la programmation orientée objet. Et comme dans le même temps, très peu de documentation a été rédigée et que le projet a changé de domaine, je me retrouve tout seul à essayer de décrypter des lignes de code absconses et indigestes.

Je souhaite donc vous faire profiter d’un petit retour d’expérience afin d’améliorer la gestion des dates dans vos projets Java.

Petit rappel, il existe deux classes qui permettent de représenter une date dans l’api standard. Il s’agit de Calendar et Date, toutes deux dans le package java.util. Je ne traite pas ici du package java.sql.

Lorsque vous avez besoin de représenter une date en attribut d’une classe, je recommande l’utilisation de Date plutôt que Calendar. En effet, Date est un objet immuable (ou presque), il garanti qu’il ne sera pas modifié par mégarde et élimine les problèmes d’accès concurrent en cas de programmation multithread :

public class Personne {
    public final String nom, prenom;
    public final Date dateDeNaissance;
}

Faites attention lorsque vous initialisez une Date. Si vous utilisez le constructeur par défaut, la date sera initialisée avec pour valeur le nombre de milliseconde depuis le 1er janvier 1970. Le problème est que lorsque vous récupérez une deuxième Date par défaut et que vous les comparez toutes les deux, bien que ces deux dates correspondent au même jour calendaire, la comparaison échouera car la valeur en milliseconde sera différente.

Je recommande donc l’écriture d’une classe d’utilitaire qui permettra de manipuler les dates en adoptant une approche fonctionnelle :

public class CalendarUtil {
    private static final Calendar calendar = Calendar.getInstance();

    public static Date getDate(int jour, int mois, int année) {
    }
    public static Date getDate() {
        //retourne une date correspondant à la date courante (aujourd'hui)
    }
    public static Date incrementer(Date date, int jours) {
    }
    public static boolean equals(Date date1, Date date2) {
        //indique si deux dates correspondent au même jour calendaire
        //sans tenir compte des heures, minutes, secondes
    }
    public static int difference(Date date1, Date date2) {
        //retourne la différence en nombre de jours
    }
    public static boolean isEcheanceEchue(Date date, Periodicite period) {
    }
    public static String format(Date date, String pattern) {
    }
    [...]
}

Comme vous l’aurez constaté, cette classe d’utilitaire ne prend que des Date en paramètre. C’est en effet ma troisième recommandation et sans doute la plus importante. L’usage de Calendar doit être réservé aux calculs sur les dates, et donc être circonscrit à la classe CalendarUtil.

Je ne traite pas de la question des fuseaux et des locales, mais je recommande là encore une approche fonctionnelle

Par ailleurs, les plus perspicaces d’entre vous aurons remarqué que la méthode incrémenter() de CalendarUtil peut entrainer une conflit de signature. C’est le cas si l’on a besoin d’ajouter des mois ou des années à une date.

Dans ce cas, je recommande de suivre les préconisations de Stephan Schmidt :

public static Date incrementer(Date date, NbJours jours) {
}
public static Date incrementer(Date date, NbMois mois) {
}
public static Date incrementer(Date date, NbAnnees annees) {
}
public class NbJours {
    public final int value;
    public Jour(int value) {
        this.value = value;
    }
}
[...]

Ces recommandations, si elles sont suivies à la lettre, vous éviterons bien des soucis tel que je peux en rencontrer actuellement avec mon vieux projet. Dernier conseil qui va de soit, vous devrez évidemment tester unitairement chaque méthode de CalendarUtil.

Java est présent sur 99.9% des PC en entreprise

Selon une étude Forrester mentionnée sur Silicon.fr, le logiciel Java (JRE) est présent sur 99.9 % des PC en entreprise, devant le logiciel Flash (99%).

Un framework Swing

J’ai développé un framework Swing que j’ai appelé Swinger et qui permet de décrire une application de bureau avec un simple fichier XML :

<j:frame width="600" height="400" addWindowListener="actions.ActionQuitter" x="50" y="50">
	<j:menubar>
		<j:menu text="Fichier">
			<j:menuitem text="Quitter" addActionListener="actions.ActionQuitter"/>
		</j:menu>
	</j:menubar>
	<j:panel width="600" height="400">
		<j:textarea text="Hello !" width="300" height="200"/>
	</j:panel>
</j:frame>

Je dois avouer que je suis plutôt fier de mon bébé. Il est encore très incomplet car cela ne fait que trois jours que je travaille dessus, mais j’espère qu’il est promit à un bel avenir. J’ai écrit un KickStart sur le wiki du projet. Si vous avez des questions, n’hésitez pas à les poser dans l’onglet « Issues ».

Créer une application Facebook en Java

[EDIT]

Facebook abandonne le langage FBML. Dorénavant, toutes les applications devront être écrites selon les standards du web (HTML/CSS/JavaScript) et être intégrées à Facebook grâce aux iFrames. Ce tutoriel est donc devenu en grande partie obsolète.

[/EDIT]

Je vous propose un tutoriel pour créer votre première application Facebook. Il existe deux APIs standards, l’une en PHP, l’autre en Java. Nous allons étudier la seconde. Notre application s’appellera yafba (Yet Another Facebook Application).

Nota : Certaines lignes de code sont trop longues et ne s’affichent pas entièrement. Dans ce cas, faites un copier-coller dans un éditeur de texte.

Prérequis

Vous devez posséder un compte sur Facebook et ajouter l’application developers. Cette application va vous permettre d’obtenir une clé d’API pour votre application et vous permettre d’accéder à la documentation en ligne.

Vous devez également avoir un hébergement Java. En effet, bien que les utilisateurs accédent à votre application par l’intermédiaire de Facebook, vous hébergez vous-même l’application et les données que vous recueillez. Ce qui est important, c’est que le serveur qui héberge votre application doit être accessible publiquement par une URL. Il n’est pas nécessaire d’acquérir un nom de domaine, vous pouvez utiliser l’URL fournie par votre hébergeur.

L’environnement de développement

Vous devez télécharger l’API Facebook. Celle-ci est disponible via l’application developers :

L’archive contient le code source de la librairie à partir duquel vous pourrez générer la javadoc. Vous trouverez également la librairie compilée sous la forme d’une archive facebook.jar que vous devez importer dans votre projet.

Notez qu’il n’est pas possible de tester une application Facebook en localhost. Pour être testée, l’application doit être déployée sur le serveur que vous avez déclaré dans l’adresse de callback. Il existe néanmoins un émulateur accessible en ligne qui permet de tester son code FBML ou de tester l’API Facebook.

L’architecture

Nous n’aborderons pas la structure d’une application Facebook en détail, celle-ci est constituée de plusieurs composants dont la plupart sont générés automatiquement par les serveurs de Facebook. Nous nous intéresserons uniquement à la génération de la page d’accueil.

Pour faire fonctionner notre application, nous utiliserons un simple conteneur de Servlet, par exemple Tomcat. L’application reposera sur les Servlets et les JSPs. Les Servlets auront la responsabilité d’extraire les informations de l’API Facebook, et les JSPs serviront à générer la couche présentation au format FBML (FaceBook Markup Langage). Nous utiliserons accessoirement la librairie JSTL.

Référencement de l’application sur Facebook

Avant de développer notre application, nous allons commencer par la référencer sur Facebook. Pour cela, vous devez demander une clé d’API par le biais de l’application developers.

Les informations importantes à fournir sont le nom de votre application et l’URL de callback. Cette dernière doit correspondre à l’URL de votre serveur suivi du répertoire dans lequel vous avez l’intention de placer votre application. Elle est de la forme http://serveur.com/yafba/.

Vous pouvez également définir une URL pour le canvas qui correspond au cadre de votre application. Celle-ci est de la forme http://apps.facebook.com/yafba/. Ainsi, lorsque votre serveur contient un fichier http://serveur.com/yafba/index.jsp, celui-ci est accessible à travers Facebook par l’url http://apps.facebook.com/yafba/index.jsp.

Demandez enfin à ce que votre application puisse être intégrée à Facebook, cela permettra aux utilisateurs de l’ajouter à leur profil sous la forme d’un widget. Vous verrez alors apparaître des options supplémentaires. Parmi celles-ci, l’URL Post-Add correspond à l’URL « frontale » vers laquelle sont dirigés les utilisateurs qui cliquent sur le lien de votre application.

Toutes ces opérations se font à partir de l’application developers.

Connexion

Maintenant que notre application est référencée sur Facebook et que notre environnement de développement est correctement configuré, nous allons commencer à coder.

Nous allons écrire une Servlet « test » qui traitera les requêtes en provenance de Facebook :

<servlet>
	<servlet-name>test</servlet-name>
	<servlet-class>fr.hadf.yafba.servlets.Test</servlet-class>
</servlet>
<servlet-mapping>
	<servlet-name>test</servlet-name>
	<url-pattern>/test</url-pattern>
</servlet-mapping>

La classe centrale de l’API est FacebookRestClient. Il s’agit d’une classe abstraite qui est héritée par deux sous-classes qu’on choisi selon le protocole qu’on veut utiliser, XML ou Jason. Nous allons utiliser le protocole XML.

La première chose que nous faisons est d’extraire le champ « fb_sig_session_key » de la requête entrante. Si ce champ est vide, nous redirigeons l’utilisateur vers la page de login dont l’URL est construite avec la clé d’API. Lorsque l’utilisateur aura été authentifié, il sera à nouveau redirigé vers notre Servlet, mais cette fois avec un champ « fb_sig_session_key » renseigné :

private void connection(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException, FacebookException {
	String sessionKey = req.getParameter("fb_sig_session_key");
	if(sessionKey == null) {//on redirige l'utilisateur vers la page de login
		String url = "http://www.facebook.com/login.php?api_key="+api_key+"&v=1.0&canvas&next=test";
		res.getWriter().println("<fb:redirect url='"+url+"' />");
		return;
	}
	else {//l'utilisateur est maintenant authentifié
		FacebookXmlRestClient client = new FacebookXmlRestClient(api_key, secret, sessionKey);
		loginSuccessfull(client, req, res);
	}
}

Utilisation de l’API Facebook

Nous allons maintenant utiliser l’API Facebook pour extraire la liste des amis de l’utilisateur courant :

protected void loginSuccessfull(FacebookRestClient client, HttpServletRequest req, HttpServletResponse res)
throws IOException, FacebookException, ServletException {
	Document root = (Document)client.friends_get();
	NodeList list = root.getElementsByTagName("uid");
	ArrayList friends = new ArrayList();
	for(int i=0; i<list.getLength(); ++i) {
		String uid = list.item(i).getTextContent();
		friends.add(uid);
	}

	req.setAttribute("friends", friends);
	getServletContext().getRequestDispatcher("/test.jsp").forward(req, res);
}

Nous utilisons simplement la fonction FacebookRestClient.friends_get(). Cette méthode retourne un objet diffèrent selon qu’on utilise le protocole XML ou Jason. Dans notre cas, nous récupérons un objet de type org.w3c.dom.Document. Pour connaître le format de la réponse, il suffit d’interroger la console de test disponible sur Facebook :

<?xml version="1.0" encoding="UTF-8"?>
<friends_get_response 	xmlns="http://api.facebook.com/1.0/"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://api.facebook.com/1.0/ http://api.facebook.com/1.0/facebook.xsd"
	list="true">

	<uid>1</uid>
	<uid>2</uid>
	<uid>3</uid>

</friends_get_response>

Nous extrayons alors le champ uid et utilisons l’objet request pour passer la liste des valeurs à la JSP.

Nous n’utilisons pas cette fonction, mais sachez que l’API permet également d’interroger la base d’utilisateur de Facebook grâce au langage FQL :

Document root = (Document)client.fql_query("SELECT name FROM user WHERE uid=" + uid;

Couche présentation

Nous commençons par écrire une page index.jsp qui nous servira d’URL « frontale », celle déclarée en URL Post-Add. Elle sollicite l’utilisateur pour envoyer une série d’invitations à ses amis afin d’ajouter notre application à leur profil :

<%@ page language="java" pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<fb:fbml>
	<fb:request-form type="yafba"
		action="test"
		content="Je vous invite à ajouter l'application yafba">
		<fb:multi-friend-selector actiontext="Selectionnez les amis auxquels vous voulez adresser une invitation"/>
	</fb:request-form>
</fb:fbml>

Notre application est ensuite très simple, elle se contente d’afficher une liste d’amis (test.jsp). Rappelons que cette liste a été extraite à partir de la Servlet « test » qui est appelée après validation du formulaire d’invitation. Nous utilisons la librairie JSTL pour garder propre la couche présentation :

<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>

<fb:fbml>
	<c:forEach items="${requestScope['friends']}" var="uid">
		<fb:name uid="${uid}"/><br>
	</c:forEach>
</fb:fbml>

Conclusion

Vous venez d’écrire votre première application Facebook. Elle est accessible à partir du cadre « My Application » dans l’application developers.

Il ne s’agit que d’une présentation très modeste de ce qu’il est possible de faire. Ce tutoriel vous a surtout permis de comprendre l’architecture d’une application Facebook. A vous maintenant d’explorer la documentation si vous voulez aller plus loin.

Bonne continuation 😉

Remerciements

Je remercie Michael Bagur pour son aide précieuse, en particulier pour la phase de connexion à l’API, et pour sa relecture.

Que pensez-vous des évolutions à venir du langage Java ?

Le site developpez.com organise des sondages au titre de Java User Group en vue de récolter l’opinion des developpeurs Java sur les évolutions futures du langage. Je recommande à tous les developpeurs confirmés d’y participer et de partager leur opinon sur le forum.

A retrospective of Java

Un billet qui date un peu, et en anglais, qui présente une petite rétrospective de Java.

http://www.readwriteweb.com/archives/java_a_retrospective.php

Créer des effets graphiques avec Swing

Swing est la librairie graphique de Java. C’est une librairie extrêmement bien écrite et son introduction dans le jdk 1.2 a été une véritable révolution. Mais cette librairie souffre l’inconvénient d’être conçue avant tout pour les développeurs, et le moins que l’on puisse dire est que ceux-là ne sont pas réputés pour leurs talents de graphiste.

Je ne crois pas que cet état des choses peut changer, mais un livre est là pour tenter de prouver le contraire. Ecrit en anglais, Filthy Rich Clients (Clients riches esthétiques) montre au développeur comment concevoir des effets graphiques de toute sorte et permettre de donner un peu de finesse à leurs applications graphiques. Les slides, qui sont visibles au format pdf sur le site dédié, sont très bien faits. Ils montrent des exemples progressifs de code pour obtenir des effets tels que des dégradés ou des effets de transparence.

Sans doute s’agit-il d’un pas en avant dans la perspective qu’ambitionne Sun de gratter des parts de marché au lecteur Flash. Mais le pas décisif ne sera véritablement franchit que lorsqu’un framework sera disponible avec les outils wysiwyg à destination des designers.

Les frameworks Ajax

Les frameworks de développement Web reposant sur JSP on l’inconvénient majeur de nécessiter une bonne connaissance de JavaScript pour pouvoir développer un site en Ajax. Pendant longtemps, ces frameworks ne prennaient pas en compte cette dimension du développement Web. Mais un nouveau type de frameworks spécialement conçu autour de la technologie Ajax a fait son apparition depuis environ un an. Leur particularité est de permettre à un développeur Java d’écrire une application Ajax sans aucune connaissance de JavaScript.

Il existe deux frameworks plus ou moins équivalents que sont GWT (Google Web Toolkit) et Echo2. L’un comme l’autre permet de concevoir une application Ajax sans écrire une seule ligne de code en JavaScript. Leur principe est de proposer une librairie Java et un compilateur qui converti le code de cette librairie en JavaScript. Mais bien que reposant sur le même principe général, ces deux frameworks sont en fait très différents.

GWT distingue de façon très nette les parties cliente et serveur. La première est intégralement compilée en JavaScript et peut être exportée vers n’importe quel serveur Web tel que Apache, tandis que la partie serveur est destinée à tourner sur un conteneur de Servlet tel Tomcat. Bien sûr, il est possible de faire tourner le tout sur Tomcat, mais seules les librairies pouvant être compilées en JavaScript peuvent être inclues dans le code de la partie cliente.

En revanche, Echo2 n’offre pas de cadre pour distinguer le côté serveur et le côté client, il appartient au développeur de s’en tenir au design pattern adéquate. Et à la différence de GWT, Echo2 génère une véritable application Java dont le code est intégralement délivré par des Servlets. Il n’est donc pas possible d’exporter une application Echo2 vers un simple serveur Web.

Quel que soit le choix de la technologie, les frameworks Ajax ont l’avantage, pour un développeur Java, de pouvoir se lancer dans l’écriture de Services Web complexes. On signalera enfin l’existence d’une librairie Ajax conçue spécifiquement pour le framework JSF et qui s’appelle Ajax4Jsf, nous aurons l’occasion d’y revenir.

Les frameworks de développement Web et le pattern MVC

Le langage Java s’est principalement imposé côté serveur, cela s’entend dans une architecture client/serveur. C’est pourtant dans les applications autonomes que Java a tout d’abord mis en oeuvre l’architecture qui allait faire sa popularité, à savoir le pattern MVC. La philosophie sous-jacente à MVC est de supprimer les couplages inutiles, c’est-à-dire de décomposer l’application en modules indépendants les uns des autres. C’est déjà ce que permet de faire la programmation orientée objet en théorie, mais la réalité est que les développeurs, cherchant la facilité au premier abord, établissent souvent à des redondances inutiles qui sont à l’origine d’enchevêtrements abscons. Les designs patterns sont là pour rappeler les bonnes pratiques en matière de programmation et, de ce fait, faciliter tant la collaboration des équipes que la mise à jour ultérieure du code. Cette approche de la programmation a été adoptée dans la librairie swing qui est la librairie graphique de Java pour les application autonomes.

Parallèlement à son succès auprès des développeurs, Java s’est progressivement imposé côté serveur jusqu’à devenir un acteur incontournable du Web au même titre que le langage PHP. Mais cette progression c’est faite laborieusement comme nous avons pu le voir dans un billet précédent. Face à la complexité croissante des applications Web, la nécessité d’en revenir aux meilleurs pratiques de développement s’est rapidement fait sentir. C’est pour répondre à la détresse des architectes logiciels que la fondation Apache a crée le framework Struts. Un framework dont l’objectif avoué est d’inviter les développeurs à de meilleures pratiques, et notamment à recourir au fameux pattern MVC qui consiste à séparer une application en trois couches que sont la couche de présentation, la couche métier et la couche de contrôle, celle qui fait le pont entre les deux premières.

La couche de présentation (Vue) est celle qui a la responsabilité de générer ce qui est affiché à l’écran, c’est-à-dire le positionnement des composants graphiques ainsi que les détails de leur aspect comme la couleur. La couche métier (Model) est celle qui met en oeuvre la logique de l’application, elle a pour responsabilité de représenter les données du problème et de les résoudre. Enfin, le controleur (Controler) établit la relation entre la Vue et le Model, elle gère la dynamique de l’application.

Comme nous l’avons écrit dans dans un billet précédent, les JSP reposent sur un langage de balises extensible. Cette propriété a été exploitée par les concepteurs de Struts pour créer une librairie de balises permettant de résoudre la majorité des problèmes posés par l’écriture de la couche présentation, cela sans avoir besoin de recourir aux Scriptlets. Cela permet finalement d’unifier le langage utilisé pour la couche présentation généralement écrite par les équipes de design. Le langage Java est ainsi réservé à l’écriture des couches métier et controleur.

C’est donc pour répondre à ce motif que le framework Struts a été développé. Il y est parvenu au prix d’une certaine complexité qui le réserve aux projets de grande envergure.


avril 2021
L M M J V S D
 1234
567891011
12131415161718
19202122232425
2627282930  

linux

Linux

jiwamusic