Tag Archives: java

Interface et Héritage en Java : Le TamagoTux

J’ai écris précédément un article sur les interfaces, avec des exemples en Java. Voici un autre « exemple », tiré d’un projet personnel, d’utilisation des interfaces, de l’heritage de classes abstraites, de types abstraits. Il s’agit en fait de la partie logique d’un petit jeu, Tamagotux, permettant d’élever votre tux, votre GNU, votre BSD daemon ou Puffy (BlowFish OpenBSD).

Dans cet exemple, l’implémentation n’est modélisé que pour Tux. Nous avons donc une interface Animals, qui fournit les méthodes public de l’animal. On créera ainsi Tux de la manière suivante :

Animals Tamagotux = new Tux() ;

L’interface propose plusieurs méthodes.

Les premières permettent de récupérée ou ajouter des Attribute() à Tux en passant en argument son nom. La méthode pour récupérer un Attribute() retourne un objet Attribute(), son interface est vue plus bas. On peut ensuite locker ou unlocker les actions réalisables sur l’animal. Ainsi, on ne pourra, par exemple, pas lancer le thread ‘Jouer’, lier a l’Attribute() Fun() pendant qu’il mange. On peut ensuite grâce aux deux méthodes [get/set]CurrentAction(), récupérer ou définir l’action courante de Tux. Le getters est plus utile que le setters, mais pour, par exemple stopper une action, il est plus simple de tout simplement détruire l’action courante en la passant à null que de envoyer un signal au thread. Enfin, Animals() expose une dernière méthode, vivre(), qui est lié à un thread, non modélisé ici, qui en fait diminue progressivement les Attribute() défini (faim, fatigue, amusement, etc) et rend l’animal « actionnable ». Une fois l’animal en vie, le boolean IsInitialized passe à true et il devient impossible de lui rajouter des Attribute(). Passons maintenant à la classe abstraite abstractAnimals(), elle a pour but d’implémenter les getters et setters qui sont les mêmes pour la plupart des TamagoTux, dans le cas contraire, les méthodes ne sont pas final, elles peuvent donc être override. Il y a trois attributs, le premier, sans doute le plus important, est une liste d’objet Attribute(), le nom est, je pense, assez explicite que pour détailer son rôle, c’est ici que se trouve tous les objets Attribute() de l’animal (faim, fatigue, etc). On a ensuite un objet du type actionThread, qui contient le thread de l’action courante (manger, dormir, jouer,…) et enfin un boolean qui permet de locker l’appel de nouvelle action, le temps que l’action courante se termine. J’ai utilisé un maximum de thread afin de, premièrement, ne pas geler le GUI le temps de l’action, quand le TamagoTux joue, son niveau d’amusement ne grimpe pas en un 10éme de secondes, il monte progressivement, donc toutes les actions et secondement, les Tamagotux eux-même sont threadé, ce qui permet, dans la même partie, de s’occuper de plusieurs Tamagotux en parallèle, de les faire interagir, et cela, dans la même instance de programme. Les méthodes de abstractAnimals() ne sont donc que les implémentations de méthodes de l’interface Animals() que j’ai expliqué plus haut.

Passons maintenant au second package, le package Attribute.

La encore, une interface, une classe abstraite et des classes final. Comme précédement, la plupart des méthodes de l’interface sont implémentées dans la classe abstraite à l’exception de createThreadedAction() car, le thread d’action lié à chaque Attribute(), varie de l’un à l’autre. D’abord un getters et un setters de la value de l’Attribute() . Ils retournent ou prennent un argument un objet Object,() car on en connait pas le type de la valeur de chaque Attribute(). Dans l’implémentation final de chaque Attribute(), un champ static String est défini avec comme valeur, le type de l’Attribute(). Chaque fois que l’on voudra modifier la valeur de l’Attribute(), on vérifia que l’Object() passé en argument est du type de l’Attribute() avant de faire quoique ce soit. Ensuite, on a un boolean qui permet de locker la valeur de l’Attribute(), par exemple, le nom, une fois fixé, on ne peut par renommer notre animal, on va donc rendre l’Attribute() read-only. (C’est aussi utile pour éviter que plusieurs thread ne travaillent en même temps sur le même Attribute() ). Les Attribute() sont identifiés par un String, initialisé dans le constructeur, et permettant de les rendrent accesible via la méthode getAttribute(). L’attribut Name ne peut être défini qu’une seule et unique fois (lors de la construction de l’objet). Les deux méthodes restantes permettent soit de lancer l’action lié a l’Attribute(), soit de la récupérer (pour par exemple, surveiller le thread lié avec un autre thread qui le prendra en argument). Dans la classe abstraite, on retrouve donc un objet Object() qui contient la valeur de l’attribut, son nom, son threadedAction, le type de l’Attribute() (String, Integer, Float, Boolean, etc) et le locker de value. Ensuite, on implémente les méthodes de l’interface, non implémentées dans la classe final, plus, une méthode privée qui vérifie que le type donné en argument lors de la modification de la valeur de l’Attribute() et le type de la valeur de l’Attribute() correspondent. J’ai ici défini plusieurs classes final, correspondant aux Attribute() de base, la fatigue, la faim, le moral, le fun, le nom. On peut en rajouter d’autre, par exemple l’âge, le sexe, la couleur des yeux, le png lié a sa représentation dans le GUI, etc, etc. Il suffit de rajouter une classe, qui implémente les méthodes de l’interface Attribute() (sans forcément dériver de abstractAttribute() ).

