Archive pour la catégorie ‘Tutoriels’

RDF et les débats en ligne

Lundi 28 juin 2010

Cela fait maintenant deux ans que je travaille dans le cadre de l’ANR intermed sur les débats en ligne. Et après deux ans, nous avons via de nouvelles rencontres, de nouvelles opportunités d’échange sur le sujet. J’en profite alors pour recommander des formats d’échange de données entre différentes applications dédiées aux débats en ligne. Les formats sont des utilisations conjointes de divers vocabulaires RDF.

Il faut dire que ça commence à faire pas mal de temps qu’on nous parle de démocratie participative et que sur le net, il n’y a pas grand chose. Un blog institutionnel par là (voir le travail de blog-territorial et leur livre sur l’usage des blogs dans des collectivités), un élu qui raconte sa vie ici et là, une candidate qui propose une plateforme que je comprends toujours pas à quoi elle sert … En fait si, il y a beaucoup de choses. Il y a beaucoup de forums ou blogs ou l’on peut débattre, quelques wikis aussi. Mais il n’y a pas de réelle plateforme pour les débats qui permette de passer à une grande échelle (de sujets et d’utilisateurs). Il n’y a pas non plus de système qui fasse correctement le lien entre les discussions (en ligne ou non) et les décisions ainsi que leurs mises en application.

L’objectif de l’article n’est pas de dresser un état de l’art de la pratique de débats en ligne mais de proposer des formats d’échanges de données afin de faciliter la création d’une véritable plateforme de débat (ou de transformer le web en une véritable plateforme de débats …).

Dans une vision trés web 2.0, le débat 2.0 permettrait de partager les données entre applications, offrant des possibilité de réutilisation et de traitement de ces données (on veut des Mashups pour le débat !!). Au lieu d’encourager une collectivité à avoir son propre blog et imposer celui-ci comme espace de discussion privilégié des administrés, pourquoi ne pas proposer à la collectivité une application qui lui permette d’aggréger les flux RSS des blogs déjà existant et de synthétiser les critiques qui y sont exprimées.

L’article se compose en deux parties:

  1. La première partie a pour objectif de présenter ce qu’est un débat en ligne et les problématiques d’interopérabilité intrinséque à cette notion.
  2. La deuxième partie présente un ensemble de vocabulaires RDF et leur utilisation conjointe pour représenter les éléments d’une discussion. Les vocabulaires choisis ont leur limite mais l’un des avantages de RDF est que des ponts existent entre les vocabulaires (cf le projet LOD) et que les vocabulaires peuvent être étendus (ajout de classes plus spécialisées, ajout de propriétés, …). La solution de “format” ici présentée n’est donc qu’un début de proposition que nous serons amenés à faire évoluer, cependant, ce qui est présenté ici devrait constituer un noyau stable.

Un débat en ligne c’est quoi ?

Déjà, il m’est très difficile de définir ce qu’est un débat. Alors définir ce qu’est un débat en ligne… Je vous propose un début de définition mais je vous invite à m’aider à la raffiner.

Un débat en ligne c’est un débat supporté (au moins en partie) par des applications web.

Une fois qu’on a dit ça, on n’a pas dit grand chose.

Voici quelques citations pour m’aider à définir ce qu’est un débat.

  • La version wikipédia : Un débat est une discussion sur un sujet, précis ou de fond, annoncé à l’avance, à laquelle prennent part des individus ayant des avis, idées, réflexions ou opinions divergentes pour le sujet considéré.
  • Dans le décret de 2002 relatif à l’organisation du débat public, on observe qu’un débat public est évalué par une commission (de trois à sept membres), avec un président. Une personne publique ou un maître d’ouvrage porteur du débat doit proposer au président de la commission un dossier à destination du public. Ce dossier peut contenir des documents de références jugés nécessaires pour le débat. Ce dossier est donc évalué par la commission avant que le débat public ne soit organisé. Le porteur du débat peut également proposer des modalités d’action et un calendrier. Sont susceptibles de donner naissance à un débat, des projets d’aménagement ou d’équipement d’intérêt national de l’Etat, des collectivités territoriales, des établissements publics, et des personnes privées entrant dans un ensemble de catégories listées dans le décret. La commission peut estimer que le débat n’a pas lieu d’être et proposer une concertation à la place. Le bilan du débat ou de la concertation, doit être publié et transmis aux décisionnaires.
  • Dans la Loi du 27 février 2002 relative à la démocratie de proximité, Champ d’application et objet du débat public : La Commission nationale du débat public, autorité administrative indépendante, est chargée de veiller au respect de la participation du public au processus d’élaboration des projets d’aménagement ou d’équipement d’intérêt national de l’Etat, des collectivités territoriales, des établissements publics et des personnes privées, relevant de catégories d’opérations dont la liste est fixée par décret en Conseil d’Etat, dès lors qu’ils présentent de forts enjeux socio-économiques ou ont des impacts significatifs sur l’environnement ou l’aménagement du territoire. (…) « En outre, la Commission nationale du débat public veille au respect de bonnes conditions d’information du public durant la phase de réalisation des projets dont elle a été saisie jusqu’à la réception des équipements et travaux. « Elle conseille à leur demande les autorités compétentes et tout maître d’ouvrage sur toute question relative à la concertation avec le public tout au long de l’élaboration d’un projet. « La Commission nationale du débat public a également pour mission d’émettre tous avis et recommandations à caractère général ou méthodologique de nature à favoriser et développer la concertation avec le public. « La Commission nationale du débat public et les commissions particulières ne se prononcent pas sur le fond des projets qui leur sont soumis.
  • (Testard-Vaillant, 2008) parle de La place publique ou de l’espace public qui « est un des concepts fondamentaux de la démocratie. Il désigne le lieu symbolique où peuvent s’exprimer toutes les opinions qui structurent le jeu politique, où l’on traite des questions relevant de la collectivité ».
  • Chez (Vedel, 2003), le débat est une phase séparée de l’information des citoyens et de la délibération. C’est l’une des 3 dimensions (information, débat, délibération) de son cube de la démocratie. Le débat ou la discussion permet de mesurer l’étroitesse ou la fermeture de l’espace public. Le débat est la phase entre l’information et la délibération. Le débat s’inscrit donc dans un processus de prise de décision.
  • (Bidima, 1997 p113 ) : Toute palabre suppose la prédisposition des groupes ou sujets en débat à mettre en péril leur vérité par la confrontation. Il s’établit implicitement un mouvement de corrosion des positions assurées et absolues. Palabrer signifie mettre “ses absolus” devant la possibilité de leur relativisation. Ce jeu entre un absolu qui devient relatif et l’émergence du seul absolu qui est le relatif, constitue l’une des composantes du mouvement de prise et de dépossession de la parole qu’est la palabre.
  • (Callon et al, 2002) définissent l’objectif d’un débat public de la façon suivante : “il doit organiser l’accueil des groupes concernés et faciliter la réduction des incertitudes.”
  • (Fung, 2006) estime que les mécanismes participatifs sont évalués selon trois critéres : la légitimité, l’équité et l’efficacité. Les indicateurs pour cette évaluation sont : le champ de participation (qui peut s’exprimer et qui s’exprime), les modes de communication et de prise de décision, l’impact réel des discussions sur les prises de décision.
  • (Vignaux, 1988) la définition d’Aristote de la discussion dialectique est la suivante : c’est un jeu à deux où le couple de partenaires incarne à la fois deux oppositions binaires, celle de l’affirmation et de la négation, celle de la victoire et de la défaite.
  • (Chabrol, 1999), une opinion est un acte discursif où l’énonciateur « modalise » explicitement ou implicitement l’objet de son énonciation avec les dimensions « possible/impossible », « souhaitable/non souhaitable », « beau/laid », « agréable/désagréable » …

On ne trouve pas vraiment de définition de ce qu’est un débat public sur le site du CNDP. On apprend ce qui justifie la mise en place de débats publics, qui sont les acteurs important dans l’organisation du débat et quel est l’objectif principal d’un débat (consulter et informer le citoyen, le faire participer à l’élaboration d’un projet socio-environnemental qui le concerne). Mais on ne nous fournit pas de définition formelle de ce qu’est un débat.

Un débat s’inscrit dans un processus de prise de décision. Le mot débat peut concerner le processus complet ou une étape uniquement du processus de décision. Dans tous les cas, la discussion est un élément central du débat. C’est un échange qui permet d’exprimer des opinions contraires, des oppositions, de revoir ses certitudes ou incertitudes à la lumière de celles des autres participants dans le but d’aider à prendre une décision. Un débat fait intervenir des acteurs différents : des organisateurs, des évaluateurs, des groupes concernés qui se sont manifestés ou qu’il faut identifier.

Ajoutons que pour certains, la discussion est source de formation et d’information, pour d’autres, il faut déjà être informé pour pouvoir discuter. Pour certain il faut réduire les incertitudes des groupes concernés, pour d’autre, il faut aider le décideur.

Soulignons l’importance du sujet et de l’expression du sujet. L’un des échecs du débat public sur les nanotechnologies semble être d’avoir voulu traiter des Nanos dans leur ensemble (cf le site du débat Nano). La formulation du sujet d’un débat a de l’importance, “êtes vous pour ou contre les nanotechnologies ? ” est différent de “sur les options générales en matière de développement et de régulation des nanotechnologies”.

Et enfin, il ne faut pas sous-estimer l’aspect “image” de l’organisateur du débat public. Un autre facteur d’échec du débat public sur les nanotechnologies est peut-être d’avoir été organisé par le CNDP, organisme d’état jugé comme parti pris dans la discussion par de nombreux participants.

Dans notre approche, jusqu’ici, nous avons utilisé des ressources de départ (en l’occurence des documents html en ligne) comme point d’accroche des discussions. Nous avons adopté la position de l’information avant la discussion. Cependant, les deux approches ne sont pas incompatibles. La discussion permet dans tous les cas de s’informer.

Peut-on considérer qu’il existe déjà des outils de débats en ligne ?

Si l’on considére qu’un débat est une discussion dans laquelle s’expriment des opinions alors oui il existe déjà des outils. Tous les outils de discussion permettent d’exprimer des opinions sur des sujets. Après, le traitement de ces opinions n’est pas toujours une mince affaire (Wilson et al, 2009). Dans ce cas, il existe des solutions pour déceler les opinion, mais limitées par des problèmatiques de taille et de dynamique. La plupart des solutions de détection d’opinions sont effectuées à posteriori, sur des corpus ciblés et de taille limitée. Pas de fouille d’opinion en temps réel.

Si l’on considére que le débat est un processus de décision à part entiére, alors ce processus peut-être découpé en étapes (information, discussion, décision, ou autre découpage). Chaque étape pouvant être plus ou moins soutenue par des outils en ligne, comment faire en sorte que les données produites puissent être utiles d’étapes en étapes (que ces étapes soient intégralement en ligne, ou intégralement en présentiel ou les deux) ?

Nous sommes dans une vision du débat en ligne ou la phase de discussion est primordiale mais non suffisante. Nous sommes dans une vision du débat ou il y a un complément entre “réel et virtuel” (virtuel au sens de numérique). Dans ce contexte, il existe déjà des applications et d’autres sont à inventer. Cette hétérogénéité d’outils pose avant tout un problème d’interopérabilité.

Par exemple, on peut concevoir un outil pour aider à constituer un réseau. Ce réseau aura ensuite besoin de discuter en ligne et en présentiel. Il y aura donc besoin d’outils de discussion en ligne mais aussi d’outils d’organisation d’événements. Il faudra à un moment trouver des documents de références et en produire (donc outils d’annotations, de bookmarking et outils de co-rédaction). A certains moments il faudra prendre des décisions (besoin d’outils de vote). Et à chaque phase en présence, il faudra se référer à ce qui a été produit en ligne (outils de production de synthèses) et éventuellement faire part de ce qui a été dit en présence via des outils en ligne pour ceux qui n’ont pas pu venir aux événements présentiels…

Soit on imagine faire un outil monolithique qui englobe toutes les fonctionnalités nécessaires au débat, soit on conçoit des outils indépendants en garantissant des ponts entre ces outils.

Nous avons fait le choix de la deuxième solution parce que cela permet de réintégrer des outils déjà existants, cela permet de travailler plus facilement à plusieurs acteurs (chaque acteur pouvant développer un module indépendant), cela permet de prévoir des environnements modulables et adaptables à des formules de débats différents (comme le dit le CNDP, à chaque débat ses modalités d’action).

Nous allons dans la deuxième partie de cet article traiter d’un début de solution pour l’interopérabilité.

RDF c’est quoi et à quoi ça sert pour les débats?

Maintenant que l’on a fait le constat qu’il n’y avait pas de réelle application existante pour les débats en ligne mais qu’il existe un ensemble d’applications pouvant supporter des processus de débats en présences, il faut penser à l’articulation de ces outils en ligne entre eux et à l’articulation de ces outils avec les phases de débats en présentiel.

Le premier problème que cela pose est celui des formats de représentation des données. Il faut des formats ouverts, facile à comprendre par des programmes et par des humains. RDF nous semble donc être un bon candidat.

Qu’est-ce que RDF ?

RDF est un langage de description de méta-données. Une méta-donnée est une donnée sur une donnée. Par exemple, vous accédez à un document : la date de création de ce document, l’auteur de ce document sont des méta-données.

Sur la page du W3C consacrée à RDF, la première phrase est : RDF est un modèle standard pour l’échange de données sur le web.

La syntaxe de RDF est basée sur des triplets : sujet-prédicat-objet. Ceci permet d’exprimer des relations binaires entre des ressources. Par exemple, sujet:  Natoine, prédicat : est auteur, Objet : de ce document.

RDF permet de représenter des relations entre des ressources.

RDF permet de typer le lien entre des ressources et de typer les ressources. L’exemple précédent devrait être complété de la façon suivante : sujet : Une Personne identifié comme étant Natoine, est lié : par un lien de type “est auteur”, à une ressource objet : ce document qui est un Billet de blog. On sait que Natoine est une Personne, que le lien est de type est_auteur et que le document est un Billet de Blog. RDF utilise des notions de Classes (Personne, Billet de blog, …), de Relations (est auteur) et d’instances (Natoine est une Personne).

Une ressource est identifiée par une URI. Une URI est un identifiant unique, c’est cette unicité qui est importante. Une URL peut-être utilisée en tant qu’URI.

