package - Deptinfo

publicité
NFA 035
Compléments Java
Conservatoire National des Arts et Métiers
2013
Guillaume Levieux
Plan du cours
• Les packages
– import, déclaration, visibilité
• Normes de codage proposées par Sun :
– organisation du fichier, commentaires, indentation,
nommage
• Documenter son code : Javadoc
– objectif, formatage, tags
• Tests unitaires : JUnit 4
– principe, assertion, fixtures
Les packages en JAVA
Définition, import
Les packages
• Système d’organisation des types (classes ou
interfaces) qu’on déclare dans notre
programme
• Chaque package définit un espace de
nommage pour les types qui y sont déclarés
– Evite les conflits de noms : on peut donner le même
nom à des types, si leur package est différent
• Nous utilisons le système de fichiers (hiérarchie
de répertoires) pour définir nos packages.
Package et répertoires
• Chaque package (répertoire) contient :
– De 0 à n fichiers .java (unités de compilation)
– De 0 à n autres répertoires (sous packages)
• Chaque unité de compilation (fichier .java)
contient :
– Une seule classe ou interface publique, nommée
comme le fichier qui la contient.
– De 0 a n autres classes ou interfaces, invisibles hors
de l'unité de compilation
Les packages
• Nom d’un package : son chemin d’accès
depuis le package de plus haut niveau, avec
des “.”
• Exemple : java.lang
– Le compilateur connait plusieurs répertoires de
packages.
– L’un de ces répertoires contient un répertoire java,
qui contient lui meme un répertoire lang, qui
contient par exemple le fichier Object.class
• Il existe un package "non nommé", pour les
petits programmes qui ne souhaitent pas
utiliser les packages
Les archives .jar
• Un ensemble de packages peut être publié
sous forme d'archive .jar (Java ARchive)
• C'est un fichier zip des packages et parfois un
fichier manifest :
– Lien vers la classe principale si jar executable
– Lien vers d'autres jar utiles
– Signature numérique…
• Par exemple, le package java.lang est dans
rt.jar, lui meme dans le répertoire lib de votre
JRE
Déclaration du package
• Si une classe est placée dans un package, elle
doit le dire au début du fichier où elle est
déclarée :
– package truc.machin.chose
• Si la classe n’est dans aucun package, pas
besoin de le spécifier au début du fichier et
elle sera placée dans le package sans nom.
Import d'un package
• Il est possible d'accéder aux classes d'un
package depuis un autre package.
• Pour simplifier cet accès, on utilise la
commande import
• Ex :
import java.io.File;
import java.util.ArrayList;
Import d'un package
• "import" ne concerne pas un package, mais
tout ou partie de son contenu :
– import machin.truc est faux !
• On peut importer un type spécifique
– import machin.truc.MaClasse
• On peut importer tous les types d’un package
(le type sera chargé si on l’utilise)
– import machin.truc.*
Import d'un package
• Ne pas oublier : les packages définissent des
espaces de noms.
• On peut accéder à n'importe quelle classe sans
utiliser import :
– Il suffit de préfixer le nom de la classe par son nom
de package (laborieux) :
ex : truc.machin.MaClasse.test(); //methode statique de MaClasse
• Donc import "n’ajoute" pas les types d’un
package :
– Simplement, les types définis dans un package
seront accessibles directement, sans les préfixer de
leur nom de package complet.
Visibilité
• Tous les types publiques de plus haut niveau
d’un même package se voient entre eux
directement
• La hiérarchie n’a aucun impact :
– Une classe du package machin ne voit pas plus une
classe de machin.truc (sous package) qu’une classe
de blah.hop.
Visibilité
• On a accès aux types publiques des autres
packages.
• Le fait d'être du même package apporte des
droits supplémentaires sur les membres des
classes du même package
– Si package différent : on ne voit que les membres
publiques.
– Si même package : on voit aussi les "protected" et
"par defaut"
• Voir aussi si héritage, mais autre cours.
CLASSPATH
• Les chemins de packages sont relatifs.
• Il faut bien indiquer le chemin absolu de la
racine au compilateur et à la JVM.
• Le CLASSPATH permet de dire où se trouvent
les packages sur le disque. On peut aussi le
définir dans l’EDI.
• On donne la racine des répertoires qui
contiennent des packages, ensuite les
directives import donnent le reste du chemin
package-info.java
• Le fichier package-info.java est un fichier
particulier du package.
• Il permet de fournir des informations sur le
package
– annoter le package
– placer des commentaires javadoc qui concernent le
package
Exemple sous Eclipse
Présentation des normes de codage
définies par SUN
Disponibles en ligne
http://www.oracle.com/technetwor
k/java/codeconvtoc-136057.html
Pourquoi des normes de codage ?
• Selon SUN : 80% du coût d’une portion de code
provient de sa maintenance.
• Améliorer la lisibilité du code
• La logique de traitement doit être facilement
assimilable visuellement (identation,
nommage)
• Le code doit être transférable entre différents
auteurs (conventions)
• Vous même oublierez… et deviendrez votre
propre client.
Le nommage des fichiers
• Fichiers sources :
– Contient un type (classe / interface) publique
– Même nom que le type publique
– Extension .java
• Fichiers compilés :
– Bytecode pour la machine virtuelle
– Extension .class
Le contenu des fichiers
On se limite à 2000 lignes de source par classe
Le fichier commence par un commentaire, lié au fichier :
(version, droits d'utilisation)
•
•
•
•
•
•
•
•
•
•
•
•
•
/*
* @(#)Blah.java
1.82 99/03/18
*
* Copyright (c) 1994-1999 Sun Microsystems, Inc.
* 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
* All rights reserved.
*
* This software is the confidential and proprietary information of Sun
* Microsystems, Inc. ("Confidential Information"). You shall not
* disclose such Confidential Information and shall use it only in
* accordance with the terms of the license agreement you entered into
* with Sun.
*/
Le contenu des fichiers
• On donne ensuite les informations relatives
aux packages : package puis import
• package tps.tp1;
• import java.awt.peer.CanvasPeer;
• import java.net.*
Place le fichier dans un package donné : package
Importe les classes situées dans d’autres packages
(.class)
Le contenu des fichiers
• Vient ensuite le commentaire de classe
•
•
•
•
•
•
/**
* Class description goes here.
*
* @version 1.82 18 Mar 1999
* @author Firstname Lastname
*/
• Explique l’utilité de la classe, en donne la version,
l’auteur.
• Différent du commentaire de fichier, utilité logique de
la classe
Le contenu des fichiers
On déclare ensuite la classe ou l'interface
•
•
•
public class Blah extends SomeClass {
/* A class implementation comment can go here. */
Peut être suivi d’un commentaire d’implémentation de
classe (ne concerne que l’implémentation et donc
le/les programmeur de cette classe, inutile dans la
description générale)
Commentaire d’implémentation non extrait, une seule *
Le contenu des fichiers
Ensuite, dans l’ordre, le contenu de la classe :
• Attributs de classe (statiques), dans l’ordre public /
protected / private
• Attributs d’instance, dans l’ordre public / protected /
private
• Les constructeurs
• Les méthodes (groupage logique, pas par portée ou
visibilité)
Indentation
Indentation : espaces ou tabulations en début de ligne
L’indentation est primordiale.
Elle permet de saisir au premier coup d’œil la structure
du code.
Les lignes entre { } définissent un bloc. Les blocs peuvent
être soumis à des structures de contrôle (if, while…),
ce qui crée une hiérarchie.
Chaque fois qu’un bloc est soumis à une structure de
contrôle, toutes ses lignes sont indentées un cran plus
loin que cette dernière.
On indente à une tabulation = 4 espaces. (tab ou espaces,
au choix)
Exemple
int a = 10; //Un énoncé seul,
if(a>10) { //structure de contrôle et ouverture d’un bloc
a = a+1; //Indentation une tab
if(a>20) { //structure de contrôle et ouverture bloc
a = a+3; //Indentation deux tabs
a = a/2; //Indentation deux tabs
a = a-1; //Indentation deux tabs
}//Fin du second bloc
}//Fin du premier bloc
Eclipse
ctrl + shift + F pour auto-format sous Eclipse
Indentation
On limite la taille des lignes de code à environ 80 cars
Si du code dépasse, on coupe :
• Après une virgule
• Après un opérateur
• Au plus haut niveau possible
• On s’aligne avec le début de l’expression, ligne
précédente
• Si c’est illisible -> 8 espaces d’indentation (pour ne
pas cacher les blocs du dessous à 4 espaces)
Indentation
On préfère le premier, on coupe au plus haut niveau
Indentation
C’est avant tout une question de lisibilité…
Indentation
Sur les structure de contrôle, décaler de 8 espaces, pour ne
pas cacher le bloc contrôlé.
Indentation
Pour un operateur ternaire
Commentaires
Commentaires d’implémentation : /*...*/, et //
Ces commentaires expliquent des choix
d’implémentation
Commentaires de documentation: /**...*/
Ils sont extraits par javadoc
Ces commentaires donnent les spécifications d’une
partie de code, les détails liés à l’utilisation et non pas
les détails liés à l’implémentation.
Commentaires en bloc
/*
* Here is a block comment.
*
* Explaining some code.
*/
Toujours précédé d’une ligne blanche
Commentaires sur une ligne
/* Exemple de commentaire sur une ligne */
// Exemple de commentaire sur une ligne
Toujours précédé d’une ligne blanche
Indenté au meme niveau que le code qui le suit
Permet de décrire rapidement la suite du code
Commentaires de fin de ligne
Commentaire très court qui explique une ligne
Commenter une portion de code
Préférer // à /* */ :
- un commentaire déjà présent peut stopper le bloc de
commentaire
- les éditeurs ont des raccourcis pour les ajouter
automatiquement en début de ligne.
Sur Eclipse : raccourci Ctrl+Shift+/ ou Ctrl + Shift + C
Déclarations
Une seule déclaration par ligne.
Plus grande clarté, et encourage les commentaires
Initialiser sur la même ligne (sauf ssi calcul nécessaire)
int nbForces = 0; //Le nombre de forces a ajouter
float speed = 0.0f; //La vitesse du train
Si c’est possible, aligner les déclarations et leur
commentaires.
Déclarations
Placer les déclarations au début des blocs (portée de la variable)
Ne pas attendre l’utilisation de la variable pour la déclarer.
Autorisé uniquement pour les boucles for :
for (int i=0;i<10:i++) {
…
}
Déclarations
Ne pas masquer une déclaration de plus haut niveau,
c’est valide mais dangereux.
Déclarations
‘(‘ juste après le nom de la méthode
‘{‘ sur la même ligne que le nom de méthode
‘}’ indenté comme la méthode (comme pour tout bloc)
{ } autorisé pour bloc null
Méthodes séparées par une ligne blanche
Enoncés
Un énoncé se termine par ‘;’
Un seul énoncé par ligne :
argv++; argc--; //Interdit !!!
Si plusieurs énoncés forment un bloc, indenter en
conséquence.
Toujours utiliser la notation en bloc { } pour les structures
de contrôle (évite les erreurs quand ajout d’une ligne)
Le if
Le do while
Lignes vides
• On place une ligne vide :
– Entre deux méthodes
– Entre les variables locales et le premier énoncé
dans une méthode
– Avant un commentaire en bloc ou sur une ligne
– Pour séparer des sections logiques dans le code
d’un méthode.
Espaces
• On place un espace :
– Après les mots clefs qui utilisent des parenthèses
(while par exemple)
• Attention, pas après les noms de méthodes (on colle la
parenthèse)
• Permet justement de distinguer les mot clefs des méthodes
– Après les virgules dans les listes d’arguments
– Autour des tous les opérateurs binaires sauf ‘point’
– Jamais autour des opérateurs unaires comme
négatif, positif, incrémentation, décrémentation
– Autour des accolades { et }
– Après un cast e.g. int b = (int) a;
Conventions de nommage
• Sun propose des convention pour le nommage
des variables, classes, packages, etc…
• Quel type de noms choisir et comment les
écrire
• Toujours pour rendre le code plus lisible
Nommage des classes
•
•
•
•
•
Ne pas abréger si possible
Une capitale à chaque début de mot
Tous le mots collés
Pas de caractères accentués
Ex
– Raster, Etudiant, ListeChainee, MaClasseAMoi
• Pareil pour interfaces ou classes abstraites.
Nommage des méthodes
• Des verbes
• Toujours éviter les abbréviations
• Première lettre en minuscule
• Ex :
– run(), runFaster(), runVeryVeryFast()
Nommage des variables
• Des noms courts, signifiants, commencent par
une minuscule puis capitale a chaque mot
• Entiers i,j,k…
• Caractères : c,d,e…
• Ex :
– int i;
– float myWidth;
Nommage des constantes
• Mot clef final (qui ne changera plus)
• Toutes en capitales
• Séparées par un ‘_’
final int MAX_WIDTH = 100;
• Utiliser des constantes (pas de +10 ou -12.5f au
milieu du code)
– À part pour les +1 et -1 des incrémentations et
décrémentations et 0.
Nommage des packages
• Tout en minuscule
• [a-z], [0-9]
– com.sun.eng
– com.apple.quicktime.v2
– edu.cmu.cs.bovik.cheese
Variables d’instances et public
• On déclare en général les variables d’instantes
privées, et on utilise des accesseurs
private int nbClients = 0;
public int getNbClients() {
return nbClients;
}
public void setNbClients(int nbClients) {
this.nbClients = nbClients;
}
• Sauf si la classe peut être vue comme un simple
structure de données (pas de méthodes)
• Sous Eclipse : A+Shift+S puis Generate Getters
and Setters
Assignements
• Ne pas faire d’assignement au milieu d’une
expression :
– a = b + (c = i + j);
• Ecrire plutôt
– c = i + j;
– a = b + c;
Operateurs et parenthèses
• Ne pas s’appuyer sur la précédence et
l'associativité des opérateurs :
– x = x * 5 + 2 / 8 > 0 && a++ != 1; //Illisible
– x = ((x * 5) + (2 / 8) > 0) && ((a++) != 1) //Mieux
• Toujours mettre des parenthèses, même si ca
parait évident :
– if ((a > 1) && (b < 0))
Documenter son code
avec Javadoc
Reference disponible sur
http://docs.oracle.com/javase/7/d
ocs/technotes/tools/windows/java
doc.html#referenceguide
Commentaires de documentation
• Comme vu précédemment, on utilise les
commentaires de documentations /** */
• Il sont extrait par le programme javadoc qui va
les utiliser pour générer une documentation
HTML
• Commentaires pout l’utilisateur, pas pour le
programmeur de la classe (pour ca on utilise
/* */, qui n’est pas extrait du code
Commentaires de documentation
• Permet de documenter une classe (interface) ou un de
ses membres
• La documentation se met toujours avant l’objet
documenté dans le fichier.
Commentaires de documentation
• La première phrase du commentaire est
utilisée comme résumé du commentaire total
• Toutes les phrase du début du commentaire
jusqu’au premier @ sont la section de
description principale
• On peut y adjoindre du code HTML
• Ensuite chaque ligne @ permet de définir un
tag particulier
Commentaires de documentation
• Il existe plusieurs tags : @authorv {@code}
{@docRoot} @deprecated @exception etc...
• Les tags entre { } peuvent être placés au milieu
de la description principale
• Tags les plus courants :
–
–
–
–
–
@author : l’auteur
@param : paramètre en entrée d’une méthode
@return : ce que retourne la méthode
@see : renvoie à une autre partie de la doc
@version : numero de version
Ex : commentaire de classe
/**
* A class representing a window on the screen.
* For example:
* <pre>
* Window win = new Window(parent);
* win.show();
* </pre>
*
* @author Sami Shaio
* @version 1.15, 13 Dec 2006
* @see java.awt.BaseWindow
* @see java.awt.Button
*/
class Window extends BaseWindow {
...
}
<pre> permet de garder le formatage intact
Ex : commentaire de variable d’instance
/**
* The X-coordinate of the component.
*
* @see #getLocation()
*/
int x = 1263732;
Ex : commentaire de methode
/**
* Returns the character at the specified index. An index
* ranges from <code>0</code> to <code>length() - 1</code>.
*
* @param index the index of the desired character.
* @return the desired character.
* @exception StringIndexOutOfRangeException
* if the index is not in the range <code>0</code>
* to <code>length()-1</code>.
* @see java.lang.Character#charValue()
*/
public char charAt(int index) {
...
}
Comment compiler la documentation
• On utilise l’utilitaire javadoc.exe présent dans
le répertoire bin du JDK
Tester son code
Junit 4
JUnit
• Principe du développement dirigé par les
tests.
• On réfléchit à l’objet en pensant à ce que son
comportement devra toujours vérifier pour
être correct.
• On met en scène ces cas dans des méthodes
de tests.
• On peut ensuite appeler ces méthodes
automatiquement, pour vérifier que l’objet les
respecte toujours.
JUnit
• Permet de faire très rapidement des tests de
non régression.
• Une modification dans le code peut avoir des
effets inattendus sur le reste du programme
• Grace à JUnit :
– Vous aviez codé des classe
– Vous aviez codé leurs tests
– Vous modifiez une seule classe : il est très simple
de relancer tous les tests pour tester
automatiquement l’ensemble du programme
JUnit
• Permet de tester le comportement des objets.
• Pour chaque classe du programme, on définit
une classe de test JUnit (bonne pratique)
• Quand on lancera une séquence de test :
– Les classes test que l’on a définies seront
instanciées
– Leur méthodes seront appelées et nos tests
effectués
– Toutes les erreurs nous seront signalées.
Assertions
• JUnit utilise des assertions
–
–
–
–
–
assertTrue(...), assertFalse(...)
assertEquals(Object, Object)
assertSame(Object, Object)
assertNull(...)
assertEquals(double expected, double actual,
double delta)
• Exception AssertionFailedError levée si
l’assertion est fausse.
Une classe de test JUnit 4
• On crée une classe comme les autres, pour qui la
classe testée est visible (même package par
exemple)
• Annotation @Test pour les méthodes de test
• Annotation @Before pour une méthode qui sera
toujours effectuée avant chaque test de cette
classe.
• Annotation @After pour une méthode qui sera
effectuée après chaque test de cette classe
• @Before et @After permettent de créer des
Fixtures : fixer l’état dans lequel s’effectue chaque
test.
Exemple classe de test JUnit 4
public class Calc {
public long add(int a, int b) {
return a+b;
}
}
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class CalcTest {
@Test
public void testAdd() {
assertEquals(5, new Calc().add(2, 3));
}
}
Lancer un test JUnit 4
• On exécute cette classe au travers de JUnit
(Eclipse sait par exemple les lancer)
JUnit 4 : Fixture au niveau class
• @BeforeClass
public static void runBeforeClass() {
// run for one time before all test cases
}
• @AfterClass
public static void runAfterClass() {
// run for one time after all test cases
}
JUnit 4 : Gestion des exceptions
• @Test(expected = ArithmeticException.class)
public void divisionWithException() {
// divide by zero
simpleMath.divide(1, 0);
}
• On peut aussi utiliser un try catch et un fail
• public void divisionWithException() {
try {
simpleMath.divide(1, 0);
fail("On aurait du avoir une ArithmeticException");
} catch (ArithmeticException e) {
//Le test est ok !
}
}
JUnit 4 : Gestion des boucles infinies
• @Test(timeout = 1000)
public void retourneJamais() {
for (int i=0;i<10;) {
}
}
Téléchargement