Enfin, le dernier package, les actionThread() liés aux Attribute(). Comme pour les deux précédents, une interface, une classe abstraite, des classe final.

On a donc un interface actionThreaded(), trois méthodes, une pour démarrer le thread, une seconde pour le stopper ‘proprement’. La première passe en fait le boolean started à true, le stop à false. Le thread étant un while(starded), contenu dans un while master, par exemple un while(i<modifier), ou i est un itérateur s’incrémentant à chaque iteration et « modifier » le nombre d’iteration à réaliser. Enfin, la méthode run(), qui est l’action réalisée lors que lancement du thread. La classe abstraire abstractThreadedAction() hérite de la classe Thread() de Java. abstractThreadedAction a un champ attribute de type Object(), qui est l’Attribute() sur lequel il va travailler, un modifier, la valeur a rajouter/supprimer/remplacer dans l’Attribute(), un champ time, qui permet de définir combien de temps le thread durera avant de se terminer, un champ sleepTime, qui est le temps en milliseconde de pause à la fin de chaque itération du thread et enfin le boolean sur son état. Les méthodes startThread() et stopThread() sont implémentées dans la classe abstraite et peuvent être override et la méthode run(), quant à elle, est implémentée dans la classe final, afin de changer le comportement du thread selon l’action à réaliser. Là encore, comme pour les Attribute(), le rajout d’action est très simple via l’implémentation de la classe threadedAction() et l’héritage de java.lang.Thread. L’héritage d’abstractThreadedAction() est lui, optionnel car java.lang.Thread implémente tout le nécéssaire au bon fonctionnement du thread.

Au final, on peut donc, en quelques minutes, créer un nouvel animal :

  1. Créer une classe final en implémentant l’interface Animals
  2. Rajouter des attributs a l’animal. Pour en rajouter de nouveaux, il suffit d’implementer Attribute dans une nouvelle classe
  3. Définir un comportement ou une action pour chaque attribut, ou implémenter threadedAction, ensuite, définir la classe créée comme threadedAction de l’Attribute désiré.

Cette conception reste cependant assez simple. Il y a quelques défauts, notamment le fait que, par simplicité, j’ai toutes les méthodes et attributs en public. Evidemment, dans mon code, la plupart des attributs de classe seront privés et seul les méthodes définient dans les interfaces seront public. Mais, voici un exemple « complet » d’utilisation à la fois des interface et de l’heritage pour d’une part placer la réutilisabilité du code au centre de la conception, permettre une certaine modularité dans la conception et donc, faciliter la mise à jour par la suite et au final, malgré une structure interne assez « complexe », fournir au developpeur/end-user, une interface de quelques méthodes permettant facilement d’exploiter l’intégratilité des fonctionnalitées. Sans interface, avec uniquement de l’héritage, la réalisation aurait à la fois été plus complexe à penser, mais aussi à coder et l’utilisabilité final aurait été grandement déteriorée.

Je vais poster le code du programme d’ici quelques jours afin de permettre de voir, en dehors de la « théorie » ou de la modélisation, les résultats et la facilité d’utilisation.

Les interfaces en Java