L’un des intérêts de RDF, c’est que grâce à son mécanisme d’identification des ressources, il est possible à plusieurs personnes de créer des méta-données sur une même ressource et il est possible d’aggréger ces différentes méta-données. RDF semble avoir été inventé pour faire des mashups ;) . Par exemple, le site lastfm va créer un descriptif des musiques que j’écoute. Facebook va créer un descriptif de ma liste d’amis. Dans mon blog je crée un ensemble d’articles. Dans delicious je renseigne les pages web que je lie et les tags que j’utilise. Si ces systèmes proposaient tous des exports RDF des données précitées, je pourrai faire des recoupements comme par exemple savoir quels sont mes amis facebook qui me répondent sur mon blog ou les musiques que nous écoutons en commun, les tags communs que nous utilisons…

Concrétement comment fonctionne RDF?

J’ai présenté dans un article précédent de ce blog un cas d’utilisation du vocabulaire FOAF.

Je vais revenir sur cet exemple pour mieux présenter ce que permet de faire RDF.

La spécification de RDF nous apprend que RDF est un langage de description. Si on y regarde de plus prés, RDF est un méta-langage de description, c’est à dire qu’il permet d’écrire des langages de description (aussi appelés vocabulaires).

RDFS (pour RDF schéma) défini les expressions de base du langage RDF. RDFS définit un ensemble de classes et de propriétés. Dans les classes de RDF, on trouve la classe Classe et la classe Property.

En gros RDF permet d’écrire que Personne est une Classe que cette classe a, entre autres, une Propriété est_auteur. RDF permet aussi de préciser que la Propriété est_auteur permet de relier des instances de la classe Personne et des instances de la classe Document (grâce au Range et au Domain).

Bref, RDF permet de définir des vocabulaires, c’est le cas du Vocabulaire FOAF, donc de fournir un descriptif de classes et de relations entre ces classes.

A partir de ce vocabulaire, et toujours avec la même syntaxe, il devient possible d’exprimer des bases de faits. Il est possible grâce à FOAF de décrire un ensemble d’instances de Personne et les relations entre ces personnes.

Pourquoi définir plusieurs Vocabulaires ?

Il faut peut-être revenir sur la définition de ce qu’est une Ontologie. Le but d’un langage de description est de fournir une syntaxe pour écrire une Ontologie.

Une Ontologie, au sens informatique inspiré du sens philosophique, est une description formelle ou semi-formelle du monde.

Le but ultime est donc de pouvoir décrire le monde dans son ensemble, c’est à dire tous les éléments du monde et leurs relations, toutes les règles,  et ce selon tous les points de vue. Mais aussi de pouvoir raisonner (au sens de créer de nouvelles connaissances) à partir de cette description du monde.

Cependant, il faut constater que ce travail est impossible. Une description du monde dans son ensemble est une tâche colossale, le monde est en évolution constante, le point de vue des uns n’est pas toujours compatible avec le point de vue des autres, …

Du coup au lieu de parler d’Ontologie pour représenter le monde dans son ensemble, on préférera parler d’ontologies légéres permettant de représenter une partie bien définie du monde.

Par exemple, le vocabulaire FOAF permet de faire une ontologie des Personnes et de leurs relations. Le vocabulaire Dublin Core permet de faire une ontologie des documents. Et il existe de nombreuses ontologies pour représenter bien des choses différentes.

Quel format de données utiliser pour les débats ?

Le constat est fait, il faut des outils différents pour les différentes phases des débats. Nous proposons d’utiliser RDF pour représenter les données produites par ces débats.

Maintenant, allons-nous proposer un Vocabulaire pour les débats ?

La réponse est non. Comme dit précédement, il existe déjà des outils qui peuvent servir aux débats. Il existe aussi des vocabulaires pour représenter les données produites par ces différents outils.

Nous n’allons donc pas proposer un Vocabulaire unique pour représenter le débat dans son ensemble, nous allons utiliser des vocabulaires existants pour représenter certaines données des débats.

Par exemple, FOAF nous permettra de représenter les liens entre les individus.

SIOC nous permettra de représenter les productions des individus dans des discussions.

Dublin Core et RSS nous permettront de représenter des informations sur les documents de références servant à informer les participants des débats et les documents produits par les débats.

Annotea permettra de représenter des annotations (c’est à dire des liens entre de nouvelles données et des sélections de documents).

Il existe aussi des vocabulaires pour représenter d’autres données comme des événements (cf travail d’état de l’art et LODE de Raphaël Troncy and co), des coordonnées géographiques, des tags (MOAT, NiceTag), …

Nous allons détailler ici des solutions concrétes de représentation des données de la discussion. Pour le reste, il faut bien comprendre que nous nous inscrivons dans cette démarche de choix de vocabulaires pour lesquels il existe des “ponts” vers d’autres vocabulaires. Par exemple, le vocabulaire SIOC définit une classe UserAccount comme étant une sous-classe de OnlineAccount du vocabulaire FOAF. Cette démarche de lier des ontologies les unes aux autres est centrale dans le projet Linking Open Data. Elle accentue encore plus les possibilités d’aggrégations de méta-données sur des ressources.

Concrétement nous représentons quelles informations et comment ?

Profil “minimal” d’un utilisateur

Le profil minimal d’un utilisateur consiste à associer une ressource à un compte utilisateur. Ceci est fait par la classe UserAccount du vocabulaire SIOC.

Un utilisateur en lui-même est représenté par la classe Person de FOAF.

Ceci sert de point de départ à la représentation du réseau social et d’autres informations de profil de l’utilisateur.

Deux exemples suivent ou nous représentons une personne qui posséde un compte utilisateur avec le login Natoine dans la plateforme de débat “debat2.0.org” (plateforme fictive). Le premier exemple part d’une personne et présente l’un de ses comptes. Le deuxième part d’un compte et présente la personne à qui le compte appartient.

<!– Exemple 1 –>

<?xml version =”1.0″ encoding =”utf-8″?>
<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
xmlns:foaf=”http://xmlns.com/foaf/0.1/”
xmlns:sioc=”http://rdfs.org/sioc/ns#”>
<foaf:Person rdf:about=”http://www.natoine.fr/#me” xml:base=”http://www.natoine.fr”>
<foaf:account>
<sioc:UserAccount rdf:about=”http://www.debat20.com/#natoine” rdfs:label=”natoine”>
<!– Autres informations sur le compte –>
</sioc:UserAccount>
</foaf:account>
<!– Autres informations sur la personne –>
<rdfs:seeAlso rdf:resource=”http://www.natoine.fr/natoine.rdf”/>
</foaf:Person>
</rdf:RDF>

<!– Exemple 2 –>

<?xml version =”1.0″ encoding =”utf-8″?>
<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
xmlns:foaf=”http://xmlns.com/foaf/0.1/”
xmlns:sioc=”http://rdfs.org/sioc/ns#”>
<sioc:UserAccount rdf:about=”http://www.debat20.com/#natoine” rdfs:label=”natoine”>
<sioc:account_of>
<foaf:Person rdf:about=”http://www.natoine.fr/#me” xml:base=”http://www.natoine.fr”>
<!– Autres informations sur la personne –>
<rdfs:seeAlso rdf:resource=”http://www.natoine.fr/natoine.rdf”/>
</foaf:Person>
</sioc:account_of>
<!– Autres informations sur le compte –>
</sioc:UserAccount>
</rdf:RDF>

Pour un exemple plus complet, voir mon article de blog sur FOAF.

Deux remarques :

  • la plupart des propriétés sont définies avec leur propriété inverse. Ici, on a montré qu’il existait une propriété foaf:account et une propriété sioc:account_of qui sont l’inverse l’une de l’autre.
  • Il n’est pas obligatoire de donner toutes les informations au sujet d’une instance. Ici j’utilise la propriété rdfs:seeAlso pour renvoyer à un autre document RDF dans lequel je donne plus d’informations sur la ressource. Cette pratique n’est pas obligatoire mais elle est recommandée. Elle permet d’alléger un document RDF et de guider la recherche d’information sur une ressource.

Participation d’un utilisateur

La participation d’un utilisateur est pour l’instant essentiellement représentée par la classe Post de SIOC. Un Post est un élément de discussion comme il est possible d’en émettre dans un blog ou un forum. L’utilisateur est relié à un Post comme en étant l’auteur grâce à la relation has_creator de SIOC. Cette relation lie le Post au UserAccount de la personne.

Le Post est aussi lié au site, ou espace de discussion, dans lequel il a été émis par la relation has_container de SIOC. Un espace de discussion étant représenté par la classe Forum de SIOC. Un commentaire de blog est représenté par la classe BlogPost de l’extension SIOC types, cette classe BlogPost étant une sous-classe de la classe Post. Un BlogPost est contenu par un Blog qui est une classe spécialisant la classe Forum. Il deviendra peut-être nécessaire de définir d’autres classes étendant la classe Forum pour définir de nouveaux espaces de discussion. Mais il existe déjà pas mal de classes intéressantes, comme une classe Wiki, dans l’extension SIOC types. Il y a aussi d’autres classes et propriétés définies dans SWAN.

Bien d’autres informations peuvent être ajoutées à un Post en utilisant des propriétés de SIOC, ou de Dublin Core et RSS (puisque Dublin Core et RSS permettent d’ajouter des informations sur toutes ressources).

Un exemple ou nous représentons deux posts créés par l’utilisateur Natoine, un dans un forum, un dans un blog :

<?xml version =”1.0″ encoding =”utf-8″?>
<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
xmlns:foaf=”http://xmlns.com/foaf/0.1/”
xmlns:sioc=”http://rdfs.org/sioc/ns#”
xmlns:dc=”http://purl.org/dc/elements/1.1/”
xmlns:dcterms=”http://purl.org/dc/terms/”
xmlns:content=”http://purl.org/rss/1.0/modules/content/”
xmlns:siocType=”http://rdfs.org/sioc/types”
>
<sioc:UserAccount rdf:about=”http://www.debat20.com/#natoine” rdfs:label=”natoine”>
<rdfs:seeAlso rdf:resource=”http://www.debat20.com/useraccount?p=natoine”/>
<sioc:creator_of>
<!– Premier Post –>
<sioc:Post rdf:about=”http://www.natoine.fr/blog/?p=437″>
<sioc:has_container>
<siocType:Weblog rdf:about=”http://www.natoine.fr/wordpress/?sioc_type=site#weblog”>
<sioc:name>Main blog at natoine</sioc:name>
</siocType:Weblog>
</sioc:has_container>
<dcterms:created>2010-02-01T15:56:28Z</dcterms:created>
<sioc:content>le commentaire libre version texte simple.</sioc:content>
<content:encoded><![CDATA[ le commentaire libre version HTML ]]></content:encoded>
<sioc:topic rdfs:label=”Programmation” rdf:resource=”http://www.natoine.fr/wordpress/?cat=5″/>
<sioc:topic rdfs:label=”Tutoriels” rdf:resource=”http://www.natoine.fr/wordpress/?cat=4″/>
<sioc:links_to rdf:resource=”http://www.natoine.fr/wordpress/?p=393″ rdfs:label=”tutoriel précédent sur la POO java”/>
<sioc:links_to rdf:resource=”http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html” rdfs:label=”la convention de codage recommandée par sun”/>
<sioc:has_reply>
<sioc:Post rdf:about=”http://www.natoine.fr/forum/?p=444″/>
</sioc:has_reply>
<sioc:reply_of>
<sioc:Post rdf:about=”http://www.natoine.fr/wordpress/?p=398″/>
</sioc:reply_of>
</sioc:Post>
<!– Deuxième Post –>
<sioc:Post rdf:about=”http://www.natoine.fr/forum/?p=444″>
<sioc:has_container>
<sioc:Forum rdf:about=”http://www.natoine.fr/wordpress/?sioc_type=site#forum”>
<sioc:name>Main forum at natoine</sioc:name>
</sioc:Forum>
</sioc:has_container>
<dcterms:created>2010-03-01T15:56:28Z</dcterms:created>
<sioc:content>le commentaire libre version texte simple.</sioc:content>
<content:encoded><![CDATA[ le commentaire libre version HTML ]]></content:encoded>
<sioc:topic rdfs:label=”Programmation” rdf:resource=”http://www.natoine.fr/wordpress/?cat=5″/>
<sioc:topic rdfs:label=”Tutoriels” rdf:resource=”http://www.natoine.fr/wordpress/?cat=4″/>
<sioc:has_reply>
<sioc:Post rdf:about=”http://www.natoine.fr/forum/?p=445″/>
</sioc:has_reply>
<sioc:reply_of>
<sioc:Post rdf:about=”http://www.natoine.fr/blog/?p=437″/>
</sioc:reply_of>
</sioc:Post>
</sioc:creator_of>
</sioc:UserAccount>
</rdf:RDF>

De la même façon que précédemment, puisque il existe des propriétés inverses, il est possible de décrire un site web et l’ensemble des messages qu’il contient. Par exemple, vous pouvez accéder à l’export SIOC des données de ce blog.

La description d’un Post peut déclarer qui en est l’auteur par la relation sioc:has_creator.

Un graphe de discussion

Un graphe de discussion s’obtient en liant des Posts par les status de réponses. Un Post peut être une réponse à un ou plusieurs autres Post par la relation reply_to de SIOC. Un Post peut avoir des réponses par la relation has_reply de SIOC.

Des POSTS peuvent être des réponses les uns aux autres sans nécessairement provenir d’un même espace de discussion.

Il est aussi possible de dire qu’un Post fait référence à une autre ressource par la relation links_to de SIOC.

Documents de référence

Les documents de référence sont des ressources web HTML ou vidéo ou audio. En utilisant les vocabulaires Dublin Core et RSS, on peut décrire la plupart des informations utiles sur ces documents comme qui en est auteur, le contenu, la date de mise en ligne … On peut éventuellement utiliser la classe Document de FOAF. Si le document est d’une autre ressource que texte, il est possible d’utiliser d’autres vocabulaires comme le vocabulaire Media et ses extensions Video et Audio.

Plutôt que de détailler des exemples ici, je vous invite à consulter un exemple simple sur le site de Dublin Core et un exemple de RSS1.0 utilisant le module Dublin Core.

Annotations

Les annotations telles que nous les définissons recouvrent toute pratique visant à ajouter des données sur des documents ou des sélections de documents.

On peut alors considérer un Post sur un blog comme étant une annotation d’article de blog, un Post sur un forum comme étant une annotation de la discussion dans son ensemble ou du Topic de celle-ci.

Les annotations faisant référence à des pratiques classiques de discussion sur le web comme les blogs ou forums ont été présentées précédemment.

Nous allons ici détailler un type d’annotations : les annotations portant sur des sélections de document.

Nous nous basons sur le vocabulaire Annotea pour représenter ce type d’annotations.