Voici un petit cours/tutos sur les interfaces en java. Le but n’est pas d’expliquer en profondeur le fonctionnement des interfaces, cela ayant déjà été fait par pas mal de gens.Pour la théorie je recommande deux ouvrages, le premier, chez Eyrolles, “Programmer en Java” de Claude Delannoy, Ingénieur au CNRS, dans la collection BestOf. Une véritable bible du développeur Java à petit prix (800 pages, 19 € prix couverture) déjà vendu à 250 000 exemplaires, traduit en plusieurs langues (ce qui est remarquable pour un livre technique de ce type). Ce serait un crime de ne pas se jeter dessus. Un second, plus générique, toujours chez Eyrolles, “La programmation Orientée Objet, Cours et Exercices en UML2, Java, C#, C++, Python, PHP et Linq” par Hughes Bersini, Ingénieur physicien et Directeur du Laboratoire sur l’intelligence artificielle à l’ULB (Université Libre de Bruxelles), un pédagogue exceptionnel et ouvert que j’ai d’ailleurs eu l’occasion de rencontrer il y a quelques mois dans le cadre d’un salon sur le logiciel libre. 600 pages +/- à 35 € prix couverture. Bon, ceci étant dit, je pars du principe que la théorie de l’héritage, le polymorphisme, l’abstraction et les règles de bases qui sous-tendent l’OO sont connues (pas forcément maîtrisées). Passons au but de l’article, montrer en quoi les interfaces sont réellement un outil/concept utile à la conception d’un logiciel et offre une réelle abstraction supplémentaire par rapport aux classes abstraites et à l’héritage de classes abstraites. En effet, à la lecture de beaucoup de cours, les interfaces sont souvent très bien expliquées dans la théorie mais pas dans la pratique, ce qui, au final, donne la sensation au lecteur qu’une interface est juste une classe abstraite sans l’implémentation des méthodes de classes.
Pourquoi ? Voici un exemple standard vraiment simple qui ressort dans presque tous les cours/tutos :

Humain.java :

Garçon.java :

Main.java :

Cet exemple est tiré directement d’un cours, considéré comme une référence, paru chez O’reilly (comme la plupart de leurs livres). Ceci ne montre rien des interfaces à part le fait que l’on implémente une interface Humain dans Garçon et que l’on redéfinit la méthode d’interface respirer() dans Garçon. Ensuite on crée un objet Garçon(), nommé Jean puis, on fait respirer Jean. Dans cet exemple, la plupart des lecteurs se disent : “Un Garçon est un humain et il respire… Ok… Mais moi dans mon code, vu que tous les humains respirent, garçons ou filles, et de la même manière, je ne vais pas redéfinir la méthode respirer chaque fois, ça ne me sert a rien ! Hum… Je vais plutôt faire une classe abstraite Humain et Garçon héritera de Humain !” Et cette réaction est légitime, car en effet cet exemple (et la plupart de ceux que l’on trouve) est dénué de sens pour quelqu’un qui aborde le sujet et sort en général du chapitre sur les abstractions. (Dans tous les livres que j’ai, quel que soit le langage, si on parle d’abstraction, le chapitre suivant sera 9 fois sur 10 les interfaces…).

J’ai donc fait un exemple pour rendre justice aux interfaces et que vous compreniez en quoi la redéfinition de méthode est vraiment utile. Voici la situation à modéliser.

“Je veux un tableau d’objet, ces objets seront des êtres vivants, je veux pouvoir les faire mourir et ressusciter selon le type d’êtres vivants.”

Un besoin très simple, J’ai donc une interface Vivant, cette interface a 3 méthodes, la première retourne une valeur booléenne sur l’état de l’être (true ou false), la seconde le tue, la troisième le ressuscite. L’interface est donc un dénominateur commun de méthodes à tous les êtres vivants. Maintenant il faut implémenter cette interface. Nous allons créer basiquement deux classes, Humain et Chat. Sur ces deux types d’êtres vivants on peut implémenter sans aucun souci les comportements demandés dans le besoin et définis dans l’interface. La où la redéfinition, grâce aux interfaces, sera utile, c’est au niveau de la résurrection. En effet, un humain ne peut ressusciter (ou alors il faudrait créer une classe supplémentaire Saint), par contre un chat a plusieurs vies, on peut donc dire qu’il peut “ressusciter”.

Voici le code que l’on obtient avec l’utilisation correcte des interfaces pour ce besoin :

Vivant.java :

Humain.java

Chat.java :

Main.java

Alors, pour le code de l’interface, rien de bien mystérieux. Sur humain on a donc implémenté Vivant, on a défini un attribut boolean livin sur son état, la méthode is_alive() retourne simplement livin, la méthode kill() vérifie que l’humain n’est pas déjà mort, si ce n’est pas le cas (que livin est a true), on le tue, sinon on prévient qu’il est déjà mort et la méthode ressusciter renvoie simplement que JP n’est pas JC. Pour la classe chat, on a le même attribut livin que sur humain, on a juste un attribut intégré en plus contenant le nombre de vies restant au chat, la méthode is_alive a le même comportement que Humain, kill également, par contre ressusciter a un comportement différent. Sur le premier if, on vérifie que le chat a encore des vies et qu’il est mort, si c’est le cas, on le ressuscite en passant livin a true et on lui enlève une vie, si on veut le ressusciter mais qu’il n’est pas mort ou alors qu’il ne lui reste plus de vie on prévient l’utilisateur selon la situation. Enfin, dans main.java, c’est à ce niveau que tout va se jouer. Dans la plupart des cours on aurait créé un objet Chat et un objet Humain, mais les interfaces jouent un rôle d’abstraction, ce qui veut dire que l’on peut créer (comme demandé dans le besoin) un tableau d’objets du type de l’interface. On peut donc créer un tableau de vivants. On initialisera ensuite chaque objet selon le type de vivant, par exemple un chat ou un humain. Et là où l’abstraction est vraiment utile c’est que, vu que ces classes implémentent les mêmes méthodes, celles définies dans l’interface, on peut dans une boucle for par exemple, appeler ses méthodes sans connaître le type ‘final’ de l’objet sur lequel on travaille. On peut donc tuer tous les êtres vivants du tableau sans savoir si on a affaire à un humain, un chat, un chien, un cochon, de plus ce n’est pas le but, on veut tuer les êtres vivants du tableau, on se moque de savoir de quel être vivant il s’agit. Voici le dernier point qui est souvent mal détaillé dans les cours, l’abstraction que les interfaces proposent, ce qui, en plus de forcer la redéfinition, est la différence fondamentale entre classes abstraites et interfaces. Dans main.java on créé donc un array de size[2], un tableau de vivants que l’on nomme etres_vivant, on crée à l’index 0 un chat et à l’index 1 un Humain. Ensuite on a un for(x;x;x) qui parcourt le tableau et qui sur chaque objet, fait des appels de méthodes :

1. Savoir s’il est vivant

2. Le faire mourir

3. Le ressusciter

4. Le ressusciter

5. Le tuer

6. Le ressusciter

7. Savoir s’il est vivant

Ce qui nous donne dans la sortie standard :