Les éléments important à représenter dans une annotation :

  • L’annotation en elle-même, représentée par la classe annotea:Annotation
  • La ressource annotée, liée à l’annotation par la propriété annotea:annotates
  • L’emplacement exact annoté, ou la sélection de la portion de ressource annotée, lié à l’annotation par la propriété annotea:context.
  • Le corps de l’annotation, ou la nouvelle information apportée par l’annotation, liée à l’annotation par la propriété annotea:body.

Dans le cas d’une ressource HTML annotée, l’emplacement exact, la sélection est précisée par l’utilisation d’un XPointer.

Dans notre cas, la plupart des annotations que nous représentons sont dites discursives. Les informations ajoutées à des portions de documents sont des commentaires saisis par les utilisateurs dans le cadre d’une discussion. Je vous renvoie à la thèse de Gaëlle Lortal pour en savoir plus sur l’annotation discursive. Dans ce contexte, nous avons choisi de représenter le corps de l’annotation par la classe Post de SIOC.

Un exemple d’annotation discursive :

<?xml version =”1.0″ encoding =”utf-8″?>
<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
xmlns:sioc=”http://rdfs.org/sioc/ns#”
xmlns:dc=”http://purl.org/dc/elements/1.1/”
xmlns:annotea=”http://www.w3.org/2000/10/annotation-ns”
>
<annotea:Annotation rdf:about=”http://www.natoine.fr/annotation/?p=479″>
<annotea:annotates rdf:resource=”http://www.jeanSallantin.fr/homepage”/>
<annotea:body>
<sioc:Post rdf:about=”http://www.natoine.fr/wordpress/?p=401″ dc:title=”IPC ou communication inter portlet 2. JSR286″>
<rdfs:seeAlso rdf:resource=”http://www.natoine.fr/wordpress/index.php?sioc_type=post&amp;sioc_id=401″/>
</sioc:Post>
</annotea:body>
<annotea:context>
http://www.jeanSallantin.fr/homepage#xpointer(id(”Main”)/p[2])
</annotea:context>
</annotea:Annotation>
</rdf:RDF>

Nous ne développons pas dans cet article de blog le cas des annotations de type Tag. Il existe actuellement plusieurs solutions pour représenter les tags.

Par exemple, s’il s’agit d’un domaine auquel la ressource fait référence, on peut utiliser la propriété topic de SIOC, on peut aussi dans ce cas utiliser la classe Concept de SKOS, il est possible de désambiguïser le sens d’un tag en faisant référence à une définition de wikipédia en passant par l’ontologie MOAT. Enfin, il existe un vocabulaire Nice Tag Ontology permettant de préciser le sens d’une action de tagging.

A ce sujet, je vous recommande de suivre les travaux de Freddy Limpens et Alexandre Monnin. Nous sommes encore en train de travailler sur l’utilisation des résultats de ces travaux dans notre contexte.

Ce qu’il manque !!!

Nous venons de voir plusieurs données qu’il est essentiel de représenter pour des débats en ligne. Cependant, il en manque encore.

En particulier, il n’est pas encore possible de représenter une opinion ou de typer un Post (c’est un contre-argument, une conclusion, …). Et ceci est central comme exposé précédemment. Le travail du VoCamp à Paris donne pas mal de pointeurs sur ce sujet, notamment des vocabulaires comme ARGDF. Enfin, les travaux sur NiceTag sont trés prometteurs à ce sujet. Cependant, NiceTag se concentre essentiellement sur le sens de l’activité de tagging et non sur l’activité d’annoter. Il est possible de dire qu’un tag exprime un désaccord en spécialisant la relation nt:isRelatedTo. Mais il n’est pas encore possible de dire qu’une annotation discursive exprime un désaccord.

Pour l’instant j’entrevois deux possibilités :

  • soit on ajoute dans le corps d’une annotation une action de tagging exprimant le désaccord. Mais ceci créera une redondance d’information. Une action de tagging lie la ressource taggée à la ressource représentant le tag par la propriété isRelatedTo. Il faudrait donc répéter l’information de quelle ressource est taggée alors que celle-ci est déjà exprimée par la propriété annotates de l’annotation.
  • soit les vocabulaires NiceTag et Annotea évoluent. Pour ma part je considére qu’une action de tagging est un cas particulier d’une action d’annotation. Il me semble qu’alors la propriété isRelatedTo est une propriété inverse et plus spécialisée de la relation annotates … Piste à suivre ;)

Il n’existe pas à ma connaissance de vocabulaire définissant une classe Debate.

Je n’ai pas présenté de solutions permettant de représenter les groupes d’opinion ou stakeholders (parties prenantes). Il est sûrement possible d’utiliser des notions de groupes comme celles présentées dans FOAF. Dans ces groupes, il serait sûrement intéressant de représenter les rôles de chacun. Ceci pose la question de la légitimité de la prise de parole au nom d’un groupe. Est-ce que n’importe qui membre d’un groupe s’exprime nécessairement au nom de ce groupe ?

Enfin, je ne discute pas de la nature des ressources (ce qui est identifié par une URI). C’est à dire que je ne discute pas du fait qu’une ressource soit accessible par le web ou non (voir l’ontologie IRW à ce sujet). Du coup, il serait intéressant de se demander ce que peut être une annotation sur une ressource comme la tour eiffel par exemple (la tour eiffel a une URI, donc est une ressource, mais n’est pas accessible par le web).

Bien entendu le travail de représentation des débats n’est pas fini. Ce que je propose ici est l’utilisation de vocabulaires existant pour une représentation de l’activité d’un réseau social au cours d’une discussion. Je m’appuie beaucoup sur les propositions de A.Passant dans sa thèse. Essentiellement, je n’ai fait qu’ajouter le lien entre les annotations d’Annotea et les Post de SIOC.

Niveaux d’accès et syntaxe Java

Lundi 1 février 2010

Enfin nous allons faire ce point tant attendu sur les niveaux d’accès en Java. Youpi !!!

Nous en profitons aussi pour faire un point syntaxe java.

La première partie de ce tutoriel vient en complément du tutoriel précédent sur la POO java. Dans le tutoriel précédent,vous avez pu voir comment déclarer des classes. Dans ce tutoriel, vous allez voir comment déclarer des attributs et des méthodes dans une classe et comment définir leurs niveaux de droit d’accès. En gros, comment écrire le corps d’une classe. Nous serons obligés pour être complet de présenter les règles d’écriture des “identifiers”. Ces mots qui vont vous permettre de nommer vos classes et vos variables. Nous ferons un tour des types primitifs en java, ça peut toujours servir. Puis pour être complet sur la syntaxe java, nous ferons un point sur les conditionnelles (if, while, for, …).

Corps de classe Java

Attributs

Les attributs, ou variables de classes, définissent un ensemble d’indicateurs de l’état des objets.

La classe définit les attributs et leurs types.

Un objet (instance de classe) a effectivement une liste d’attributs associés, ce sont des instances des attributs déclarés dans la classe. L’ensemble de ces valeurs définit l’état de l’objet, on les appelle d’ailleurs aussi variables d’état.

Les attributs sont typés. Ils peuvent être de type primitif ou être des objets.

La syntaxe pour déclarer un attribut est : le modifier de droit d’accés, le type de l’attribut, le nom de l’attribut. [modifier] [type] [nom de l'attribut] ;

exemple :

private int id ;

Eventuellement, vous pouvez aussi associer une valeur à l’attribut. Ce sera la valeur de l’attribut lors de l’instanciation d’un objet de la classe (sauf si vous modifiez cette valeur dans le constructeur) :

exemple :

private int id = 0 ;

Les modifiers d’accés permettent d’associer un droit d’accés à un attribut. Nous détaillerons les différents modifiers et leurs effets un peu plus loin dans ce tutoriel.

Méthodes

Les méthodes sont déclarées dans les classes, elles définissent le comportement des objets.

Elles peuvent être appelées par un objet, la syntaxe d’appel étant : monObjet.maMethode(param1, param2, …);

Lors de l’appel d’une méthode, celle-ci renvoie “quelque chose”. Cette “chose” peut être un objet, une valeur ou rien. Il faut donc préciser le type de ce qui est renvoyé par une méthode. Si la méthode ne renvoie rien, on utilise le mot clef void.

La syntaxe de déclaration d’une méthode est : le modifier de droit d’accés, le type de retour de la méthode,  le nom de la méthode, les paramètres entre parenthéses, le corps de la méthode entre accolades.

[modifier] [nom méthode] ( [type][param1] , [type][param2] , [type][param3], …, [type][param n]) { [corps de méthode] }

Pour dire dans le corps de la méthode de renvoyer quelque chose, on emploie le mot clef return.

exemple :

public int getId() { return id; }

public void setId( int nouvel_id ) { id = nouvel_id ; }

Pour préciser que l’on fait référence à l’id de notre objet, j’aurai pu écrire this.id au lieu de id. Mais dans ce cas, il n’y a pas de confusion possible, donc this n’est pas nécessaire.

exemple :

public int getId() { return this.id; }

public void setId( int nouvel_id ) { this.id = nouvel_id ; }

Surcharge et re-définition de méthodes

L’opération de surcharge consiste à définir plusieurs méthodes ayant le même nom dans une même classe. Ces méthodes peuvent avoir des types de retour identiques ou différents. Par contre, il est obligatoire que le nombre ou le type des paramètres change.

L’opération de re-définition de méthodes concerne l’héritage et consiste à redéfinir dans une classe fille une méthode déjà définie dans une classe mère.

Droits d’accès

Nous allons maintenant présenter les différents modifiers et les droits d’accés qu’ils permettent de définir. Nous ne traitons ici que des modifiers d’accés.

Les modifiers d’accés sont :

  • default
  • public
  • private
  • protected

Nous avons déjà vu dans les tutoriels précédents l’utilisation de default et public dans le cas de déclaration de classes. Encore une fois, default et public sont les seuls modifiers d’accés possibles sur des classes.

Effet des modifiers d’accés sur des classes

  • default : c’est le niveau d’accés par défaut. Ne pas utiliser de modifier d’accés ou utiliser le modifier default revient au même. Une classe d’accés par défaut n’est visible que par les autres classes de son package.
  • public : Une classe d’accés public est visible par toutes les autres classes.

Effet des modifiers sur les membres (attributs et méthodes) d’une classe

  • default : est le niveau d’accés par défaut. Ne pas utiliser de modifier ou utiliser le modifier default revient au même. Un membre déclaré de niveau d’accés par défaut est visible dans la classe et dans toute classe du même package.
  • public : Tout membre déclaré public appartenant à une classe A, est visible par toute classe qui a accés à la classe A.
  • private : Tout membre déclaré private n’est visible que dans la classe ou il est déclaré. Soulignons que ceci est vrai même par héritage. Soit une classe A dont un membre est private. Une classe B hérite de A. La classe B n’hérite pas des membres private. Redéclarer dans la classe B un membre qui est présent et private dans A n’est ni une surcharge ni une re-définition.
  • protected : Un membre déclaré protected est visible dans la classe, dans toute classe du même package et par héritage dans toute classe fille. Soit une classe A dont un membre est protected. La classe B hérite de A. La classe B hérite le membre protected de A.

Autres Modifier

Nous allons traiter ici de quelques autres modifiers bien utiles: final, abstract et static.

Il faut retenir qu’il est possible d’associer plusieurs modifiers à une déclaration (que ce soit une classe ou un membre). Bien sûr, on ne peut utiliser qu’un seul modifier d’accés. Mais on peut faire des combinaisons avec les autres modifiers.

On peut par exemple déclarer un membre static et final et public.

  • final : Une classe marquée final ne pourra pas être héritée (pas de classes filles possible). Une méthode marquée final ne peut pas être redéfinie dans une classe fille. Une variable marquée finale ne pourra pas avoir une nouvelle valeur assignée. Marquer un attribut comme étant final revient à définir une constante. Marquer un paramètre final dans une déclaration de méthode revient à garantir que la méthode ne pourra pas modifier la valeur de ce paramétre.
  • abstract : Abstract ne s’utilise que sur les classes et les méthodes. Une classe marquée abstract est dite abstraite, elle ne peut pas être instanciée (on ne peut pas faire d’objet par appel à new de cette classe). Une méthode abstraite n’a pas de corps (pas de définition) et une classe ayant une méthode abstraite doit nécessairement être abstraite. Les classes et les méthodes abstraites sont utiles dans un contexte d’héritage. Elles permettent de déclarer des classes d’un niveau d’abstraction élevé. Une classe héritant d’une classe abstraite doit implémenter toutes les méthodes abstraites héritées, à moins d’être elle-même abstraite.
  • static : Une méthode ou un attribut marqué static existe indépendamment de toute instance de classe. On dit souvent que toutes les instances d’une classe partagent les mêmes membres static. En fait, c’est pire que ça. Un membre static est unique quelquesoit le nombre d’instances de la classe et il existe même si il n’y a aucune instance de cette classe.

Identifiers

Nous allons ici présenter les éléments de syntaxe essentiels pour les identifiers. Les identifiers étant les noms de variables (variables de classe, paramétres, variables locales), les noms de méthodes, les noms de classe.

Nous nous en tenons ici à ce qu’il est possible ou impossible de faire. Mais il existe beaucoup de bonnes pratiques ou conventions de codage que nous vous invitons à connaître et adopter : les javabeans (nous leur consacrerons un tutoriel) et la convention de codage recommandée par sun.

Il existe un plugin eclipse, check style qui vous permet de définir une convention de codage et de faire contrôler par eclipse que vous la respectez bien.

Il existe un ensemble de règles de bases (dites légales) à connaître concernant le nommage de classes, variables et méthodes.

Règles générales sur les identifiers :

  • il est interdit de réutiliser un mot-clef java pour nommer une classe, une variable ou une méthode (vous ne pourrez pas appeler une variable void par exemple, ou public).
  • les identifiers ne doivent être composés que de caractères unicodes, de nombres, de symboles monétaires, et de caractères de liens (”_” par exemple mais pas “-”).
  • les identifiers doivent commencer par une lettre, un symbole monétaire ou un caractère de lien.
  • les identifiers ne doivent pas commencer par un nombre.
  • les identifiers sont sensibles à la casse.

Nommage de classes

  • il ne peut y avoir qu’une seule classe public par fichier java. Le fichier java doit porter le même nom que cette classe public.

La règle suivante n’est qu’une convention. Mais même eclipse vous rappelera à l’ordre si vous ne la respectez pas.

  • le nom d’une classe commence par une majuscule. Si le nom d’une classe est la concaténation de plusieurs mots, la première lettre de chaque mot devrait être en majuscule.

Nommage de variables et constantes

Ce sont aussi des conventions.

  • le nom d’une variable commence par une minuscule.
  • le nom d’une constante est en majuscule et on utilise un “_” pour séparer les mots constituants le nom de la constante.

Nommage de méthodes

C’est encore une convention.

  • la premièe lettre d’une méthode est une minuscule. Ensuite chaque mot commence par une majuscule. En règle générale, on essaye d’utiliser des verbes.

Types primitifs

Les types primitifs en java sont représentés par des mots-clefs commençant par une minuscule. Le type String par exemple n’est pas un type primitif, c’est une classe héritant de Object.

Certaint types primitifs ont des équivalents objets comme int et Integer par exemple. La conversion entre int et Integer étant aisée et permettant de traiter des variables de type primitif comme des objets et vice versa.

Vous retrouverez ces informations sur la page de sun sur les types primitifs.

La liste des types primitifs :

  • byte : codé sur 8 bits signés. Permet de représenter un entier entre -128 et 127 inclus.
  • short : codé sur 16 bits signés. Permet de représenter un entier entre -32 768 et 32 767 inclus.
  • int : codé sur 32 bits signés. Permet de représenter un entier entre -2 147 483 648 et 2 147 483 647 inclus.
  • long : codé sur 64 bits signés. Permet de représenter un entier entre -9 223 372 036 854 775 808 et 9 223 372 036 854 775 807 inclus.
  • float : Permet de représenter un nombre décimal avec une précision sur 32 bits.
  • double : Permet de représenter un nombre décimal avec une précision sur 64 bits.
  • boolean : Permet de représenter un booléen. Prend les valeurs true ou false.
  • char : Permet de représenter un caractère unicode codé sur 16 bits.

Les conditionnelles en Java

Nous présentons ici les syntaxes de la plupart des conditionnelles Java. Sun les appelle les “control flow statements”, et leur consacre une partie de son tutoriel.

Les conditionnelles sont des sentences qui permettent de ne pas faire uniquement des exécutions linéaires du code. En règle générale, une ligne de code correspond à une instruction. Les instructions s’exécutent donc dans leur ordre d’apparition dans le code.

Les conditionnelles peremettent de casser cette linéarité en mettant en place des tests conditionnels (if then else) ou des boucles (for, while).

Il n’y a que deux conditionnelles à connaître : if et for.

A partir de ces deux conditionnelles toutes les autres peuvent être définies.

  • if then else : permet de décrire une exécution de code ou une autre en fonction du résultat d’un test. Si le test est vrai exécuter ce code, si le test est faux, exécuter cet autre code.
  • for : permet de mettre en place une boucle d’exécution. Pour chaque élément de cette liste, exécuter ce code. Donc exécuter n fois ce code.

Exemple de if then else :

if( test )

{

System.out.print(”test vrai”);

}

else

{

System.out.print(”test faux”);

}

il est possible d’enchaîner les tests de if. Par exemple :

if ( id== 0)

{

System.out.print(”id = 0″);

}

else if (id == 1)

{

System.out.print(”id=1″);

}

else …

Il est aussi possible de ne pas préciser de else si on a aucun code alternatif à faire exécuter.

Exemple de for :

for (int i =0 ; i< 5 ; i++)

{

System.out.print( ” tour n°” + i );

}

Cette boucle s’exécutera 5 fois et affichera : tour n°0 tour n°1 tour n°2 tour n°3 tour n°4

Les autres :

  • switch : Cette conditionnelle revient à écrire un ensemble de tests if sur la valeur d’une variable.
  • while : Cette boucle s’exécute tant qu’un test est vrai. Très pratique pour créer des boucles infinies.
  • do-while : C’est l’utilisation inverse de la boucle while. Au lieu de dire “tant que ce test est vrai, faire cette action”, on dit “faire cette action tant que ce test est vrai”.

Exemple de switch :

soit un int month représentant un mois. Le code suivant permet de tester la valeur de month et d’afficher le mois en lettres en fonction de sa valeur numérique.

switch(month)

{

case 1:  System.out.println("January"); break;
case 2:  System.out.println("February"); break;
case 3:  System.out.println("March"); break;
case 4:  System.out.println("April"); break;
case 5:  System.out.println("May"); break;
case 6:  System.out.println("June"); break;
case 7:  System.out.println("July"); break;
case 8:  System.out.println("August"); break;
case 9:  System.out.println("September"); break;
case 10: System.out.println("October"); break;
case 11: System.out.println("November"); break;
case 12: System.out.println("December"); break;
default: System.out.println("Invalid month.");break;

}

Le mot clef case permet de préciser “si month prend cette valeur alors faire tout ce qui suit”.

Le mot clef default revient à dire “si la valeur n’est pas prise en compte par un case alors faire …”.

Le mot clef break permet de dire qu’il faut s’arréter là ou break est rencontré. En réalité, case dit c’est à partir d’ici qu’il faut exécuter. Et s’il n’y a pas de break, le code des case suivant est aussi exécuté.

Par exemple dans notre cas précédent, s’il n’y avait pas de break et avec month = 10, il serait affiché : October November December Invalid month.

Nous revenons sur break dans les interrupteurs de boucles.

exemple de while :

while (true)

{

System.out.println(”toto”);

}

C’est un exemple de boucle infinie. Le test de notre while est un booléen vrai. Donc le corps du while sera exécuté à l’infini. Ce genre de code peut-être dangereux et très pratique. Très dangereux parce que l’on peut facilement faire une boucle infinie sans le vouloir. Mais parfois on a besoin de boucles infinies. Quand on veut garder des processus atifs par exemple.

Un exemple de do while :

do

{

System.out.println(”toto”);

}

while(false)

C’est l’exemple inverse du cas précédent. Ici “toto” sera affiché une fois uniquement. Le test du while étant faux, la boucle ne sera pas exécutée.

La grande différence entre while et do-while est que dans le cas du do-while, le test est exécuté à chaque fin de tour et non au début. Du coup, le corps de do est exécuté au moins une fois.

Les interrupteurs de boucles :

  • break : permet d’interrompre l’exécution d’une boucle. A la rencontre d’un break, la boucle est interrompue.
  • continue : permet de finir un tour d’exécution de boucle. A la rencontre de continue, on passe au tour suivant d’exécution de la boucle.
  • return : permet d’interrompre l’exécution d’une méthode et retourne une variable ou une valeur. return peut donc aussi être utilisé pour sortir d’une boucle, mais il terminera aussi l’exécution de la méthode dans laquelle la boucle est définie.

Nous en avons fini avec ce tutoriel sur la syntaxe et les niveaux de droits d’accés. Il ne vous reste plus qu’à pratiquer.

Dans la suite des tutoriels, nous allons nous orienter vers des composants logiciels java orientés pour du web essentiellement.

Il nous reste un cours sur les javabeans pour présenter une convention de nommage incontournable dans le monde professionnel. Un cours sur les Enums, qui permettent de définir des structures très utiles principalement pour le traitement de String.

Puis nous définirons un environnement de production qui nous semble otpimal pour des développements web (un ensemble de plugins eclipse, l’utilisation de Maven, et le framework hibernate).

Enfin, nous détaillerons les composants qui nous intéressent le plus, à savoir les Servlet et les Portlet.

Programmation Orientée Objet en JAVA

Dimanche 24 janvier 2010

Dans cet article, second de la série de nos tutoriels sur java, nous vous proposons une petite introduction à la POO (Programmation Orientée Objet). Il existe de nombreux tutoriels sur ce sujet. Nous essayons ici de rester simple et concis. Nous présenterons un exemple complet après un rapide cadre théorique.

Nous recommandons les excellents tutoriaux de sun à ce sujet.

Un peu de Théorie

Sur Wikipedia, on trouve cette définition :

La programmation orientée objet (POO) ou programmation par objet, a été élaborée par Alan Kay dans les années 1970. C’est un paradigme de programmation informatique qui consiste en la définition et l’interaction de briques logicielles appelées objets.

Qu’est-ce qu’un objet ? C’est une représentation informatique d’une entité physique ou d’une idée. Un objet est caractérisé par des attributs et des méthodes. On parle aussi de variables d’état (permettant de caractériser l’état de l’objet) et de comportements. Un objet est aussi une instance d’un modèle. Le modèle, que l’on appelle une Classe, représente donc un concept. Une classe est un descripteur des objets, elle va préciser quels sont les attributs (et les valeurs que ces attributs peuvent prendre) et méthodes de l’objet.

L’une des motivations de la programmation Objet est la réutilisabilité. Le but est que des classes définies pour un projet puissent être réutilisées dans d’autres sans avoir pour autant à comprendre le mécanisme interne de ces classes. Pour cela, deux notions importantes : celle d’interface et celle d’héritage.

Dans cette optique de réutilisabilité, il est important de souligner la possibilité de communiquer la signature d’une Classe. La signature d’une classe est sa description, la liste de ses attributs, la liste de ses méthodes. Cette description permet à tout un chacun de savoir comment peut être utilisé un objet d’une classe, comment on peut interagir avec un objet (certains diront “comment on peut communiquer avec cet objet”, pour moi on leur donne des ordres tout au plus, ce n’est pas une véritable communication). La signature permet de voir une Classe et ses instances comme une sorte de boîte noire dont on ne connait que les points d’entrées et de sorties. Ces signatures peuvent être commentées et publiées, c’est le cas de l’api en ligne ou javadoc.

C’est dans cette optique de signature qu’ont été définies les interfaces. On dit d’une interface que c’est un contract entre la classe et le monde extérieur. Une interface décrit exactement une signature mais restreinte à un ensemble de méthodes. Et une interface ne définit en aucun cas le fonctionnement de ses méthodes. Une classe qui implémente une interface garantit donc que tous les objets instances de cette classe ont une méthode qui s’appelle de cette façon et qui renvoie ce type de résultat.

L’héritage est la possibilité de spécialiser ou généraliser les Classes. Prenez une classe A avec ses attributs et ses méthodes. Une classe B doit avoir les mêmes attributs et méthodes mais avec quelques éléments en plus. On dit que B spécialise A. On peut alors grâce à l’héritage dire explicitement B est identique à A avec ces éléments supplémentaires. L’héritage permet d’économiser du code. Il est aussi possible de redéfinir l’une des méthodes de A dans B. Ainsi, B a bien une méthode portant le même nom que celle de A mais elle ne fait pas le même traitement. En gros, une ferrari et une deux chevaux sont toutes les deux des voitures qui peuvent accélérer mais pas de la même façon. Il est important de retenir que tout objet instance de B est aussi instance de A. C’est ce que l’on appelle le polymorphisme.

Dernier point sur l’héritage : dans certains langages, il est possible de faire de l’héritage multiple. L’héritage multiple consiste à dire : soit deux classes distinctes (non liées par héritage) A et B, une troisième classe C peut hériter de A et de B. C’est à dire que C hérite toutes les méthodes et attributs de A et de B. Il n’est pas possible en Java de faire de l’héritage multiple. Cependant, il est possible d’implémenter plusieurs interfaces.

Concrétement on fait comment ?

De nombreux tutoriaux existent ou on vous fera coder des voitures ou des distributeurs de billets. Vous en trouverez de très bons sur développez par exemple.

Ici, nous allons nous contenter de l’essentiel. Comment on écrit une classe, comment on hérite d’une classe, comment on déclare une interface, comment on implémente une interface, et enfin comment une interface hérite d’une autre.

Je vous recommande de lire notre premier tutoriel débuter java. Nous ne détaillons toujours pas dans ce tutoriel tous les usages de tous les mots clefs java liés aux niveaux de droits d’accés. Nous consacrerons un tutoriel à ce sujet.

Avant de commencer, je voudrais insister sur l’ambiguité du mot objet. On l’utilise souvent à tort et à travers. On ne sait plus vraiment si on désigne une classe ou une instance de classe avec le mot objet. L’existence d’une classe Object en java n’aide pas à lever cette ambiguité. Donc une bonne fois pour toute : un objet est une instance d’une classe.

Définition d’une classe

Avant tout un petit rappel sur les classes en Java:

  • On peut déclarer autant de classes que l’on souhaite dans un fichier java.
  • On ne peut déclarer qu’une seule classe public.
  • Le fichier doit porter le même nom que la classe public s’il y en a une.
  • S’il n’y a pas de classe public dans le fichier, le nom du fichier n’a pas d’importance.

Il faut aussi noter qu’une classe en Java est censée faire partie d’un package. Ceci n’est pas obligatoire mais c’est une bonne pratique. Dans Eclipse par exemple, quand vous créez une classe sans la mettre dans un package, celle-ci est placée dans un package par défaut (default package).

Donc en règle générale, un fichier .java débute par une ligne de déclaration de package, par exemple pour signaler que les classes de ce fichier sont dans le package tutoriels lui même inclus dans le package natoine, on écrira :

package natoine.tutoriels;

Un point sur les différents niveaux de droits d’accés pour les classes. Celles-ci peuvent avoir comme droit d’accés : default ou public.

  • default : Le niveau d’accés par défaut. Dans ce cas, la classe n’est visible que par les autres classes de son package.
  • public: Le niveau d’accés publique. C’est à dire qu’elle est visible par toutes les autres classes, même les classes qui ne sont pas du même package.

Pour indiquer qu’une classe est de niveau d’accés par défaut ou publique, on utilise des mots-clefs que l’on appelle des modifiers. Le mot-clef pour le niveau par défaut est default, celui pour publique est public. En ce qui concerne le niveau d’accés par défaut, le mot-clef n’est pas indispensable. Ne rien mettre ou mettre le modifier default revient au même.

Pour déclarer une classe, on utilise le mot-clef class. Par convention, le nom d’une classe commence par une majuscule.

Déclaration d’une classe d’accés par défaut DefaultClass :

class DefaultClass

ou bien :

default class DefaultClass

Déclaration d’une classe d’accés publique PublicClass :

public class PublicClass

Ensuite il faut ouvrir le corps de la définition de la classe par une acolade puis refermer cette acolade une fois la définition finie.

Héritage de classe

Pour hériter d’une classe, il faut utiliser le mot-clef extends. Par exemple nous allons faire un classe ExtendDefaultClass :

public class ExtendDefaultClass extends DefaultClass

Vous remarquerez que vous êtes obligés de mettre cette nouvelle classe dans le même package que DefaultClass. Sinon, la classe DefaultClass ne sera pas visible.

A l’opposé si nous faisons unc classe ExtendPublicClass qui hérite de la classe PublicClass, nous pouvons la mettre dans un autre package que celui contenant la classe PublicClass.

Il reste deux modifiers important à aborder concernant la définition de classes. Ces mots-clefs sont final et abstract :

  • final : Le modifier final indique que la classe ne peut pas avoir de classe fille. Aucune classe ne pourra hériter d’une classe marquée final.
  • abstract : Le modifier abstract permet de déclarer une classe comme étant abstraite. Une classe abstraite ne peut pas être instanciée, sa seule raison d’être est d’être héritée. Notez qu’une classe abstraite n’est pas obligée de déclarer des méthodes abstraites. Par contre, une classe déclarant une méthode abstraite doit nécessairement être une classe abstraite.

Déclarons une classe final FinalExtendDefaultClass qui hérité de DefaultClass :

final class FinalExtendDefaultClass extends DefaultClass

Déclarons une classe abstraite AbstractPublicClass qui hérite de la classe PublicClass :

public abstract class AbstractPublicClass extends PublicClass

Implémentation d’une interface

Pour déclarer une interface, il faut utiliser le mot-clef interface. Les interfaces comme les classes peuvent être accessible par défaut ou publique. Elles suivent les mêmes règles de droit d’accés et les modifiers d’accés sont les mêmes (default, public).

L’intérêt d’une interface est de préciser des méthodes à obligatoirement implémenter. Une classe implémentant une interface doit nécessairement implémenter les méthodes de cette interface.

Pour l’exemple, nous allons déclarer une interface publique PublicInterface avec une méthode printName().

public interface PublicInterface
{
void printName();
}

Petite remarque au sujet des méthodes d’une interface (pour ceux qui ont pris de l’avance concernant les droits d’accés des méthodes) : elles sont abstraites et publiques obligatoirement. Elles sont nécessairement publiques parce que sinon, elles ne seraient pas visibles par les classes qui doivent les implémenter. Et elles sont abstraites parce que chaque classe doit définir leur implémentation et l’interface ne suppose rien d’autre au sujet des classes (l’interface ne sait pas quels sont les attributs des classes l’implémentant ni les autres méthodes).

La méthode printName aurait pu être écrite de la façon suivante, cela revient au même :

public abstract void printName();

Pour qu’une classe implémente une interface, il faut utiliser le mot-clef implements et bien sur, déclarer et implémenter les méthodes de l’interface en question. Par exemple, nous allons déclarer une classe publique PublicClassImplementPublicInterface.

public class PublicClassImplementPublicInterface implements PublicInterface
{
public void printName()
{
System.out.println(”PublicClassImplementPublicInterface”);
}
}

Si une classe doit implémenter plusieurs interfaces, il suffit de séparer chaque nom d’interface par une virgule.

Une classe peut hériter d’une autre classe et implémenter une ou plusieurs interfaces. Dans ce cas, le mot clef extends et la déclaration de la classe mère précéde le mot-clef implements et la liste des interfaces. Par exemple :

public class PublicClassExtendsImplements extends AbstractPublicClass implements PublicInterface

Héritage d’interface

Il est possible pour une interface d’hériter d’une autre interface. Il suffit de préciser l’interface héritée par le mot-clef extends.

Déclarons une interface InterfaceExtendsPublicInterface qui hérite de notre interface précédente PublicInterface :

public interface InterfaceExtendsPublicInterface extends PublicInterface
{
void printInterfaceList();
}

Cette interface n’a pas à redéclarer les méthodes héritées par ses interfaces mères mais les classes implémentant cette interface devront les implémenter.

Instanciation de classe

Instancier un objet se fait simplement par l’utilisation du mot clef new. Par exemple, instancions un objet de la classe PublicClassImplementInterface:

new PublicClassImplementPublicInterface();

Lors de l’appel à new PublicClassImplementPublicInterface(), un nouvel objet de la classe PublicClassImplementPublicInterface est construit. Cette construction fait appel au constructeur de la classe PublicClassImplementPublicInterface.

Dans notre exemple, nous n’avons pas défini de constructeur dans la classe PublicClassImplementPublicInterface. Du coup, le constructeur appelé est celui de la classe dont hérite PublicClassImplementPublicInterface. Si celle-ci ne définit pas de constructeur non plus, le constructeur appelé est celui de la classe mère de la classe dont hérite PublicClassImplementPublicInterface. Etc jusqu’à la classe Object qui elle déclare bien un constructeur.

En java, il existe une super classe, la classe Object. Toutes les classes que vous définirez héritent donc de cette classe Object et ce sans avoir à utiliser le mot-clef extends.

Nous allons maintenant déclarer une classe FinTutoClass qui elle déclare un constructeur. Un constructeur de classe doit porter le même nom que la classe et se déclare de la même façon qu’une méthode à part qu’il n’a pas de type de retour. Afin de bien finir ce tutoriel, cette classe FinTutoClass hérite de la classe PublicClassExtendsImplements et implémente l’interface InterfaceExtendsPublicInterface.

public class FinTutoClass extends PublicClassExtendsImplements implements InterfaceExtendsPublicInterface
{
public FinTutoClass()
{
super();
}
public void printInterfaceList()
{
for(Class _interface : this.getClass().getInterfaces())
{
System.out.println(” ” + _interface.getSimpleName());
}
}
}

Encore une fois, le constructeur peut avoir le même niveau de droits que toute méthode (donc default, public, private ou protected).

L’utilisation de super(); signifie que le constructeur a le même comportement que le constructeur de la classe mère. Ensuite il est toujours possible d’ajouter d’autres instructions. En réalité, super() est appelé dans tous les cas.

Maintenant nous allons consacrer la fin de ce tutoriel au polymorphisme. Nous allons écrire une classe MainClass avec une méthode main afin de pouvoir l’exécuter. Les questions auxquelles nous allons tenter de répondre sont : quelle est la nature (ou le type) de notre objet? Peut-il changer de nature?

Cette dernière partie va nous permettre d’introduire l’opération de casting d’une classe. Le casting d’une classe (on dit que l’on caste un objet d’une classe) consiste à demander à un objet d’agir en tant qu’objet d’un autre type que celui déclaré lors de sa construction. Il est possible de caster l’objet selon les classes dont il est instance (c’est à dire la classe déclarée lors de l’appel à new et toutes les classes méres) et selon les interfaces qu’il implémente.

Le contenu de la classe MainClass :

public class MainClass {
public static void main(String[] args)
{
FinTutoClass _object = new FinTutoClass();
_object.printInterfaceList();
_object.printName();
System.out.println(_object.getClass().getSimpleName());
System.out.println(((PublicClassExtendsImplements)_object).getClass().getSimpleName());
PublicClassExtendsImplements _object2 = new FinTutoClass();
_object2.printName();
((FinTutoClass)_object2).printInterfaceList();
System.out.println(_object2.getClass().getSimpleName());
PublicInterface _object3 = new FinTutoClass();
_object3.printName();
((InterfaceExtendsPublicInterface)_object3).printInterfaceList();
InterfaceExtendsPublicInterface _object4 = new FinTutoClass();
_object4.printInterfaceList();
_object4.printName();
}
}

Que fait-on dans ce main?

  • Le début est simple : on crée un objet _object de type FinTutoClass en appelant le constructeur de FinTutoClass.
  • ensuite, on appelle la méthode printInterfaceList qui est implémentée dans la classe FinTutoClass
  • La troisième ligne montre que notre objet _object peut aussi appeler les méthodes dont il a hérité. La méthode printName est implémentée dans la classe PublicClassExtendsImplements dont hérite la classe FinTutoClass et n’est pas réimplémentée dans FinTutoClass.
  • Dans la quatrième ligne, on demande à afficher la classe de l’objet _object. Il sera affiché FinTutoClass.
  • Dans la cinquième ligne on caste notre objet : (PublicClassExtendsImplements)_object signifie que _object est ici traité comme étant une instance de la classe PublicClassExtendsImplements. Puis on demande d’afficher le nom de la classe dont il est l’instance. Il sera affiché FinTutoClass malgrè le cast. Bien que l’on ait casté l’objet, celui-ci reste de la classe dont on a appelé le constructeur.
  • Dans la sixième ligne, on déclare un objet _object2 comme étant de la classe  PublicClassExtendsImplements, cependant on fait appel au constructeur de FinTutoClass. Ceci est possible car FinTutoClass hérite de PublicClassExtendsImplements.
  • Du coup, dans la septième ligne, on peut appeler une méthode implémentée dans la classe PublicClassExtendsImplements.
  • Par contre, pour appeler une méthode de la classe FinTutoClass, nous somme obligés de caster l’objet _object2 en FinTutoClass. Ceci est possible car on a effectivement affaire à un FinTutoClass.
  • D’ailleurs si on demande à _object2 d’afficher le nom de sa classe, il affichera bien FinTutoClass.
  • Ensuite, on construit un objet _object3 mais en déclarant cette fois qu’il est du type de l’interface PublicInterface. L’objet est construit via l’appel au constructeur de la classe FinTutoClass. On peut donc typer un objet selon les interfaces que sa classe implémente.
  • Du coup on peut appeler les méthodes décrites dans l’interface. Et que les méthodes de l’interface tant que l’on ne caste pas l’objet.
  • On est par exemple obligé de caster l’objet pour faire appel à la méthode printInterfaceList. On peut là aussi caster l’objet en un type d’interface (ici InterfaceExtendsPublicInterface) que sa classe implémente.
  • Cette fois on construit un objet _object4 que l’on type selon l’interface InterfaceExtendsPublicInterface.
  • Du coup on peut appeler sans cast la méthode printInterfaceList
  • On peut aussi appeler sans cast une méthode définie dans une interface dont hérite l’interface InterfaceExtendsPublicInterface.

Sources du tutoriel

Vous pouvez télécharger le contenu de mon projet eclipse pour ce tutoriel.

Bien entendu les noms de classe ont ici été choisis pour le tutoriel. Vous n’êtes pas obligé de mettre le mot Default dans le nom d’une classe d’accés pas défaut.

IPC ou communication inter portlet 2. JSR286

Vendredi 22 janvier 2010

Un tutoriel sur la communication interportlet. Les ressources sur le sujet sont encore rares, il m’a semblé nécessaire de faire ce tutoriel assez rapidement du coup.

Si vous suivez les autres tutoriels de ce site sur la programmation JAVA, il arrive bien en avance de ce qui était prévu. Mais je le réintégrerai plus tard dans un tutoriel plus long consacré aux portlets.

Pour l’instant, ce tutoriel va traiter de la communication entre portlet conforme à la JSR286.

En particulier nous ne traiterons que de la communication par passage d’événement. Cette communication étant à nos yeux la plus compatible avec une vision composant. Pour ceux qui veulent en savoir plus, la ressource issue du blog xebia est la meilleure référence que j’ai trouvé. Dans cette ressource, vous retrouverez l’essentiel de ce qui est détaillé ici et une explication de l’autre solution de communication qu’est le partage d’état. Il y a aussi une discussion dans un des forums de JBoss.

Je précise que dans le cadre de ce tutoriel, les portlets ont été développés sous eclipse (mais ça n’a pas d’importance) et déployés sous JBoss Portal (version 2.7 + AS 4.2.3).

Cependant, le tutoriel s’adresse à tous développeurs de portlet 2.0, c’est à dire dans le cadre d’un développement de portlet pour un portail respectant la JSR286.

Partage d’état vs passage d’événement

Il y a deux façons de communiquer avec la JSR 286. La première solution est le partage d’état. Nous ne détaillerons pas dans ce tutoriel cette solution mais allons en expliquer le principe. La deuxième solution, celle que nous détaillerons ici en pratique est le passage d’événement. Ce paragraphe va donc exposer les principes de ces deux solutions et va nous permettre de justifier pourqoi le passage d’événement nous semble plus proche d’une approche composant et donc d’un développement orienté vers l’intégration de composants.

Le partage d’état : dans cette solution, chaque portlet déclare les paramètre qu’il partage avec les autres portlets et chaque portlet déclare les paramètres des autres portlets qu’il veut pouvoir atteindre. Ainsi, au moment ou un portlet effectue son rendu (calcule sa vue), il rend ses paramètres visibles ou accéde à ceux des autres.

Le passage d’événement : dans cette solution, chaque portlet déclare les événements qu’il peut lever et les événements qu’il peut écouter. Un portlet léve ensuite un événement, et les portlets écouteurs sont automatiquement au courant.

Discussion : La première solution (celle du passage d’état) peut être recommandée quand les paramètres échangés ne sont utiles que pour l’affichage. La solution est facile à mettre en place, il suffit de déclarer dans le descripteur du portlet les paramétres partagés. Cependant, cette solution n’est pas recommandé quand les paramétres doivent être traités (c’est à dire quand ils risquent d’être modifiés par un calcul effectué par un autre portlet) car les paramètres ne sont échangés qu’au moment de l’appel à la méthode Render. Mais la principale critique est que cette solution rend les portlets fortement dépendants les uns des autres puisque ils supposent l’existence de ces paramètres afin de rendre leur affichage. La deuxième solution quand à elle permet d’effectuer des traitements sur les paramètres et reste très proche d’une vision composant. Le mécanisme d’événements garantit que si le paramètre existe il y aura traitement, et que si le paramètre n’existe pas, il y aura un fonctionnement par défaut.

Passage d’événement pratique

Alors en pratique comment cela fonctionne? L’exemple que je vous propose est très simple: nous développons deux portlets, un PortletA et un PortletB. Chaque portlet a son propre projet dans Eclipse (bien que j’aurai pu faire un seul projet, mais pour l’exemple, je voulais détailler un cas ou les portlets auraient pu être développés sans connaissance l’un de l’autre). Le PortletA sera l’écouteur d’événement, le PortletB se chargera de l’envoi. L’événement levé permet d’échanger une donnée de type String.

Il est possible d’échanger autre chose que des String. Tout objet serializable peut être échangé par passage d’événement.

Les erreurs classiques à éviter (si je le dis c’est que je suis passé par là croyez-moi ;) ) :

  • Ne pas utiliser la bonne api de portlet. N’oubliez pas que nous faisons des portlets avec JSR 286 donc on utillise la nouvelle api.
  • Si vous faites des JSP, n’oubliez toujours pas que vous faites des portlets version 2. Donc le taglib à utiliser est : <%@ taglib uri=”http://java.sun.com/portlet_2_0″ prefix=”portlet” %>
  • N’oubliez toujours pas que vous faites des portlets 2.0. Donc dans vos descripteurs portlet.xml, les attributs du noeud portlet-app changent : <portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd” version=”2.0″ xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”          xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>