C’est tout pour les interfaces, j’espère avoir pu expliquer clairement une des vraies utilités des interfaces. Les exemples ici sont en Java, mais le fonctionnement et la sémantique restent les mêmes dans la plupart des langages OO permettant l’utilisation d’interface (C# par exemple).

Sur ce…

Documentation d’un projet avec Javadoc

Qu’est-ce que JavaDoc ?

JavaDoc est un projet développé par Sun, devenu un standard Java, créé dans le but de fournir de la documentation en HTML depuis les commentaires dans le code La documentation s’écrit avec de commentaires simples et permet d’utiliser des tags spécifiques et des balises html classique. Les tags JavaDoc sont reconnaissable par l’arobase au début du tag, par exemple “@author”

Quoi documenter ?

La documentation peut être de plusieurs types :

  • L’expression de besoin (à renseigner ou traduire la version anglaise).
  • Architecture / Conception – Vue d’ensemble sur le logiciel
  • Technique – Documentation du code
  • Utilisateur – Manuels pour le end-user ou l’administrateur
  • Marketing – Instructions sur le produit

Nous sommes donc avec JavaDoc dans la partie Documentation Technique.

Les bénéfices ?

  • Transparence
  • Compréhensibilité du code pour les développeurs
  • Création de teste faciliter
  • Troubleshooting facilité
  • Facilite le jaugement de l’état d’avancement du projet

Documentation d’une fonction simple

/** Voici la description de la fonction <b>FaireQuelqueChose</b>
* <i>Cette Fonction permet de multiplier par 10 un nombre</i>
* @author Manu404
* @param x  Nombre a multiplier par <i>10</10>
*/

Les 2 premières lignes seront affiché dans le summary de la fonction

La ligne 3 permet de définir l’auteur de la fonction via le tag author
La ligne suivante documente l’argument de la méthode via le tag param suivi du nom de l’argument et d’une description

Pour générer la documentation sous Netbeans il suffit de faire un clic droit sur le nom du projet et cliquer sur “Generate Javadoc”

Les tags JavaDoc

@author
Le nom du développeur
syntaxe : @author <nom_du_developpeur>

@deprecated
Marque la méthode comme dépréciée. Cela signifie que la méthode sera bientôt supprimé et ne doit donc plus être utilisé
Ce tag est compilé, ce qui signifie que un warning  a la compilation sera généré sur un méthode documenté comme depracated est utilisé.
La syntaxe est la même que @author

@exception
Documente une exception lancée par une méthode
Il possède un synonyme, @throws
Syntaxe : @exception <nom_exception> <description_exception>

@param
Définit un paramètre de méthode. Requis pour chaque paramètre.
Syntaxe : @param <nom_du_paramètre> <description>

@return
Documente la valeur de retour.
Syntaxe : @return <description>

@see
Documente une association à une autre méthode ou classe, en bref, un lien vers une autre doc.
Syntaxe : @see <quoi ?>
Par exemple :
@see “Du texte”
@see package.class
Dans ce cas, il y aura deux liens dans le See Also de la documentation

@since
Précise à quelle version de la SDK/JDK une méthode a été ajoutée à la classe.
Syntaxe : @since <texte>

@throws
Documente une exception lancée par une méthode. Un synonyme pour @exception disponible depuis Javadoc 1.2.

@version
Donne la version d’une classe ou d’une méthode.
Syntaxe : @version <texte>

@ code
Permet d’afficher du code sans l’interpréter par la browser
Syntaxe : <code></code>

@ literal
Permet d’afficher du code sans l’interpréter par la browser
Syntaxe : @literal <texte>

Voici donc la même fonction mais plus documenté.
Le code :

Et voici le résultat dans la JavaDoc

Conclusion

Documentez au maximum vos projets, il y a des outils très facile d’utilisation qui existent et les quelques minutes passé a documenté une classe vous ferons gagner un temp précieux dans le cas ou par exemple un autre developpeur se joint a vous et travail sur le projet, il aura une vision assez détaillé de ou en est le projet et que fait çi ou ça.

Les tests unitaires avec JUnit dans Netbeans (6.8)

Qu’est-ce qu’un test unitaire ?

Un teste unitaire est une méthode permettant de tester une partie code (appelé unité). Le teste consiste a vérifier que le retour de l’exécution de la portion de code correspond a ce que l’on attend. Il est exécuté indépendamment du programme en créant un environnement d’exécution spécifique à la portion de code. Cela permet d”eviter de devoir recompiler tout un logiciel pour verifier la correction d’un bug des fois assez difficile a declencher “manuellement” ou pour tester des fonctionnalitées profonde dans le logiciel. Imaginez que vous deviez tester tout open-office a la main, fonction par fonction dans différent user-case. A la place on ecrit un teste qui s’executer sur la portion de code définie. Le test unitaire est souvent mis en place dans les projet basé sur les méthodologies Agile ou l’Extreme Programming. JUnit lui est un framework de test unitaire, décliné sur plusieurs language (NUnit, PHPUnit,…) Il est intégré nativement a Netbeans. Pour cet article je suis en version 6.8 avec JUnit compatible 4.x

1. Environnement de test

Pour comment on vas prendre un projet vierge Testing et y rajouter un classe Function
Voici le contenu des deux fichiers.

Main.java

Function.java

On se limite au strict minimum. Ceci, afin de bien montrer que le test est indépendant de l’exécution du programme main.En effet, aucun appel a Function.FaireQuelqueChose() n’est réalisé, pourtant nous pourrons le tester.
On vas maintenant rajouter le teste : Tools -> Create JUnit Test

Et on valide la création du teste.
A ce moment la l’architecture du projet doit ressembler a cela :

On a donc main, un classe function et un test créé par classe

2.Création d’un test

JUnit a créé un teste par défaut dans FunctionTest.java :

On vas le supprimer et en écrire qui vas vérifier que si on appel FaireQuelqueChose(10) il retourne bien 100.

On a donc par ligne :
1. On écrit sur la sortie console de test le nom du test
2. On initialise x qui sera envoyé en argument a la fonction testé
3. On créé un instance de fonction
4. On définit result qui est le résultat devant être retourné par la fonction
5. On teste la fonction a proprement dit en vérifiant que le résultat et le résultat attendu soit égaux

3. Exécution du test

Pour exécuter le test il suffit de faire un clic droit sur le projet et choisir test.
Ceci devrait nous retourner :

On remarque que un test a réussi et un autre échoue.
Celui que nous avons écrit a réussi car la fonction qui multiplie par 10 l’argument qu’on lui passe
a bien retourné 100. Le second, qui s’effectue sur main a échoué ce qui est normal. Les testes par défauts
créé par JUnit fail tout le temps du fait de l’instruction :

fail(“The test case is a prototype.”);

Supprimez-la et le test sur Main passera

Conclusion

Voila, un article sans prétention pour démystifier un peux cette partie du développement logiciel qui est souvent mis
de coté par les développeurs autodidactes.

Ressources utile pour la suite :
Netbeans : http://netbeans.org/
JUnit : http://www.junit.org/
JUnit Reference Manual : http://kentbeck.github.com/junit/javadoc/latest/