Il faut déclarer le type des paramétres échangés, ou des event levés si vous préférez. Pour cela, il faut modifier le descripteur de l’application portlet.

Il faut ajouter un noeud <event-definition> comme fils du noeud <portlet-app> dans votre fichier portlet.xml.

PortletB

Dans l’exemple, le descripteur portlet.xml associé au projet du portletB devient :

<?xml version=”1.0″ encoding=”UTF-8″?>
<portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”
version=”2.0″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>
<portlet>
<portlet-name>PortletB</portlet-name>
<portlet-class>tuto.portlet.PortletB</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Enverra des infos à Portlet A</title>
</portlet-info>
<supported-publishing-event>
<qname>totoString</qname>
</supported-publishing-event>
</portlet>
<event-definition>
<qname>totoString</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>

J’ai décidé de passer des String uniquement comme paramétre et d’appeler cet événement “totoString”.

Au niveau du code, j’ai décidé de faire un simple portlet qui charge un jsp et qui léve l’événement totoString lors d’une action. L’action est réalisé lors d’un clic sur un lien dans le portlet (cf portletB.jsp).

Le code du PortletB :

package tuto.portlet;

import java.io.IOException;
import javax.portlet.ActionRequest;
import javax.portlet.ActionResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;

public class PortletB extends GenericPortlet
{
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws IOException, PortletException
{
rResponse.setContentType(”text/html”);
PortletRequestDispatcher prd;
prd = getPortletContext().getRequestDispatcher(rResponse.encodeURL(”/WEB-INF/jsp/portletB.jsp”));
prd.include(rRequest, rResponse);
}

public void processAction(ActionRequest request, ActionResponse response)
throws PortletException,IOException {
System.out.println(”processAction”);
this.sendEvent(response);
}
public void sendEvent(ActionResponse response)
{
String _toto = “passée en event”;
response.setEvent(”totoString”, _toto);
}
}

Le fichier portletB.jsp :

<%@ page language=”java” contentType=”text/html; charset=UTF-8″
pageEncoding=”UTF-8″%>
<%@ taglib uri=”http://java.sun.com/portlet_2_0″ prefix=”portlet” %>
<portlet:defineObjects/>
HelloWorld !!! Portlet B!
<a href=”<portlet:actionURL/>” >Envoi de l’event</a>
PortletA

Le PortletA est le portlet traitant un événement. Il doit donc implémenter l’interface EventPortlet et sa méthode processEvent(EventRequest request, EventResponse response). La méthode processEvent sera automatiquement appelé lorsque un événement du type de ceux déclaré dans le descripteur portlet.xml sera levé par un autre portlet.

Le descripteur portlet.xml de PortletA :

<?xml version=”1.0″ encoding=”UTF-8″?>
<portlet-app xmlns=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”
version=”2.0″
xmlns:xsi=”http://www.w3.org/2001/XMLSchema-instance”
xsi:schemaLocation=”http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd
http://java.sun.com/xml/ns/portlet/portlet-app_2_0.xsd”>
<portlet>
<portlet-name>PortletA</portlet-name>
<portlet-class>tuto.portlet.PortletA</portlet-class>
<supports>
<mime-type>text/html</mime-type>
<portlet-mode>VIEW</portlet-mode>
</supports>
<portlet-info>
<title>Recevra des infos de Portlet B</title>
</portlet-info>
<supported-processing-event>
<qname>totoString</qname>
</supported-processing-event>

</portlet>

<event-definition>
<qname>totoString</qname>
<value-type>java.lang.String</value-type>
</event-definition>
</portlet-app>

Le code de PortletA :

package tuto.portlet;

import java.io.IOException;
import java.io.PrintWriter;

import javax.portlet.Event;
import javax.portlet.EventRequest;
import javax.portlet.EventResponse;
import javax.portlet.GenericPortlet;
import javax.portlet.PortletException;
import javax.portlet.PortletRequestDispatcher;
import javax.portlet.RenderRequest;
import javax.portlet.RenderResponse;
import javax.portlet.EventPortlet;

public class PortletA extends GenericPortlet implements EventPortlet
{
protected void doView(RenderRequest rRequest, RenderResponse rResponse) throws IOException, PortletException
{
if(rRequest.getParameter(”stringEvent”)!=null)//Action avec Event
{
rResponse.setContentType(”text/html”);
PrintWriter writer = rResponse.getWriter();
writer.write(”Event value of totoString : ” + rRequest.getParameter(”stringEvent”));
writer.close();
}
else //Action sans Event
{
rResponse.setContentType(”text/html”);
PortletRequestDispatcher prd;
prd = getPortletContext().getRequestDispatcher(rResponse.encodeURL(”/WEB-INF/jsp/portletA.jsp”));
prd.include(rRequest, rResponse);
}
}

public void processEvent(EventRequest request, EventResponse response)
{
Event event = request.getEvent();
String _toto = “vide”;
if(event.getName().equals(”totoString”))
{
_toto = (String)event.getValue();
response.setRenderParameter(”stringEvent”, _toto);
}
}

}

Le jsp de PortletA n’a aucune importance étant donné que c’est uniquement du HTML au final. Pour varier les plaisirs j’ai préféré utiliser un printWriter pour l’affichage après traitement de l’événement. Le but étant juste ici de constater visuellement que le PortletA a bien reçu l’événement. Dans un cas concret, il n’est pas forcément nécessaire de modifier le rendu du PortletA une fois l’événement traité.

Rendu dans JBoss Portal

Une fois déployés les deux portlets s’affichent ainsi :

capture d'écran des portlets du tuto ipc dans JBoss

capture d'écran des portlets du tuto ipc dans JBoss

Une fois cliqué sur le lien “Envoi de l’event” :

capture d'écran des portlets du tuto dans JBoss une fois event envoyé

capture d'écran des portlets du tuto dans JBoss une fois event envoyé

J’espére que ce tutoriel court et rapide vous aura suffisament éclairé et vous fera gagner du temps. Le plus difficile concernant l’IPC étant encore de trouver de la documentation.

Vous pouvez télécharger les sources de ce tutoriel.

utilisation d’un vocabulaire RDF - le cas de FOAF

Lundi 28 décembre 2009

Je commence une série de tutoriels axés web sémantique. Dans le cadre de mes travaux je dois utiliser des vocabulaires RDF-OWL pour représenter des données et les échanger entre des applications.

Du coup, je me suis dit en voyant le peu de tutoriels en français sur le web que ça vaudrait le coup d’en faire un moi-même.

Ce premier tutoriel concerne l’utilisation d’un vocabulaire existant. En particulier le vocabulaire FOAF qui permet de décrire des personnes et le réseau de connaissances de ces personnes.

Nous allons dans ce premier tutoriel utiliser une syntaxe RDF/XML. Ce n’est pas la seule solution possible mais c’est celle qui m’a semblé “la plus propre”, la plus simple à lire par un humain. Je reviendrai peut-être dans d’autres tutoriels sur d’autres syntaxes.

Le mieux étant de s’appuyer sur l’usage, je vais m’appuyer sur la construction du RDF FOAF permettant de me décrire.

Début du document

Un document RDF/XML est avant tout un document XML. Donc vous pouvez déclarer la version d’xml utilisée et l’encodage :

<?xml version =”1.0″ encoding =”utf-8″?>

Vous pouvez aussi lui associer un style.

Ensuite, vous allez devoir dans votre RDF faire référence aux vocabulaires existants que vous utilisez. Par exemple, FOAF est défini à l’url http://xmlns.com/foaf/0.1/

A chaque fois que vous allez utiliser une classe de FOAF, vous allez devoir taper http://xmlns.com/foaf/0.1/:ClasseAUtiliser

Mais heureusement vous pouvez déclarer au début de votre RDF que vous allez utiliser ce vocabulaire et lui associer un alias. Cette déclaration peut se faire dans la balise <rdf:RDF> signalant le début de votre document RDF. Mais notez que vous pouvez déclarer un alias pour un vocabulaire dans n’importe quel noeud. L’alias n’étant alors valable que pour les noeuds fils.

Exemple pour FOAF en début de document :

<rdf:RDF xmlns:foaf=”http://xmlns.com/foaf/0.1/”>

On a associé l’alias foaf au vocabulaire défini à l’url http://xmlns.com/foaf/0.1/

On aura aussi besoin de quelques éléments du vocabulaire RDF de base donc le début de document devient :

<rdf:RDF xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#” xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#” xmlns:foaf=”http://xmlns.com/foaf/0.1/”>

Nous ajouterons d’autres vocabulaires par la suite dans ce tutoriel. Mais je ne reviendrai pas sur la déclaration des alias.

Principes de RDF

Avant de nous intéresser au corps du document, nous allons faire un petit rappel sur le principe de base de RDF.

RDF permet d’écrire des triplets Sujet Prédicat Objet.

Un sujet, un prédicat et un objet sont des ressources identifiées par des URI. Une URI étant censée être unique pour une ressource. Par exemple, une URL est une URI.

Afin de permettre de réifier un triplet en concept, il est possible d’associer une URI à un triplet. Ces triplets réifiés sont appelés des Statement.

Les Objets et Sujets sont des instances de classes RDF. Les prédicats sont des propriétés RDF. Dans les spécifications, pour chaque propriété est précisé son Domaine (le type ou la classe du Sujet) et son Range (le type ou la classe de l’Objet).

Corps du document

Nous allons dans ce document décrire ma personne Natoine. Nous allons utiliser la classe foaf:Person. Le début de la déclaration :

<foaf:Person rdf:about=”http://www.natoine.fr/#me”>
  • foaf:Person, je fais une instance de Person.
  • rdf:about=”http://www.natoine.fr/#me” , je précise l’URI de la ressource. En l’occurence j’utilise une URL existante, la page d’accueil de mon domaine à laquelle je concaténe #me. Il existe d’autres façons de faire référence à une ressource. Par exemple, au lieu de rdf:about on peut utiliser rdf:ID. Dans ce cas, la valeur prise est concaténée à l’URL du document pour constituer l’URI ou bien concaténée à une URI précisée par xml:base. Par exemple :
<rdf:RDF xmlns:foaf=”http://xmlns.com/foaf/0.1/” xml:base=”http://www.natoine.fr”>

<foaf:Person rdf:ID=”me”>

</foaf:Person>

</rdf:RDF>

On parle toujours de la personne identifiée par l’URI http://www.natoine.fr/#me. rdf:ID ajoute un #. Notez aussi que rdf:about=”#me” serait totalement équivalent. Si rdf:about ne précise pas une URI compléte, celle-ci est construite par concaténation.

Foaf Basics

Maintenant que peut-on dire sur ma personne?  FOAF définit un ensemble de propriétés. Je ne vais pas toutes les détailler. Il suffit d’aller regarder les spécifications de FOAF.

Mais pour l’exemple je vais préciser mon nom, prénom, surnom,… En gros les Basics de FOAF. Que du très simple pour l’instant. On utilise des Strings ou des références à des ressources web.

<foaf:Person rdf:about=”http://www.natoine.fr/#me”>
<!– FOAF Basics –>
<foaf:name xml:lang=”fr”>Antoine Seilles</foaf:name>
<foaf:nick>Natoine</foaf:nick>
<foaf:surname>Natoine</foaf:surname>
<foaf:familyName>Seilles</foaf:familyName>
<foaf:firstName>Antoine</foaf:firstName>
<foaf:title>phD Student</foaf:title>
<foaf:homepage rdf:resource=”http://www.natoine.fr/”/>
<foaf:img rdf:resource=”/natoine.ico”/>
<foaf:depiction rdf:resource=”/natoine.ico”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/01.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/02.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/07.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/08.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/13.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/18.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/19.JPG”/>
<foaf:depiction rdf:resource=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/20.JPG”/>
</foaf:Person>

Notez l’utilisation de rdf:resource pour faire référence à des ressources existantes. Il est possible de faire des références absolues, ou relatives (celles-ci obéissent aux mêmes règles que rdf:ID).

Pour des ressources présentes sur internet, vous pouvez vous contenter de préciser l’URL. Mais je vous encourage à en dire un peu plus quand c’est possible. Par exemple pour des images, il est possible d’utiliser la classe foaf:Image. Je détaille l’utilisation de foaf:Image un peu plus loin dans ce tutoriel.

Foaf Personal Info

Attaquons-nous maintenant aux informations personnelles (Personal Info), tout en restant sur des ressources internet ou des String.

Voilà ce que je rajoute comme infos me concernant :

<!– FOAF Personal Info –>
<foaf:weblog rdf:resource=”/wordpress”/>
<foaf:currentProject rdf:resource=”http://www.imagilab.fr”/>
<foaf:currentProject rdf:resource=”http://www.blackpad.fr”/>
<foaf:currentProject rdf:resource=”http://intermed.csregistry.org/tiki-index.php”/>
<foaf:workplaceHomepage rdf:resource=”http://www.lirmm.fr/”/>
<foaf:workInfoHomepage rdf:resource=”http://www.lirmm.fr/”/>
<foaf:schoolHomepage rdf:resource=”http://lycee-pompidou-34.org/”/>
<foaf:schoolHomepage rdf:resource=”http://www.univ-montp2.fr/”/>
<foaf:publications rdf:resource=”/publications”/>

Venons-en maintenant aux centres d’intèrets. L’un de mes centres d’interêt est l’Intelligence Artificielle. Dans les spécifications de FOAF, il est dit que la propriété interst a pour range un foaf:Document.

Une syntaxe minimale pour dire que je suis intéressé par l’intelligence artificielle serait :

<foaf:interest rdf:resource=”http://fr.wikipedia.org/wiki/Intelligence_artificielle”/>

Mais on peut faire mieux grâce à la classe foaf:Document :

<foaf:interest>

<foaf:Document rdf:about=”http://fr.wikipedia.org/wiki/Intelligence_artificielle”/>

</foaf:interest>

Cependant on peut avoir envie d’en dire un peu plus au sujet de ce centre d’intérêt que de faire référence à une page wikipedia. Pour l’exemple, on va dire que la page en question a pour titre Intelligence Artificielle, qu’elle est la page française de wikipedia au sujet de l’intelligence artificielle.

On va utiliser les propriétés title et description du vocabulaire Dublin Core et la propriété foaf:topic de FOAF.

Il faut ajouter l’alias à dublin core : xmlns:dc=”http://purl.org/dc/elements/1.1/”

et notre foaf interest devient :

<foaf:interest>
<foaf:Document rdf:about=”http://fr.wikipedia.org/wiki/Intelligence_artificielle”>
<dc:title>Intelligence Artificielle</dc:title>
<dc:description>French Artificial Intelligence page on wikipedia</dc:description>
<foaf:topic>Artificial Intelligence</foaf:topic>
</foaf:Document>
</foaf:interest>

De la même façon on peut donner plus d’information sur les foaf:Image utilisées comme foaf:depiction. Par exemple, j’ai enrichi les infos concernant mes photos de la façon suivante :

<foaf:depiction>
<foaf:Image rdf:about=”http://www.imagilab.fr/wp-content/gallery/RiviereTournage/01.JPG”>
<dc:title>Antoine et Erik</dc:title>
<dc:description>Picture of Natoine and Erik during “La riviere” shooting</dc:description>
<dc:format>image/jpg</dc:format>
<foaf:maker rdf:resource=”http://www.vincentrok.com/”/>
</foaf:Image>
</foaf:depiction>

J’utilise à la fois le vocabulaire Dublin Core et le vocabulaire FOAF. La propriété foaf:maker est équivalente à la propriété Dublin Core dc:creator. Elle permet de préciser qui est l’auteur d’une ressource. En l’occurence, les photos sont prises par Vincent Rok.

foaf:maker est censé être une foaf:Person. Donc comme toujours, je peux me contenter d’une URL ou je peux créer une foaf:Person. Ce qui donne à minima:

<foaf:maker>
<foaf:Person rdf:about=”http://www.vincentrok.com/”/>
</foaf:maker>

Cependant, il se trouve que je connais Vincent Rok et donc je déclarerai Vincent Rok comme une personne quand je déclarerai mes connaissances. Du coup je peux me contenter de la ligne <foaf:maker rdf:resource=”http://www.vincentrok.com”/> .

Lien à DBPedia

Bien sûr on pourrait faire encore mieux. Surtout qu’un topic foaf est “A thing” (la super classe) pour RDF. Du coup on pourrait faire de topic n’importe quoi d’autre, comme un tag par exemple, ou une discipline. Mais il faudrait s’appuyer sur un autre vocabulaire. Gardez en tête que une URL est souvent la meilleure information à donner. Surtout si par cette URL on peut à nouveau récupérer du RDF. Pensez à DBPedia par exemple. Au lieu de décrire dans mon profil ce qu’est mon centre d’intérêt en utilisant le vocabulaire de Dublin Core, je pourrai mettre une url à laquelle on trouvera une description de ce centre d’intérêt.

Un autre de mes centres d’intérêt est la Réalité virtuelle. Il existe une page Wikipedia française et un équivalent anglais. Je pourrai faire un simple lien vers l’une de ces deux URL ou, un peu mieux, mettre l’une de ces URL comme Document avec un petit peu d’informations supplémentaires. Sauf qu’il y a encore mieux: DBpedia permet pour chaque page de Wikipedia version anglaise de récupérer un RDF décrivant cette ressource.

L’URL Wikipedia de la réalité virtuelle en anglais est : http://en.wikipedia.org/wiki/Virtual_reality

Du coup, il existe une page DBpedia : http://dbpedia.org/page/Virtual_reality

Et pour récupérer le RDF/xml l’url est : http://dbpedia.org/data/Virtual_reality.rdf

Ce qui donne dans mon RDF :

<foaf:interest rdf:resource=”http://dbpedia.org/data/Virtual_reality.rdf”/>

Si vous allez regarder le contenu de ce RDF, vous verrez qu’il y a des infos super pratique comme l’utilisation de owl:sameAs qui permet de dire que cette ressource est la même que d’autres ressources, et puis surtout l’utilisation de foaf:page et foaf:depiction. Donc DBpedia réutilise des vocabulaires existant comme le vocabulaire FOAF.

Déclarez vos connaissances

Ensuite, viennent les “connaissances”, ces personnes que je connais. FOAF ne permet que de déclarer des connaissances grâce à la propriété knows.

Je vais déclarer que je connais Vincent Rok le photographe et Julien Cotret mon collégue de bureau.

<foaf:knows>
<foaf:Person rdf:about=”http://www.vincentrok.com/”>
<foaf:nick>Vincent Rok</foaf:nick>
<foaf:homepage rdf:resource=”http://www.vincentrok.com/”/>
<foaf:gender>male</foaf:gender>
<foaf:currentProject rdf:resource=”http://www.imagilab.fr”/>
</foaf:Person>
</foaf:knows>
<foaf:knows>
<foaf:Person rdf:about=”http://www.natoine.fr/#Julien_Cotret”>
<foaf:name xml:lang=”fr”>Julien Cotret</foaf:name>
<foaf:familyName>Cotret</foaf:familyName>
<foaf:firstName>Julien</foaf:firstName>
<foaf:title>phD Student</foaf:title>
<foaf:gender>male</foaf:gender>
<foaf:currentProject rdf:resource=”http://intermed.csregistry.org/tiki-index.php”/>
</foaf:Person>
</foaf:knows>

Mais je ne connais pas Julien de la même façon que je connais Vincent. Et Foaf ne me permet pas d’en dire plus sur ces relations. Cependant, il est possible d’étendre FOAF (comme tout autre vocabulaire) et de définir des relations plus spécifiques.

Enrichissement d’un vocabulaire

Par exemple nous allons définir une relation de collégue de travail.

Cette tâche demande que l’on crée un rdf de description du vocabulaire enrichi puis qu’on ajoute un alias à ce vocabulaire.

Appelons notre nouveau vocabulaire totoFoaf.

<rdf:RDF
xmlns:rdf=”http://www.w3.org/1999/02/22-rdf-syntax-ns#”
xmlns:rdfs=”http://www.w3.org/2000/01/rdf-schema#”
xmlns:foaf=”http://xmlns.com/foaf/0.1/”
xmlns:dc=”http://purl.org/dc/elements/1.1/”
xml:base=”http://www.natoine.fr/totoFoaf.rdf”>

<rdf:Description rdf:about=”">
<dc:author rdf:resource=”"/>
<dc:title>Sample Relationships Schema</dc:title>
<dc:description>Schema for Defining Relationships in FOAF</dc:description>
</rdf:Description>

<!–property–>

<rdf:Description rdf:about=”http://www.natoine.fr/totoFoaf.rdf/Colleague”>
<rdf:type rdf:resource=”http://www.w3.org/1999/02/22-rdf-syntax-ns#Property”/>
<rdfs:subPropertyOf rdf:resource=”http://xmlns.com/foaf/0.1/knows”/>
<rdfs:label>Colleague</rdfs:label>
</rdf:Description>
</rdf:RDF>

Du coup en modifiant mon rdf on peut dire que Julien Cotret est un collégue de travail.

<totoFoaf:colleague>
<foaf:Person rdf:about=”http://www.natoine.fr/#Julien_Cotret”>
<foaf:name xml:lang=”fr”>Julien Cotret</foaf:name>
<foaf:familyName>Cotret</foaf:familyName>
<foaf:firstName>Julien</foaf:firstName>
<foaf:title>phD Student</foaf:title>
<foaf:gender>male</foaf:gender>
<foaf:currentProject rdf:resource=”http://intermed.csregistry.org/tiki-index.php”/>
</foaf:Person>
</totoFoaf:colleague>

Mes comptes sur le web

Il reste un dernier point. L’une des problèmatiques du web actuel avec la prolifération des applications de social networking est l’identité fragmentée des utilisateurs. Etant utilisateur de Facebook, de twitter, d’un blog, de plusieurs forums, je me retrouve avec autant de comptes utilisateurs différent que d’applications web que j’utilise. Du coup, j’ai envie de dire que tout ces comptes me sont associés. Il est possible de le faire grâce à la propriété foaf:account.

Par exemple je déclare mon compte twitter :

<foaf:account>
<foaf:OnlineAccount>
<foaf:accountServiceHomepage rdf:resource=”http://www.twitter.com”/>
<foaf:accountName>natoine</foaf:accountName>
</foaf:OnlineAccount>
</foaf:account>

Pour conclure ce turoriel, vous trouverez mon FOAF complet en ligne. Vous pouvez l’explorer avec FOAF explorer qui permet d’explorer de proches en proches le réseau. Et essentiel pour tester votre RDF/XML, il existe un validateur w3C.

Premier code Ruby

Vendredi 4 décembre 2009

Nous commençons une prise en main Ruby on Rails avec Julien Cotret mon camarade de thèse (on partage le même bureau, un encadrant en commun et surtout un projet ANR).
Du coup, j’en profite pour vous proposer un ensemble de tutoriels. Ces tutoriels sont donc rédigés au fur et à mesure de ma propre progression.

Ce tutoriel suppose que vous avez déjà installé Ruby sur votre machine.
Dans ce tutoriel nous allons réaliser un premier programme en Ruby.
Pour commencer, nous conseillons d’utiliser le programme IRB (interactive Ruby) comme recommandé dans le tutoriel : Ruby en 20 minutes

IRB permet d’écrire et d’interpréter du code Ruby à la volée. Il vous suffit de taper votre code Ruby au niveau du prompteur irb pour voir le résultat.
Lancez une console et tapez :

irb

Vous devriez avoir l’affichage suivant :

irb(main):001:0>

Vous pouvez taper du code Ruby :)

La définition de méthodes

La définition de méthodes en Ruby fait intervenir deux mots clefs : def et end
Définissons une méthode helloWorld avec IRB:

irb(main):010:0> def helloWorld
irb(main):011:1> puts “Hello World!”
irb(main):012:1> end

Pour appeler cette méthode, il suffit de taper :

irb(main):006:0> helloWorld

Vous pouvez aussi taper :

irb(main):006:0> helloWorld()

def signale donc le début de la déclaration de méthode. end la fin de la déclaration.
puts est la commande de base permettant d’écrire sur un terminal.

Hello Machin

Ou une première déclaration de méthode avec passage de paramétres :

irb(main):015:0> def hello(name)
irb(main):016:1> puts “Hello #name!”
irb(main):017:1> end

L’appel de la méthode en passant un paramétre se fait de la façon suivante :

irb(main):018:0> hello(”natoine”)

et renvoie :

Hello natoine!
=> nil

Dans notre code, name fait référence à la chaîne de caractére passée en paramétre. name représente une instance de chaîne de caractéres donc vous pouvez appeler toutes les méthodes s’appliquant à des chaînes de caractéres sur name. Par exemple, vous pouvez appeler la méthode capitalize pour que name commence par une majuscule.
#{} permet d’insérer le contenu de la variable name dans une chaîne de caractéres.

Nous allons modifier la méthode pour afficher le nom passé en paramétre avec une majuscule :

irb(main):015:0> def hello(name)
irb(main):016:1> puts “Hello #{name.capitalize}!”
irb(main):017:1> end

Le même appel que précédement :

irb(main):014:0> hello(”natoine”)

renvoie cette fois :

Hello Natoine!
=> nil

Au passage, vous pouvez appeler la méthode hello sans utiliser les paranthéses, elles sont optionelles. L’appel suivant est donc équivalent au précédent :

irb(main):014:0> hello “natoine”

Valeur de variable par défaut

Cette fois, on veut pouvoir appeler hello sans paramétre et afficher Hello World ! ou hello avec un paramétre name et afficher Hello name !

irb(main):027:0> def hello(name = “World”)
irb(main):028:1> puts “Hello #{name.capitalize}!”
irb(main):029:1> end

L’appel :

irb(main):030:0> hello

renvoie :

Hello World!
=> nil

alors que

irb(main):031:0> hello “natoine”

renvoie toujours :

Hello Natoine!
=> nil

Au sujet de la surcharge de méthodes

Petite parenthése si vous venez d’un autre langage de programmation et que vous avez l’habitude de surcharger vos méthodes. C’est à dire définir un hello sans paramétre et un hello avec paramétre. Est-ce possible en Ruby?
Et bien non. La seule solution est celle qui vient de vous être présentée. Il est impossible d’avoir plusieurs méthodes ayant le même nom dans une classe Ruby.
Par contre, il est possible de définir des valeurs par défaut pour les paramétres et donc de gérer des comportements par défaut.
Ca revient presque au même.
Première déception de Ruby peut-être? A vous de juger.

Définition de classes

Pour cette partie, je me suis aussi appuyé sur le tutoriel : premiers pas avec Ruby

La définition d’une classe se fait par l’utilisation des mots clefs class et end.
class indiquant le début de la déclaration de la classe et end la fin.
Créons une classe Groom :

irb(main):032:0> class Groom
irb(main):033:1> end

Pour l’instant nous n’avons défini aucne méthodes dans notre classe. Cependant nous pouvons déjà faire pas mal de choses.
On peut déjà instancier la classe Groom :

irb(main):036:0> spirou = Groom.new

On vient de créer un objet spirou, instance de la classe Groom. Mais que peut-on faire faire à spirou?
Et bien dans Ruby, toute classe hérite au moins de la classe Object. Donc Groom a hérité de Object toutes ses méthodes.
On peut donc vérifier quelles méthodes sont disponibles pour Groom grâce à la méthode instance_methods.

irb(main):037:0> Groom.instance_methods

On peut aussi demander explicitement de n’afficher que les méthodes propres à la classe Groom en passant un paramétre false à la méthode

instance_methodsirb(main):038:0> Groom.instance_methods false

Maintenant notre classe étant un peu vide, nous allons voir comment remédier à ce problème.
On souhaiterait associer un nom à chaque instance de la classe Groom. C’est à dire définir une variable d’instance.
On souhaiterait aussi que notre Groom puisse au moins dire “Bonjour!” et “Aurevoir!”.
Cela reviendrait à faire la déclaration de classe suivante :

class Groom
def initialize(name)
@name=name
end
def say_hello
puts “Bonjour!”
end
def say_bye
puts “Aurevoir!”
end
end

La méthode initialize est la méthode appelée lors de l’instanciation d’un objet. C’est le constructeur de la classe.
Les variables commençant par un @ sont les variables d’instance.

Modifier une classe a posteriori

Cependant, nous avons déjà déclaré la classe Groom et nous ne voulons pas la redéclarer. Nous voulons uniquement l’éditer, la modifier. Ceci est possible en Ruby très simplement. Il suffit de réutiliser le mot-clef class, comme si on redéclarait la classe Groom.
Donc modifions notre classe de façon incrémentale :

irb(main):039:0> class Groom
irb(main):040:1> def initialize(name)
irb(main):041:2> @name=name
irb(main):042:2> end
irb(main):043:1> end

Et réinstancions un objet Groom que nous appelerons spirou :

irb(main):044:0> spirou = Groom.new “spirou”

Editons encore notre classe pour ajouter les méthodes say_hello et say-bye :

irb(main):045:0> class Groom
irb(main):046:1> def say_hello
irb(main):047:2> puts “Bonjour!”
irb(main):048:2> end
irb(main):049:1> def say_bye
irb(main):050:2> puts “Aurevoir!”
irb(main):051:2> end
irb(main):052:1> end

On pourra vérifier en appelant Groom.instance_methods false ou tout simplement en demandant à spirou :

irb(main):053:0> spirou.say_bye
Aurevoir!
=> nil
irb(main):054:0> spirou.say_hello
Bonjour!
=> nil

Vous vous rendez compte que notre objet spirou peut faire appel à des méthodes qui ont été définies dans la classe Groom après la création de l’instance spirou !! Si c’est pas énorme ça.

Variables d’instance

Et notre variable d’instance @name, on aimerait bien pouvoir la modifier, la consulter. Alors comment fait-on? Ruby propose une solution très simple :

irb(main):056:0> class Groom
irb(main):057:1> attr_accessor :name
irb(main):058:1> end

Désormais deux nouvelles méthodes sont accessibles : name= et name.
name= permet de modifier la valeur de la variable et name de la consulter.
Vous pouvez vérifier toujours avec instance_methods mais surtout en modifiant le nom de spirou :

irb(main):060:0> spirou.name
=> “spirou”
irb(main):061:0> spirou.name=”fantasio”
=> “fantasio”
irb(main):062:0> spirou.name
=> “fantasio”

Premier Programme

Bon ça suffit avec irb. Passons aux choses sérieuses (pour quitter irb tapez exit, ou quit ou ctrl+D ).
Créons un premier fichier pour accueillir notre classe Groom. Le fichier s’appellera groom.rb
Le contenu du fichier va reprendre la classe Groom précédement présentée et un peu de code en plus :

class Groom
def initialize(name)
@name=name
end
def say_hello
puts “Bonjour!”
end
def say_bye
puts “Aurevoir!”
end
end

spirou = Groom.new “spirou”
spirou.say_hello
spirou.say_bye

Sauvez votre fichier. Placez vous dans le dossier contenant votre fichier avec une console et tapez :

ruby groom.rb

C’est magique, la console vous renvoie :

Bonjour!
Aurevoir!

Tweets à chaque nouvel article sur wordpress

Lundi 30 novembre 2009

Ca y est ça marche. Après de nombreux tests j’ai enfin trouvé comment générer automatiquement un post sur twitter (un tweet si vous préférez) à chaque nouvel article publié sur mon blog.

Enfin je veux dire, comment le faire en modifiant le php de wordpress moi-même, sans ajouter un plugin.

Donc je vous livre ce micro-tutoriel Do it yourself

Tout d’abord, pour poster sur Twitter en php, vous allez avoir recours aux fonctions curl. Et pour cela, il faut que votre serveur ait la lib php-curl d’installée.

php5-curl pour php5 bien sur. Sous linux vous pouvez l’ajouter via le gestionnaire de paquets.

Pensez aussi à redémarrer votre serveur Apache.

Ensuite, il faut ajouter dans le fichier wordpress/wp-includes/post.php à la ligne 1536 dans la fonction wp_insert_post() les quelques lignes suivantes :

if($post_type==’post’)
{

$ch = curl_init();
curl_setopt($ch, CURLOPT_URL , “http://twitter.com/statuses/update.xml”);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT , 2);
curl_setopt($ch, CURLOPT_RETURNTRANSFER , 1);
curl_setopt($ch, CURLOPT_POST , 1);
$title = $post_title;
$url = ‘www.natoine.fr/wordpress/?p=’.$post_ID;
curl_setopt($ch, CURLOPT_POSTFIELDS , ’status=Nouveau post sur mon blog : ‘.$title.’ : ‘.$url);
curl_setopt($ch, CURLOPT_USERPWD , “user:password”);
if ($post_status == ‘publish’ && $previous_status==’draft’) { $buffer_twitter = curl_exec($ch); }
curl_close($ch);
}

Pour moi ça tombe juste après deux appels à do_action() dans post.php et juste avant le return $post_id.
Bien sur il faut remplacer user par votre nom d’utilisateur twitter et password par votre mot de passe twitter.
J’ai fait le choix d’afficher ce message contenant un lien vers le nouveau post du coup, mais vous pouvez mettre ce que vous voulez.

Bon ce tuto est pas super rédigé mais c’est implémenté, tapé ce soir et je ne voulais pas y passer plus de temps.

Débuter JAVA

Mardi 24 novembre 2009

Pourquoi une suite de tutoriels Java? Et qui reprennent toutes les bases alors qu’il y en a déjà plein sur internet. Et bien en réalité, écrire un tutoriel est un excellent moyen de vérifier pour l’auteur qu’il maîtrise bien lui-même le sujet. Dans notre cas, nous étions quelques-uns à parler de passer la certification “programmer” de Sun pour Java. Mais après avoir essayé d’organiser des séances de révision et de subir la démotivation des uns et des autres, il m’a semblé qu’écrire une suite de tutoriels serait le meilleur moyen pour moi de m’assurer que j’avais bien le niveau.Maintenant, avancer seul sur une série de tutoriel me semblait encore une activité démotivante à la longue. Alors j’ai proposé à deux amis de les co-rédiger. Au final, nous sommes trois à écrire ces tutoriels. Chaque tutoriel est le fruit de séances de tests du contenu et de plusieurs lectures et corrections. L’équipe est composée de Kraft et moi même, qui n’avons pas perdu l’espoir d’un jour passer cette damnée certification, et de Fabien qui profite de l’occasion pour apprendre java. Nous testons et construisons les tutoriels lors de séances de pratiques. Il nous semble que ce contexte est pertinent pour vous offrir des tutoriels abouttis.

Ces tutoriels sont co-rédigés via mon wiki et publiés en version finale sur mon blog. Dans les deux cas, il est possible aux lecteurs de nous laisser des commentaires. Ne vous en privez pas, c’est comme ça qu’on progresse tous, vous et nous.

Première approche

Vocabulaire minimum

Dans cette première partie, nous allons revenir sur un vocabulaire de base qu’il peut être intéressant de connaître. Ce n’est pas que ce vocabulaire vous servira à coder à proprement parler, mais il vous permettra de mieux naviguer dans le monde JAVA. Et puis si au hasard d’une discussion votre interlocuteur utilise l’un de ces termes, ça vous évitera de passer pour un ***.
IDE : Integrated Development Environment. C’est un espace de développement. Donc un ensemble de programmes vous permettant de développer et de tester votre code sans sortir de l’espace de développement. En gros, l’espace de développement doit vous fournir un éditeur de code, un compilateur et vous permettre de lancer l’éxécution de vos programmes et de suivre le déroulement de ceux-ci. C’est un moyen de gagner du temps, beaucoup de temps.

JVM : Java Virtual Machine. C’est un ensemble de programmes et de structures de données qui permet d’interpréter des scripts ou programmes écrits dans un langage particulier, le bytecode java. Vous écrivez vos programmes dans un langage dit naturel et vous les compilez dans un autre langage, le bytecode. Celui-ci est interprétable, compréhensible, par toute JVM. C’est ce qui permet à java d’être un langage de programmation multi-plateformes. Chaque Architecture, chaque OS, a sa propre machine virtuelle. Ainsi un programme écrit en java et traduit en bytecode java est compréhensible sur toutes les plateformes ayant une JVM.

JRE : Jave Runtime Environment. C’est ce qui va vous permettre de comprendre le java. En fait, c’est là que se trouve votre JVM. Le JRE, c’est en gros l’ensemble du code nécessaire pour lancer une JVM. Quand un programme java est lancé, le JRE crée une JVM qui interpréte le bytecode du programme.

JDK : Java Development Kit. Le JDK est en gros le complément du JRE. Si le JRE permet d’interpréter un byte code, le JDK lui permet de compiler du bytecode à partir du code java dit “naturel”.

API : Application Programming Interface. C’est l’ensemble des fonctions et leurs descriptions mises à disposition des développeurs. C’est essentiel pour pouvoir partager le travail d’un développeur à l’autre. Dans le cas de Java, il existe une API des packages de bases. Mais chacun peut éditer la documentation de ses propres développements grâce à la javadoc. L’URL de l’api java 6: http://java.sun.com/javase/6/docs/api

Les bases java

Dans cette partie, nous allons vous faire écrire, compiler et exécuter un premier programme JAVA. Et ce premier programme sera un HelloWorld (comme c’est original). Ecrire ce programme vous aménera à écrire une première classe JAVA et nous allons tenter d’expliquer au fur et à mesure les éléments mis en jeux. Ce premier exercice doit être vu comme une initiation. C’est l’occasion de vérifier que vous avez bien tout ce qu’il faut pour faire du java (JRE, JDK). Les différents éléments sur lesquels nous allons revenir risquent donc de paraître survolés pour les développeurs avancés (mais pourquoi diable lieraient-ils ce tuto!!) et un brin compliqués voir flous pour les novices. Mais que les novices se rassurent, les tutos à venir reviendrons sur les points importants concernant la syntaxe java et la programmation objet.

1) Donc créons un fichier HelloWorld.java.

Dans ce fichier on déclare la classe HelloWorld :

public class HelloWorld
{

}

Alors de suite, ce qu’il faut retenir sur la déclaration de classes dans un fichier .java :

  • On peut déclarer autant de classes que l’on souhaite dans un fichier java.
  • On ne peut déclarer qu’une seule classe public.
  • Le fichier doit porter le même nom que la classe public s’il y en a une.
  • S’il n’y a pas de classe public dans le fichier, le nom du fichier n’a pas d’importance.

Du coup on va expliquer ce à quoi sert le mot-clef “public”.En java, il y a des niveaux d’accessibilité. Ces niveaux sont indiqués via des mots-clefs appelés “modifiers” en Anglais. En ce qui concerne les classes, il y a deux modifiers d’accessibilité possibles :

  • default. Le mot-clef default correspond au niveau de droit d’accés par défaut. On n’est pas obligé de l’écrire d’ailleurs. Ne rien marquer ou marquer default revient au même. Dans ce cas, la classe n’est visible que par les autres classes de son package.
  • public. Le mot-clef public correspond au niveau d’accés publique. C’est à dire qu’elle est visible par toutes les autres classes, même les classes qui ne sont pas du même package.

Arf, on tire sur la pelotte de laine. On se dit qu’on va juste expliquer à quoi sert le mot-clef public et on se retrouve à utiliser un nouveau gros mot qu’il faut définir.Qu’est-ce qu’un package? Un package est un regroupement de classes. C’est un peu le même principe qu’un répertoire. Un package peut aussi contenir d’autres packages.

L’idée est que, en programmation, on peut avoir envie de réutiliser un ensemble de classes d’un projet à un autre. Regrouper des classes qui se suffisent entre elles dans un même package permet de réutiliser ce package d’une application à une autre. On importe un package via le mot clef import en début de fichier. On déclare que les classes d’un fichier font partie d’un package par le mot-clef package.

2) Le but de notre classe : afficher “HelloWorld” dans une console.

Donc pour afficher HelloWorld, il va nous falloir faire une méthode main. C’est la méthode appelée au lancement d’un programme java…

C’est quoi une méthode?

Pourquoi la méthode main est appelée au lancement?

Comment l’application sait quelle méthode main lancer?

On répondra à toute ces questions juste après ce petit bout de code :

public class HelloWorld
{
public static void main(String[] args)
{
}
}

Alors c’est quoi une méthode? Il faut penser comportement. Une méthode est un comportement pour une instance d’une classe. … On s’enfonce là. Il va falloir tout un cours de programmation objet avec ça. Et bien oui, si vous voulez vraiment faire du java, il va falloir faire un minimum de programmation objet. Mais on y reviendra plus tard, promis. Pour l’instant, pensez plutôt fonction, c’est plus simple. Une méthode est une fonction ayant un ensemble d’arguments passés en paramétre.

Alors pourquoi main est appelée au lancement? Parce que c’est comme ça.

Comment l’application sait quel main lancer? Tout d’abord, une classe ne peut pas déclarer deux méthodes ayant exactement la même signature. La signature c’est le nom de la méthode et le type des arguments passés en paramétre. Donc, on ne peut pas avoir deux méthodes main ayant la même signature dans une même classe. Et si vous vous rappelez bien que l’on ne peut pas avoir deux classes public dans un même fichier et que je vous dis en plus qu’une méthode main ne peut pas être déclarée dans une classe autre que public, alors vous comprenez bien qu’il ne peut y avoir qu’une seule méthode main prenant un tableau de String en paramétre dans un fichier .java.

Mais c’est quoi ce static ? static est un autre mot-clef. Il peut s’appliquer notamment sur des méthodes. Cette méthode est alors spécifique de la classe. Tous les objets instances de cette classe auront alors exactement le même comportement lors de l’appel de cette méthode. En outre, une méthode static peut-être appelée sans avoir besoin d’instancier la classe. Une méthode static ne peut faire appel qu’à des méthodes ou attributs statics. Bon c’est un peu compliqué tout ça si on ne fait pas un peu d’objet avant. Donc on y reviendra quand on fera de l’objet.

Mais c’est quoi ce void ? C’est  encore un mot-clef. Void veut dire que la méthode ne renvoie rien en retour. Quand on écrit une méthode, on est censé déclarer le type de retour. C’est à dire préciser la nature de l’élément retourné par la méthode une fois qu’elle a fini son exécution. Ici on déclare que la méthode ne renvoie rien.

3) Mettons un peu de corps dans notre méthode.

public class HelloWorld
{
public static void main(String[] args)
{
System.out.print(”HelloWorld”);
}
}

System.out : on demande l’attribut public “out” de la classe System (donc out est un attribut static). Si vous ne me croyez pas vous pouvez aller faire un premier tour sur l’api java. “out” est de type PrintStream et posséde une méthode print qui prend en paramétre une String. Pour ceux qui en doutent, “HelloWorld” est une String (chaîne de caractéres).

4) Maintenant il faut qu’on compile ce fichier HelloWorld.java en un bytecode que l’on appelera HelloWorld.class. On pourra ensuite exécuter ce bytecode sur n’importe quelle JVM.

Lancez une console, ou un terminal, comme vous préférez. Ce qui vous semble le moins lourd. :)

Tapez une ligne de commande qui ressemble à ça, modulo le chemin de votre JDK :

/chemin_de_jdk/bin/javac HelloWorld.java

Normalement, si tout se passe bien, vous avez compilé votre première classe java en bytecode. Vous demandez à l’application javac de compiler le fichier HelloWorld.java plus précisément. Cela a pour conséquence de créer un fichier HelloWorld.class.

Maintenant tapez :

/chemin_de_jdk/bin/java HelloWorld

Et là dans votre terminal devrait s’afficher : HelloWorld. Vous avez demandé à l’application java d’interpréter le bytecode HelloWorld.class

Vous avez codé, compilé et exécuté votre premier programme Java. Félicitations!!! ;)