{"id":55,"date":"2017-09-09T15:34:17","date_gmt":"2017-09-09T15:34:17","guid":{"rendered":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/?p=55"},"modified":"2023-04-03T16:11:52","modified_gmt":"2023-04-03T16:11:52","slug":"exceptions-et-assertions","status":"publish","type":"post","link":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/2017\/09\/09\/exceptions-et-assertions\/","title":{"rendered":"Exceptions et Assertions"},"content":{"rendered":"<section>\n<h2>Probl\u00e8me de Fiabilit\u00e9<\/h2>\n<p>Tout programme comporte des erreurs (bugs) ou est susceptible de ge\u0301ne\u0301rer des erreurs (e.g suite a\u0300 une action de l\u2019utilisateur, de l\u2019environnement, etc &#8230;).<\/p>\n<p class=\"fragment\">La fiabilite\u0301 d\u2019un logiciel peut se de\u0301composer en deux grandes proprie\u0301te\u0301s :<\/p>\n<ul>\n<li class=\"fragment\"><b>la robustesse<\/b> qui est la capacite\u0301 du logiciel a\u0300 continuer de fonctionner en pre\u0301sence d\u2019e\u0301ve\u0301nements exceptionnels tels que la saisie d\u2019informations errone\u0301es par l\u2019utilisateur<\/li>\n<li class=\"fragment\"><b>la correction<\/b> qui est la capacite\u0301 d\u2019un logiciel a\u0300 donner des re\u0301sultats corrects lorsqu\u2019il fonctionne normalement.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Exceptions<\/h1>\n<\/section>\n<section>\n<h2>Comment traiter les Erreurs<\/h2>\n<p>Une premi\u00e8re m\u00e9thode consiste<\/p>\n<ul>\n<li class=\"fragment\">\u00e0 pr\u00e9voir les \u00e9rreurs possibles.<\/li>\n<li class=\"fragment\">associer chaque erreur possible avec un code d&#8217;erreur<\/li>\n<li class=\"fragment\">Lorsqu&#8217;une erreur est detect\u00e9e, la fonction retourne le code correspondant<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"fragment\">Chaque appel de fonction doit \u00eatre v\u00e9rifi\u00e9. Un oubli peut entrainer d&#8217;autres erreurs pouvant avoir des cons\u00e9quences tout en passant inaper\u00e7u.<\/p>\n<\/section>\n<section>\n<h2>Comment traiter les Erreurs<\/h2>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nf = openFile(filename); \/\/ Comment signaler une erreur ?\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nf = openFile(filename); \/\/ Comment signaler une erreur ?\r\nif(f == null) {\r\n    \/\/ il y a eu une erreur, mais laquelle?\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nf = openFile(filename); \/\/ Comment signaler une erreur ?\r\nif(f == null) {\r\n    if(getLastError() == 12) {\r\n        \/\/ fichier inexistant par exemple\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nf = openFile(filename); \/\/ Comment signaler une erreur ?\r\nif(f == null) {\r\n    if(getLastError() == 12) {\r\n        \/\/ fichier inexistant par exemple\r\n    }\r\n}\r\nelse {\r\n    \/\/ pas d'erreur\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\">autre exemple, la librarie FMOD en C. Toutes les fonctions retournent un code pour le resultat.<\/p>\n<pre class=\"fragment\"><code class=\"c\" data-trim=\"\">\r\nFMOD_RESULT result = FMOD_System_PlaySound(system, FMOD_CHANNEL_FREE, unSon, 0, NULL);\r\nif(result = FMOD_OK) {\r\n    \/\/ ok\r\n} else if(result == FMOD_ERR_FILE_NOTFOUND) {\r\n    ...\r\n} else if(result == FMOD_ERR_INVALID_SPEAKER) {\r\n    ...\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exceptions Java<\/h2>\n<p>Java propose un m\u00e9canisme : <b>les exceptions<\/b><\/p>\n<ul class=\"fragment\">\n<li>Les diff\u00e9rent types d&#8217;erreurs sont mod\u00e9lis\u00e9s par <span class=\"fragment\">des classes.<\/span><\/li>\n<li class=\"fragment\">La gestion des erreurs est s\u00e9par\u00e9e des instructions normales du programme. Il y a un <b>bloc d&#8217;essai<\/b> et un <b>bloc de traitement d&#8217;erreur<\/b>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Exceptions Java<\/h2>\n<p><b>De\u0301finition<\/b> : <i>Le terme exception de\u0301signe tout e\u0301ve\u0301nement arrivant durant l\u2019exe\u0301cution d\u2019un programme interrompant son fonctionnement normal.<\/i><\/p>\n<p class=\"fragment\">En java, les exceptions sont mate\u0301rialise\u0301es par des instances de classes he\u0301ritant de la classe java.lang.Throwable.<\/p>\n<p class=\"fragment\">A chaque e\u0301ve\u0300nement correspond une sous-classe pre\u0301cise, ce qui peut permettre d\u2019y associer un traitement approprie\u0301.<\/p>\n<\/section>\n<section><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/exceptions-java.png\" alt=\"\" \/><\/section>\n<section>\n<h2>Le bloc <code>try<\/code><\/h2>\n<p><b>De\u0301finition<\/b> : <i>La clause try s\u2019applique a\u0300 un bloc d\u2019instructions correspondant au fonctionnement normal mais pouvant ge\u0301ne\u0301rer des erreurs. (exemple : l&#8217;ouverture d&#8217;un fichier).<\/i><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\ntry {\r\n    ...\r\n    ...\r\n}\r\n                        <\/code><\/pre>\n<p class=\"fragment\"><b>Attention : <\/b>un bloc <code>try<\/code> ne compile pas si aucune de ses instructions n\u2019est susceptible de lancer une exception.<\/p>\n<\/section>\n<section>\n<h2>Le bloc <code>catch<\/code><\/h2>\n<p><b>De\u0301finition<\/b> : <i>La clause catch s\u2019applique a\u0300 un bloc d\u2019instructions de\u0301finissant le traitement d\u2019un type d\u2019erreur. Ce traitement sera lance\u0301 sur une instance de la classe d\u2019exception passe\u0301e en parame\u0300tre.<\/i><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\ntry{\r\n    ...\r\n}\r\ncatch(TypeErreur1 e) {\r\n    ...\r\n}\r\ncatch(TypeErreur2 e) {\r\n    ...\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Blocs <code>try-catch<\/code><\/h2>\n<p>Tout bloc <code>try<\/code> doit e\u0302tre suivit par au moins un bloc <code>catch<\/code> ou par un bloc <code>finally<\/code> (e\u0301tudie\u0301 plus loin).<\/p>\n<p class=\"fragment\">Tout bloc <code>catch<\/code> doit e\u0302tre pre\u0301ce\u0301de\u0301 par un autre bloc <code>catch<\/code> ou par un bloc <code>try<\/code>.<\/p>\n<p class=\"fragment\">Un ensemble compose\u0301 d\u2019un bloc <code>try<\/code> et d\u2019au moins un bloc <code>catch<\/code> est commune\u0301ment appele\u0301 bloc <code>try-catch<\/code>.<\/p>\n<\/section>\n<section>\n<h2>Lever une exception<\/h2>\n<p><b>De\u0301finition<\/b> : <i>Lorsqu\u2019une instruction du bloc d\u2019essai ge\u0301ne\u0300re une erreur et y associe une exception, on dit qu\u2019elle le\u0300ve (lance) cette exception.<\/i><\/p>\n<p class=\"fragment\"><b>De\u0301finition<\/b> : <i>Lorsqu\u2019un bloc de traitement d\u2019erreur est de\u0301clenche\u0301 par une exception, on dit qu\u2019il traite (capture) cette exception.<\/i><\/p>\n<\/section>\n<section>\n<h2>Fonctionnement<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/try-catch1.png\" \/><\/section>\n<section>\n<h2>Fonctionnement<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/try-catch2.png\" \/><\/section>\n<section>\n<h2>Fonctionnement<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/try-catch3.png\" \/><\/section>\n<section>\n<h2>Fonctionnement<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/try-catch4.png\" \/> <a href=\"https:\/\/repl.it\/D0Rs\" target=\"_blank\" rel=\"noopener\">run it!<\/a><\/section>\n<section>\n<h2>Fonctionnement<\/h2>\n<p>Le fonctionnement d\u2019un bloc try-catch est le suivant :<\/p>\n<ol>\n<li class=\"fragment\">si aucune des instructions du bloc d\u2019essai ne lance d\u2019exception, il est entie\u0300rement exe\u0301cute\u0301 et les blocs de traitement d\u2019erreur sont ignore\u0301s.<\/li>\n<li class=\"fragment\">si une des instructions du bloc d\u2019essai lance une exception, alors toutes les instructions du bloc d\u2019essai apre\u0300s elle sont ignore\u0301es et le premier bloc de traitement d\u2019erreur correspondant au type de d&#8217;exception lance\u0301e est ex\u00e9cut\u00e9. Tous les autres blocs de traitement d\u2019erreur sont ignore\u0301s.<\/li>\n<\/ol>\n<\/section>\n<section>\n<h2>Les Types d&#8217;Exceptions<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/exceptions-java.png\" alt=\"\" \/><\/section>\n<section>\n<h2>Lever une exception<\/h2>\n<p><b>De\u0301finition<\/b> : <i>Les exceptions de type <code>Error<\/code> sont re\u0301serve\u0301es aux erreurs qui surviennent dans le fonctionnement de la JVM. Elles peuvent survenir dans toutes les portions du codes.<\/i><\/p>\n<ul class=\"fragment\">\n<li><b>OutOfMemoryError :<\/b> survient lorsque la machine virtuelle n\u2019a plus de place pour faire une allocation et que le GC ne peut en libe\u0301rer.<\/li>\n<li><b>NoSuchMethodError :<\/b> survient lorsque la machine virtuelle ne peut trouver l\u2019imple\u0301mentation de la me\u0301thode appele\u0301e.<\/li>\n<li><b>StackOverflowError :<\/b> survient lorsque la pile de\u0301borde apre\u0300s une se\u0301rie d\u2019appel re\u0301cursif trop profond.<\/li>\n<li>etc&#8230;<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>Les Types d&#8217;Exceptions<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/exceptions-java.png\" alt=\"\" \/><\/section>\n<section>\n<h2>Lever une exception<\/h2>\n<p><b>De\u0301finition<\/b> : <i>Les exceptions de type RuntimeException correspondent a\u0300 des erreurs qui peuvent survenir dans toutes les portions du codes.<\/i><\/p>\n<ul class=\"fragment\">\n<li><b>ArithmeticException :<\/b> division par ze\u0301ro (entiers), etc &#8230;<\/li>\n<li><b>IndexOutOfBoundsException :<\/b> de\u0301passement d\u2019indice dans un tableau.<\/li>\n<li><b>NullPointerException :<\/b> re\u0301fe\u0301rence null alors qu\u2019on attendait une re\u0301fe\u0301rence vers une instance.<\/li>\n<li>etc&#8230;<\/li>\n<\/ul>\n<\/section>\n<section>\n<pre><code class=\"java\" data-trim=\"\">\r\nint a = 0;\r\ntry {\r\n    int x = 1 \/a;\r\n    System.out.println(\" x = \" + x); }\r\ncatch (ArithmeticException e)\r\n{\r\n    System.out.println(\"division par 0 : 1 \/ \" + a);\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Les Types d&#8217;Exceptions<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/exceptions-java.png\" alt=\"\" \/><\/section>\n<section>\n<h2>Lever une exception<\/h2>\n<p><b>De\u0301finition<\/b> : <i>On appelle <b>exception contro\u0302le\u0301e<\/b>, toute exception qui he\u0301rite de la classe Exception et qui n\u2019est pas une RuntimeException. Elle est dite contro\u0302le\u0301e car le compilateur ve\u0301rifie que toutes les me\u0301thodes l\u2019utilisent correctement.<\/i><\/p>\n<ul>\n<li><b>EOFException :<\/b> fin de fichier &#8230;<\/li>\n<li><b>FileNotFoundException :<\/b> fichier inexistant.<\/li>\n<li><b>ClassNotFoundException :<\/b> erreur dans le chargement d\u2019une classe.<\/li>\n<li>etc&#8230;<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>Exceptions Control\u00e9es<\/h2>\n<p>Toute exception contro\u0302le\u0301e, du JDK ou personnalise\u0301e, pouvant e\u0302tre e\u0301mise dans une me\u0301thode doit e\u0302tre :<\/p>\n<p>&nbsp;<\/p>\n<ul>\n<li>soit captur\u00e9e dans cette me\u0301thode. Elle est alors lance\u0301e dans un bloc try auquel est associe\u0301 un catch lui correspondant.<\/li>\n<li>soit e\u0302tre indique\u0301es dans le prototype de la me\u0301thode a\u0300 l\u2019aide du mot cle\u0301 <code>throws<\/code>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Exemple<\/h2>\n<p>On veut faire une fonction qui supprime le fichier &#8220;\/temp.txt&#8221;<\/p>\n<p>On peut utiliser la m\u00e9thode <code>Files.delete(Path p)<\/code> <a href=\"https:\/\/docs.oracle.com\/javase\/7\/docs\/api\/java\/nio\/file\/Files.html#delete(java.nio.file.Path)\" target=\"_blank\" rel=\"noopener\">documentation<\/a>.<\/p>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"\/temp.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"\/temp.txt\").toPath();\r\n    Files.delete(file); \/\/ peut lancer une exception!!\r\n                        \/\/ NoSuchFileException ou\r\n                        \/\/ DirectoryNotEmptyException ou\r\n                        \/\/ IOException ou\r\n                        \/\/ SecurityException ou\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"\/temp.txt\").toPath();\r\n    try {\r\n    \tFiles.delete(file);\r\n    } catch (NoSuchFileException x) {\r\n    \tSystem.err.format(\"no such file: %s%n\", file);\r\n    }\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"\/temp.txt\").toPath();\r\n    try {\r\n    \tFiles.delete(file);\r\n    } catch (NoSuchFileException x) {\r\n    \tSystem.err.format(\"no such file: %s%n\", file);\r\n    }\r\n    \/\/ Que ce passe-t'il si un autre type est lanc\u00e9 :\r\n    \/\/ DirectoryNotEmptyException ou\r\n    \/\/ IOException ou\r\n    \/\/ SecurityException ou\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    try {\r\n    \tFiles.delete(file);\r\n    } catch (NoSuchFileException x) {\r\n    \tSystem.err.format(\"no such file: %s%n\", file);\r\n    } catch (IOException x) {\r\n    \tSystem.err.format(\"delete error: %s%n\", x);\r\n    }\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    try {\r\n    \tFiles.delete(file);\r\n    } catch (NoSuchFileException x) {\r\n    \tSystem.err.format(\"no such file: %s%n\", file);\r\n    } catch (IOException x) {\r\n            \/\/ Les Exceptions DirectoryNotEmptyException\r\n            \/\/ h\u00e9ritent de IOException donc seront captur\u00e9es ici\r\n    \tSystem.err.format(\"delete error: %s%n\", x);\r\n    }\r\n\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    try {\r\n    \tFiles.delete(file);\r\n    } catch (NoSuchFileException x) {\r\n    \tSystem.err.format(\"no such file: %s%n\", file);\r\n    } catch (IOException x) {\r\n    \tSystem.err.format(\"delete error: %s%n\", x);\r\n    }\r\n\r\n    \/\/ Les Exceptions SecurityException h\u00e9ritent de\r\n    \/\/  RuntimeException donc ce n'est pas obligatoire de les attraper\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<p><a class=\"fragment\" href=\"https:\/\/repl.it\/D0XV\" target=\"_blank\" rel=\"noopener\">run it<\/a><\/section>\n<section>\n<h2>Solution 2<\/h2>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() throws IOException, NoSuchFileException {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\nf();\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() throws IOException, NoSuchFileException {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\nf(); \/\/ peut jeter une exception\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() throws IOException, NoSuchFileException {\r\n    Path file = new File(\"test.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\n    try {\r\n        f(); \/\/ peut jeter une exception\r\n    }\r\n    catch(IOException e) {\r\n            \/\/ NoSuchFileException h\u00e9rite de IOException\r\n            \/\/ Donc sera captur\u00e9e ici\r\n        System.out.println(e);\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() throws IOException \/\/pas besoins de pr\u00e9ciser les type d\u00e9riv\u00e9\r\n{\r\n    Path file = new File(\"test.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\n    try {\r\n        f(); \/\/ peut jeter une exception\r\n    }\r\n    catch(IOException e) {\r\n            \/\/ NoSuchFileException h\u00e9rite de IOException\r\n            \/\/ Donc sera captur\u00e9e ici\r\n        System.out.println(e);\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic static void f() throws IOException\r\n{\r\n    Path file = new File(\"test.txt\").toPath();\r\n    Files.delete(file);\r\n}\r\npublic static void main(String[] args) {\r\n    try {\r\n        f(); \/\/ peut jeter une exception\r\n    } catch (NoSuchFileException x) {\r\n        \/\/ C'est parfois quand m\u00eame utile de sp\u00e9cialiser\r\n        \/\/ la gestion des exceptions\r\n        System.err.format(\"no such file: %s%n\", file);\r\n    }\r\n    catch(IOException e) {\r\n        System.out.println(e);\r\n    }\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exceptions Personnalis\u00e9es<\/h2>\n<p><img decoding=\"async\" class=\"stretch\" src=\"https:\/\/pagesperso.lip6.fr\/Maria.Gradinariu\/sites\/Maria.Gradinariu\/IMG\/html\/c4-figures\/exceptions-java.png\" alt=\"\" \/><\/section>\n<section>\n<h2>Exceptions Personnalis\u00e9es<\/h2>\n<p>On peut d\u00e9finir ses propres exceptions en d\u00e9finissant une sous-classe de la classe <code>Exception<\/code>.<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class MonException extends Exception {\r\n  private int x;\r\n  public MonException(int x) {\r\n    this.x = x;\r\n  }\r\n  public String toString() {\r\n    return \"Valeur incorrecte : \" + x;\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Lancer une exception<\/h2>\n<p><b>De\u0301finition<\/b> : <i>Pour lancer une exception, on peut utiliser la clause <code>throw<\/code>.<\/i><\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class Main {\r\n  public static void main (String[] args) {\r\n    try {\r\n      int size = Integer.parseInt(args[1]);\r\n      if (size &lt; 0) {\r\n        throw new MonException(size);\r\n      }\r\n      int[] tab = new int[size] ;\r\n      System.out.println(\"Taille du tableau :\" + tab.length);\r\n    } catch (MonException e) {\r\n      System.err.println(e);\r\n    }\r\n  }\r\n}\r\n\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Lancer une exception<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class Main {\r\n  public static void main (String[] args) {\r\n    try {\r\n      int size = Integer.parseInt(args[1]);\r\n      if (size &lt; 0) {\r\n        throw new MonException(size);\r\n      }\r\n      int[] tab = new int[size] ;\r\n      System.out.println(\"Taille du tableau :\" + tab.length);\r\n    } catch (MonException e) {\r\n      System.err.println(e);\r\n    }\r\n  }\r\n}\r\n\r\n                      <\/code><\/pre>\n<pre><code class=\"bash\" data-trim=\"\">\r\n&gt;&gt; java TestTableau 3\r\nTaille du tableau : 3\r\n                      <\/code><\/pre>\n<pre><code class=\"bash\" data-trim=\"\">\r\n&gt;&gt; java TestTableau -1\r\nValeur incorrecte : -1\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exceptions Personnalis\u00e9es<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic class ExceptionCordiale extends Exception {\r\n  public ExceptionCordiale(String err) {\r\n    super(\"Je suis au regret de vous annoncer que \"+err+\". Veuillez nous excuser pour la g\u00e8ne occasionn\u00e9e.\");\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exceptions Personnalis\u00e9es<\/h2>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nclass TestTableau {\r\n  private static double sqrt(int i) {\r\n    if(i &lt; 0) throw new ExceptionCordiale(\"le nombre ne doit pas \u00eatre n\u00e9gatif\");\r\n    return Math.sqrt(i);\r\n  }\r\n  public static void main (String args) {\r\n    int i = Integer.parseInt(args[1]);\r\n    System.out.println(sqrt(i));\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\n  class TestTableau {\r\n    private static double sqrt(int i) {\r\n      if(i &lt; 0) throw new ExceptionCordiale(\"le nombre ne doit pas \u00eatre n\u00e9gatif\"); \/\/ Probl\u00e8me, exception non trait\u00e9e.\r\n      return Math.sqrt(i);\r\n    }\r\n    public static void main (String args) {\r\n      int i = Integer.parseInt(args[1]);\r\n      System.out.println(sqrt(i));\r\n    }\r\n  }\r\n                        <\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\nclass TestTableau {\r\n  private  static double sqrt(int i) throws ExceptionCordiale {\r\n    if(i &lt; 0) throw new ExceptionCordiale(\"le nombre ne doit pas \u00eatre n\u00e9gatif\");\r\n    return Math.sqrt(i);\r\n  }\r\n  public static void main (String[] args) {\r\n    int i = Integer.parseInt(args[1]);\r\n    try {\r\n      System.out.println(sqrt(i));\r\n    } catch(Exception e) {\r\n      System.out.println(e);\r\n    }\r\n  }\r\n}\r\n                        <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nclass TestTableau {\r\n  private  static double sqrt(int i) throws ExceptionCordiale {\r\n    if(i &lt; 0) throw new ExceptionCordiale(\"le nombre ne doit pas \u00eatre n\u00e9gatif\");\r\n    return Math.sqrt(i);\r\n  }\r\n  public  static void main (String[] args) {\r\n    try {\r\n      int i = Integer.parseInt(args[1]); \/\/ Peut aussi lancer une exception\r\n      System.out.println(sqrt(i));\r\n    } catch(Exception e) {\r\n      System.out.println(e);\r\n    }\r\n  }\r\n}\r\n                          <\/code><\/pre>\n<\/section>\n<section>\n<h2>Le bloc <code>finally<\/code><\/h2>\n<p><b>De\u0301finition<\/b> : <i>La clause <code>finally<\/code> d\u00e9finit un bloc d\u2019instruction qui sera ex\u00e9cut\u00e9 m\u00eame si une exception est lanc\u00e9e dans le bloc d\u2019essai. Elle permet de forcer la bonne terminaison d\u2019un traitement en pr\u00e9sence d\u2019erreur, par exemple : la fermeture des fichiers ouverts.<\/i><\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\ntry {\r\n  ...\r\n}\r\ncatch (...) {\r\n  ...\r\n}\r\nfinally {\r\n  ...\r\n}\r\n                        <\/code><\/pre>\n<\/section>\n<section>\n<h2>Le bloc <code>finally<\/code><\/h2>\n<p>Le code de la clause finally sera toujours ex\u00e9cut\u00e9 :<\/p>\n<ul>\n<li class=\"fragment\">si la clause try ne lance pas d\u2019exception : ex\u00e9cution apr\u00e8s le try (m\u00eame s\u2019il contient un return).<\/li>\n<li class=\"fragment\">si la clause try lance une exception trait\u00e9e par un catch : ex\u00e9cution apr\u00e8s le catch (m\u00eame s\u2019il contient un return).<\/li>\n<li class=\"fragment\">si la clause try lance une exception non trait\u00e9e par un catch : ex\u00e9cution apr\u00e8s le lancement de l\u2019exception.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"fragment\">Attention : <i>un appel \u00e0 la m\u00e9thode <code>System.exit()<\/code> dans le bloc try ou dans un bloc catch arr\u00eate l\u2019application sans passer par la clause finally<\/i><\/p>\n<\/section>\n<section>\n<h2>La clause finally : exemple.<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nclass TestTableau b {\r\n\r\n  public static void main (String[] args) {\r\n    try{\r\n      int x = Integer.parseInt(args[1]);\r\n      if (x &lt; 0) {  throw new MonException(x);  }\r\n      System.out.println(x);\r\n    }\r\n    catch (MonException e) {\r\n      System.err.println(e);\r\n    }\r\n    finally {\r\n      System.out.println(\"Tout est bien qui ...\");\r\n    }\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<pre><code class=\"bash\" data-trim=\"\">\r\n&gt;&gt; java TestTableau -1\r\nValeur incorrecte : -1\r\nTout est bien qui ...\r\n\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Pourquoi propager les exceptions ?<\/h2>\n<p>Plus une m\u00e9thode est \u00e9loign\u00e9e de la m\u00e9thode main dans la pile d\u2019ex\u00e9cution, moins elle a de vision globale de l\u2019application. Une m\u00e9thode peut donc avoir du mal \u00e0 savoir traiter une exception.<\/p>\n<p>Il est souvent difficile pour une m\u00e9thode effectuant un petit traitement de d\u00e9cider si une exception est critique :<\/p>\n<p><i>&#8220;Il vaut mieux laisser remonter une exception que de d\u00e9cider localement d\u2019interrompre l\u2019ensemble du programme.&#8221;<\/i><\/p>\n<\/section>\n<section>\n<h2>Comment faire remonter une exceptions ?<\/h2>\n<p>Pour traiter une exception, on distingue finalement trois m\u00e9thodes :<\/p>\n<ul>\n<li>Traitement local : l\u2019exception est trait\u00e9e dans la m\u00e9thode.<\/li>\n<li>Traitement d\u00e9l\u00e9gu\u00e9 : l\u2019exception, qui n\u2019est pas trait\u00e9e dans la m\u00e9thode, est transmise \u00e0 la m\u00e9thode appelante.<\/li>\n<li>Traitement local partiel : l\u2019exception est trait\u00e9e dans la m\u00e9thode, puis re-lanc\u00e9e pour \u00eatre transmise \u00e0 la m\u00e9thode appelante.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Traitement d\u00e9l\u00e9gu\u00e9<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n\r\npublic void f() throws FileNotFoundException {\r\n  monFichier = new FileInputStream(\".\/essai.txt\");\r\n}\r\npublic void g() {\r\n  try {\r\n    f();\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement d\u00e9l\u00e9gu\u00e9 \u00e0 g\");\r\n  }\r\n}\r\n\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Traitement local partiel<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n\r\npublic void f() throws FileNotFoundException {\r\n  try {\r\n    monFichier = new FileInputStream(\".\/essai.txt\");\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement local par f\");\r\n    throw e;\r\n  }\r\n}\r\npublic void g() {\r\n  try {\r\n    f();\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement d\u00e9l\u00e9gu\u00e9 \u00e0 g\");\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Traitement local partiel 1<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n\r\npublic void f() throws FileNotFoundException {\r\n  try {\r\n    monFichier = new FileInputStream(\".\/essai.txt\");\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement local par f\");\r\n    throw e;\r\n  }\r\n}\r\npublic void g() {\r\n  try {\r\n    f();\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement d\u00e9l\u00e9gu\u00e9 \u00e0 g\");\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Traitement local partiel 2<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n\r\npublic void f() throws MonException {\r\n  try {\r\n    monFichier = new FileInputStream(\".\/essai.txt\");\r\n  } catch (FileNotFoundException e) {\r\n    System.err.println(\"Traitement local par f\");\r\n    throw new MonException();\r\n  }\r\n}\r\npublic void g() {\r\n  try {\r\n    f();\r\n  } catch (MonException e) {\r\n    System.err.println(\"Traitement d\u00e9l\u00e9gu\u00e9 \u00e0 g\");\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Aucun traitement?<\/h2>\n<p>Si une exception remonte jusqu\u2019\u00e0 la m\u00e9thode main sans \u00eatre trait\u00e9e par cette m\u00e9thode :<\/p>\n<ul>\n<li class=\"fragment\">l\u2019ex\u00e9cution du programme est stopp\u00e9e.<\/li>\n<li class=\"fragment\">le message associ\u00e9 \u00e0 l\u2019exception est affich\u00e9, avec une description de la pile des m\u00e9thodes travers\u00e9es par l\u2019exception<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"fragment\">Remarque : <i>Seul le thread qui a g\u00e9n\u00e9r\u00e9 l\u2019exception non trait\u00e9e meurt ; les autres threads continuent leur ex\u00e9cution.<\/i><\/p>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Assertions<\/h1>\n<\/section>\n<section>\n<h2>Principe de la programmation par contrats<\/h2>\n<p>Pour v\u00e9rifier la correction d\u2019un programme lors de son d\u00e9veloppement, il est utile de v\u00e9rifier certains invariants\/conditions \u00e0 des endroits bien choisis du programme.<\/p>\n<p class=\"fragment\">Cette approche a \u00e9t\u00e9 formalis\u00e9e et g\u00e9n\u00e9ralis\u00e9e dans la programmation par contrats.<\/p>\n<p class=\"fragment\">En Java, elle peut s\u2019appuyer sur le m\u00e9canisme des assertions qui permet au programmeur de v\u00e9rifier dynamiquement des conditions<\/p>\n<\/section>\n<section>\n<h2>Localisation des points critiques<\/h2>\n<p>Lors du d\u00e9veloppement d\u2019une application, plusieurs points critiques peuvent \u00eatre \u00e0 l\u2019origine de bug. On s\u2019attachera \u00e0 contr\u00f4ler :<\/p>\n<ul>\n<li class=\"fragment\">les pr\u00e9-conditions, au d\u00e9but d\u2019une m\u00e9thode.<\/li>\n<li class=\"fragment\">les post-conditions, \u00e0 la fin d\u2019une m\u00e9thode.<\/li>\n<li class=\"fragment\">les invariants de classe, qui doivent \u00eatre pr\u00e9serv\u00e9s avant et apr\u00e8s l&#8217;appel des m\u00e9thodes de la classe.<\/li>\n<li class=\"fragment\">les invariants de boucle.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Le mot cl\u00e9 <code>assert<\/code><\/h2>\n<p>Java 1.4 introduit un nouveau mot-cl\u00e9 assert qui permet d\u2019ins\u00e9rer dans le code des assertions qui :<\/p>\n<ul>\n<li class=\"fragment\">ex\u00e9cutent une condition et v\u00e9rifient qu\u2019elle retourne <code>true<\/code>.<\/li>\n<li class=\"fragment\">lancent une erreur <code>AssertionError<\/code> (fille de la classe Error), si la condition est false.<\/li>\n<\/ul>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nassert x &lt; y ;\r\n<\/code><\/pre>\n<p class=\"fragment\">Une expression peut suivre l\u2019assertion. Facultative, elle ne sert qu\u2019a d\u00e9finir le message d\u2019erreur li\u00e9 \u00e0 l\u2019AssertionError.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nassert x == 0 : \"x n\u2019est pas nul\" ;\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Les invariants logiques<\/h2>\n<p>Les invariants logiques sont tous les invariants induits naturellement par la logique s\u00e9mantique du code. Sous forme d\u2019assertions, ils permettent de se pr\u00e9munir contre toute erreur dans les futures modifications.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\ncoef = (x * x) \/ (1 + (x * x));\r\nassert coef &lt; 1 : \"coef est compris entre 0 et 1\";\r\nassert 0 &lt;= coef : \"coef est compris entre 0 et 1\";\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Les invariants de contr\u00f4le de flux<\/h2>\n<p>Les invariants de contr\u00f4le de flux sont essentiels au bon d\u00e9roulement des programmes. Ils assurent le bon enchainement des instructions. Pour en v\u00e9rifier le respect, il suffit de placer des assert sur des lignes qui ne devraient pas \u00eatre atteintes<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nswitch(x) {\r\n  case -1 : ...\r\n  case 0 : ...\r\n  case 1 : ...\r\n  case default : assert false : x;\r\n}\r\n                    <\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nvoid foo() {\r\n  for (...) {\r\n    if (...) return;\r\n  }\r\n  assert false : \"On devrait \u00eatre sortie de foo\";\r\n}\r\n                    <\/code><\/pre>\n<\/section>\n<section>\n<h2>Les pr\u00e9conditions<\/h2>\n<p>Lorsque l\u2019on code une m\u00e9thode priv\u00e9e, on peut faire la supposition que toutes ses invocations respecteront certaines conditions implicites appel\u00e9es pr\u00e9conditions.<\/p>\n<p class=\"fragment\">Cette supposition est possible car on garde le contr\u00f4le sur tous les appels \u00e0 cette m\u00e9thode. L\u2019ajout d\u2019assert offrent une m\u00e9thode simple pour v\u00e9rifier le respect des pr\u00e9conditions.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\nprivate int updateEtu(Etudiant etu, int note) {\r\n  assert 0 &lt;= note &amp;&amp; note &lt;= 20 ;\r\n  ...\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Les postconditions<\/h2>\n<p>Les postconditions expriment des propri\u00e9t\u00e9s qui doivent \u00eatre satisfaites en fin d\u2019ex\u00e9cution d\u2019une m\u00e9thode. Elles permettent de v\u00e9rifier que le traitement de la m\u00e9thode s\u2019est bien d\u00e9roul\u00e9 et que la valeur de retour est conforme aux sp\u00e9cifications.<\/p>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic int sum (int a, int b) {\r\n\r\n  int result = a + b ;\r\n\r\n  return result;\r\n}\r\n<\/code><\/pre>\n<pre class=\"fragment hide-with-next-fragment\"><code class=\"java\" data-trim=\"\">\r\npublic int sum (int a, int b) {\r\n\r\n  int result = a + b ;\r\n  assert result - a == b : \"Sum of \" + a + \" + \" + b + \" returned \" + result;\r\n  return result;\r\n}\r\n<\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic int sum (int a, int b) {\r\n  assert (Integer.MAX_VALUE - a &gt;= b) : a + \" + \" + b + \" is too large.\";\r\n  int result = a + b ;\r\n  assert result - a == b : \"Sum of \" + a + \" + \" + b + \" returned \" + result;\r\n  return result;\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Les invariants de classe<\/h2>\n<p>Imaginons que l&#8217;on construise une classe stockant des objets qui les garde toujours tri\u00e9s.<\/p>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic void insert(Object o) {\r\nassert this.isSorted() : \"Il y a du d\u00e9sordre ici\";\r\n...\r\n}\r\n\r\n<\/code><\/pre>\n<pre class=\"fragment\"><code class=\"java\" data-trim=\"\">\r\npublic void add(Object o) {\r\n  int _old_size = maCollection.size();\r\n  this.maCollection.add(o);\r\n  assert this.maCollection.size() == _old_size + 1;\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Ex\u00e9cution avec ou sans assertions<\/h2>\n<p>Les v\u00e9rifications li\u00e9e aux assertions, utiles en p\u00e9riode de test, ralentissent l\u2019ex\u00e9cution de l\u2019application. Elles sont donc d\u00e9sactiv\u00e9es par d\u00e9faut.<\/p>\n<p>Pour activer les assertions (sauf dans les classes syst\u00e8me) :<br \/>\n<code>java -ea MonProgrammeAvecAssert<\/code><\/p>\n<p>Pour activer seulement pour une classe :<br \/>\n<code>java -ea:NomDuneClasse MonProgrammeAvecAssert<\/code><\/p>\n<p>Pour activer seulement pour un paquetage et ses sous-paquetages (les &#8230; sont \u00e0 mettre tels quels) :<br \/>\n<code>java -ea:nom.dun.package... MonProgrammeAvecAssert<\/code><\/p>\n<p>Pour d\u00e9sactiver seulement pour un paquetage (ou une classe) :<br \/>\n<code>java -ea -da:nom.dun.package... MonProgrammeAvecAssert<\/code><\/p>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Mauvais pratiques<\/h2>\n<p>Une mauvaise pratique avec les assertions, peut \u00eatre la plus courante, consiste \u00e0 les utiliser pour v\u00e9rifier une pr\u00e9condition sur une m\u00e9thode public.<\/p>\n<p>En effet le contrat ne sera pas v\u00e9rifi\u00e9 quand les assertions seront d\u00e9sactiv\u00e9es en production, or le programmeur n\u2019a pas le contr\u00f4le sur toutes les invocations de la m\u00e9thode. Dans ce cas il vaut mieux utiliser les exceptions \u00e0 la place des assertions.<\/p>\n<\/section>\n<section>\n<h2>Mauvais pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic float inverseAuCarre (int x) {\r\n  assert x == 0 : \"Le param\u00e8tre est nul\";\r\n  ...\r\n}\r\n<\/code><\/pre>\n<p>NON<\/p>\n<\/section>\n<section>\n<h2>Bonnes pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npublic float inverseAuCarre (int x) {\r\n  if (x == 0) {\r\n    throw new ArithmeticException(\"Le param\u00e8tre est nul\");\r\n  }\r\n  ...\r\n}\r\n<\/code><\/pre>\n<p>Oui!!<\/p>\n<\/section>\n<section>\n<h2>Mauvais pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nassert connect() : \"La connection est impossible\";\r\n<\/code><\/pre>\n<p>NON. En effet que se passe-t-il si on d\u00e9sactive les assertions?<\/p>\n<\/section>\n<section>\n<h2>Bonnes pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n  final boolean ok = connect();\r\n    assert ok : \"La connection est impossible\";\r\n<\/code><\/pre>\n<p>mieux!<\/p>\n<\/section>\n<section>\n<h2>Mauvais pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nassert r1 == r2 : \"r1 et r2 devraient \u00eatre \u00e9gaux\";\r\n<\/code><\/pre>\n<p>NON. Attention \u00e0 l&#8217;\u00e9galit\u00e9 entre nombres flottants.<\/p>\n<\/section>\n<section>\n<h2>Bonnes pratiques<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nassert abs(r1 - r2) &lt; 0.0001 : \"r1 et r2 devraient \u00eatre \u00e9gaux\";\r\n<\/code><\/pre>\n<p>mieux!<\/p>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Tests Unitaires<\/h1>\n<\/section>\n<section>Dans les applications non critiques, l\u2019\u00e9criture des tests a longtemps \u00e9t\u00e9 consid\u00e9r\u00e9e comme une t\u00e2che secondaire.<\/p>\n<p class=\"fragment\">Maintenant, il est conseill\u00e9 d&#8217;\u00e9crire des tests en m\u00eame temps, voire m\u00eame avant la m\u00e9thode \u00e0 tester (Test Driven Development)<\/p>\n<p class=\"fragment\">Ici, on s&#8217;int\u00e9resse au <code>tests unitaires<\/code> qui permettent la v\u00e9rification des fonctions une par une.<\/p>\n<\/section>\n<section>D\u00e9finition : <i>La couverture de code consiste \u00e0 s\u2019assurer que le test conduit \u00e0 ex\u00e9cuter l\u2019ensemble des instructions pr\u00e9sentes dans le code \u00e0 tester.<\/i><\/p>\n<p>Le but est de cr\u00e9er des tests qui permettent d&#8217;ex\u00e9cuter le plus d&#8217;instructions possibles.<\/p>\n<\/section>\n<section>\n<h2>JUnit<\/h2>\n<p>Nous allons utiliser le framework JUnit 4<\/p>\n<\/section>\n<section>\n<h2>JUnit et les annotations<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\n\r\nimport org.junit.*;\r\nimport static org.junit.Assert.*; \/\/ import toutes les fonctions static de la class org.junit.Assert\r\npublic class TestFoobar {\r\n  @BeforeClass\r\n  public void setUpClass() {\r\n    \/\/ Code ex\u00e9cut\u00e9 avant l\u2019ex\u00e9cution du premier test\r\n    \/\/ et de la premiere ex\u00e9cution de la m\u00e9thode @Before\r\n  }\r\n  @AfterClass\r\n  public void tearDownClass() {\r\n    \/\/ Code ex\u00e9cut\u00e9 apr\u00e8s l\u2019ex\u00e9cution des tous les tests\r\n  }\r\n  @Before\r\n  public void setUp() {\r\n    \/\/ Code ex\u00e9cut\u00e9 avant chaque test\r\n  }\r\n  @After\r\n  public void tearDown() {\r\n    \/\/ Code ex\u00e9cut\u00e9 apr\u00e8s chaque test\r\n  }\r\n  @Test\r\n  public void test() {\r\n    assertTrue(true);\r\n  }\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Assertions JUnit<\/h2>\n<p>Avec JUnit, la plus petite unit\u00e9 de tests est l\u2019assertion dont le r\u00e9sultat de l\u2019expression bool\u00e9enne indique un succ\u00e8s ou une erreur. Il d\u00e9finit une s\u00e9rie d\u2019assertion nomm\u00e9es <code>assertXXX()<\/code> qui sont h\u00e9rit\u00e9es de la classe <code>junit.framework.Assert<\/code> :<small><\/small><\/p>\n<ul>\n<li class=\"fragment\"><code>assertTrue()<\/code> : v\u00e9rifie que la valeur fournie en param\u00e8tre est vraie<\/li>\n<li class=\"fragment\"><code>assertFalse()<\/code> : v\u00e9rifie que la valeur fournie en param\u00e8tre est fausse<\/li>\n<li class=\"fragment\"><code>assertNull()<\/code> : v\u00e9rifie que l\u2019objet fourni en param\u00e8tre soit null<\/li>\n<li class=\"fragment\"><code>assertNotNull()<\/code> : v\u00e9rifie que l\u2019objet fourni en param\u00e8tre ne soit pas null<\/li>\n<li class=\"fragment\"><code>assertSame()<\/code> : v\u00e9rifie que les deux objets fournis en param\u00e8tre font r\u00e9f\u00e9rence \u00e0 la m\u00eame entit\u00e9<\/li>\n<li class=\"fragment\"><code>assertNotSame()<\/code> : v\u00e9rifie que les deux objets fournis en param\u00e8tre ne font pas r\u00e9f\u00e9rence \u00e0 la m\u00eame entit\u00e9<\/li>\n<li class=\"fragment\"><code>assertEquals()<\/code> : v\u00e9rifie l\u2019\u00e9galit\u00e9 de deux valeurs de type primitif ou objet (en utilisant la m\u00e9thode equals())<\/li>\n<\/ul>\n<\/section>\n<section>\n<h2>Exemple<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nimport org.junit.*;\r\nimport static org.junit.Assert.*;\r\npublic class TestPerson {\r\n  private Person p1;\r\n  private UPMCPerson p2;\r\n\r\n\r\n  @Before\r\n  public void setUp() {\r\n    p1 = new Person(\"alice\", 1977) ;\r\n    p2 = new UPMCPerson(\"bob\", 1978) ;\r\n  }\r\n  @After\r\n  public void tearDown() {\r\n    p1 = null;\r\n    p2 = null;\r\n  }\r\n  @Test\r\n  public void testGetName() {\r\n    assertEquals(\"person should have the given name\", p1.getName(), \"alice\");\r\n    assertEquals(\"person should have the given name\", p2.getName(), \"bob\");\r\n  }\r\n  @Test\r\n  public void testEquals() {\r\n    assertFalse(\"different person should be different\", p1.equals(p2));\r\n  }\r\n}\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Ex\u00e9cution de JUnit<\/h2>\n<pre><code class=\"bash\" data-trim=\"\">\r\njavac -cp .:junit-4.XX.jar TestPerson.java\r\n<\/code><\/pre>\n<pre><code class=\"java\" data-trim=\"\">\r\njava -cp .:junit-4.XX.jar:hamcrest-core-1.3.jar org.junit.runner.JUnitCore TestPerson\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemple 2<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\nimport org.junit.*;\r\nimport static org.junit.Assert.*;\r\npublic class SampleTest {\r\n  private java.util.List emptyList;\r\n\r\n  @Before\r\n  public void setUp() {\r\n    emptyList = new java.util.ArrayList();\r\n  }\r\n  @After\r\n  public void tearDown() {\r\n    emptyList = null;\r\n  }\r\n  @Test\r\n  public void testSomeBehavior() {\r\n    assertEquals(\"Empty list should have 0 elements\", 0, emptyList.size());\r\n  }\r\n  @Test(expected=IndexOutOfBoundsException.class)\r\n  public void testForException() {\r\n    Object o = emptyList.get(0);\r\n  }\r\n}\r\n<\/code><\/pre>\n<\/section>\n<\/section>\n<section>\n<section class=\"toc-pause\">\n<h1>Commentaires et Documentation<\/h1>\n<\/section>\n<section>\n<h2>Les commentaires<\/h2>\n<p><i>Les commentaires sont des portions du code source ignor\u00e9es par le compilateur ou l\u2019interpr\u00e9teur, car ils ne sont pas n\u00e9cessaires \u00e0 l\u2019ex\u00e9cution du programme. Ils sont souvent utilis\u00e9s pour expliquer : la structure code, le fonctionnement des algorithmes, le sens des variables, les optimisations, &#8230;<\/i><\/p>\n<p>Un commentaire ne doit pas paraphraser le code. Il est inutile si le code est d\u00e9j\u00e0 assez clair.<\/p>\n<\/section>\n<section>\n<h2>Les Tags<\/h2>\n<p>Il existe deux types de tags :<\/p>\n<ul>\n<li class=\"fragment\">@tag : les tags standards<\/li>\n<li class=\"fragment\">{@tag} : les tags qui seront remplac\u00e9s par une valeur.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"fragment\">Ces tags peuvent \u00eatre utilis\u00e9s pour documenter :<\/p>\n<ul>\n<li class=\"fragment\">globalement le programme (fichier overview.html)<\/li>\n<li class=\"fragment\">des packages (fichier package.html ou package-info.java)<\/li>\n<li class=\"fragment\">des classes et interfaces<\/li>\n<li class=\"fragment\">des constructeurs et m\u00e9thodes<\/li>\n<li class=\"fragment\">des attributs<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>packages, classes et interfaces<\/h2>\n<p>Pour documenter les packages, on peut utiliser :<\/p>\n<ul>\n<li class=\"fragment\"><b>@author texte :<\/b> pr\u00e9cise le ou les auteur(s)<\/li>\n<li class=\"fragment\"><b>@version texte :<\/b> num\u00e9ro de version du packages<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p class=\"fragment\">Pour documenter les classes et interfaces, on peut utiliser :<\/p>\n<ul>\n<li class=\"fragment\"><b>@author texte :<\/b> pr\u00e9cise le ou les auteur(s)<\/li>\n<li class=\"fragment\"><b>@version texte :<\/b> num\u00e9ro de version de l\u2019\u00e9l\u00e9ment<\/li>\n<li class=\"fragment\"><b>@deprecated texte :<\/b> permet de pr\u00e9ciser qu\u2019un \u00e9l\u00e9ment est d\u00e9pr\u00e9ci\u00e9.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>M\u00e9thodes et constructeurs<\/h2>\n<p>&nbsp;<\/p>\n<ul>\n<li class=\"fragment\"><b>@version texte :<\/b> num\u00e9ro de version de l\u2019\u00e9l\u00e9ment<\/li>\n<li class=\"fragment\"><b>@deprecated texte :<\/b> permet de pr\u00e9ciser que la m\u00e9thode est d\u00e9pr\u00e9ci\u00e9e<\/li>\n<li class=\"fragment\"><b>@param nom_param\u00e8tre description du param\u00e8tre :<\/b> d\u00e9fini un param\u00e8tre d\u2019une m\u00e9thode<\/li>\n<li class=\"fragment\"><b>@exception nom_exception description :<\/b> exception pouvant \u00eatre lev\u00e9e par une m\u00e9thode<\/li>\n<li class=\"fragment\"><b>@throws nom_exception description :<\/b> identique \u00e0 @exception<\/li>\n<li class=\"fragment\"><b>@return texte :<\/b> description de la valeur de retour de la m\u00e9thode<\/li>\n<li class=\"fragment\"><b>{@inheritDoc} :<\/b> recopie de la documentation de l\u2019entit\u00e9 de la classe m\u00e8re<\/li>\n<\/ul>\n<p>I I I I I I I&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Les tags g\u00e9n\u00e9riques<\/h2>\n<p>En plus des tags sp\u00e9cifiques aux diff\u00e9rents \u00e9l\u00e9ments, on peut utiliser :<\/p>\n<ul>\n<li><b>@docRoot : <\/b>chemin relatif de la racine de la documentation<\/li>\n<li><b>{@link} : <\/b>ins\u00e8re un lien vers un \u00e9l\u00e9ment de la documentation<\/li>\n<li><b>{@linkplain} : <\/b>identique \u00e0 link dans une police normale<\/li>\n<li><b>@see entit\u00e9 : <\/b>r\u00e9f\u00e9rence \u00e0 un autre \u00e9l\u00e9ment<\/li>\n<li><b>@since texte : <\/b>version o\u00f9 l\u2019\u00e9l\u00e9ment a \u00e9t\u00e9 ajout\u00e9<\/li>\n<li><b>{@literal texte} : <\/b>permet d\u2019ins\u00e9rer plus facilement les caract\u00e8res sp\u00e9ciaux sans les interpr\u00e9ter<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Remarque<\/h2>\n<p>Les textes correspondant aux diff\u00e9rents tags sont libres, mais les caract\u00e8res li\u00e9s au HTML comme &lt; ou &gt; sont interpr\u00e9t\u00e9s sp\u00e9cialement par javadoc. Pour \u00e9crire &lt;, on doit donc utiliser <code>&amp;lt;<\/code>.<\/p>\n<\/section>\n<section>\n<h2>G\u00e9n\u00e9ration de la documentation<\/h2>\n<p>Pour g\u00e9n\u00e9rer la documentation, on utilise la commande <code>javadoc<\/code> suivie d\u2019une liste de fichiers java.<\/p>\n<p>Les options les plus couramment utilis\u00e9es :<small><\/small><\/p>\n<ul>\n<li><code>-d &lt;dir&gt;<\/code> : permet de choisir le r\u00e9pertoire dans lequel sera g\u00e9n\u00e9r\u00e9e la documentation ;<\/li>\n<li><code>-author<\/code> : permet de prendre en compte les tag @author ;<\/li>\n<li><code>-version<\/code> : permet de prendre en compte les tag @version ;<\/li>\n<li><code>-public<\/code> : limite la documentation aux classes publiques ;<\/li>\n<li><code>-protected<\/code> : limite la documentation aux classes et aux membres publics et prot\u00e9g\u00e9s (par d\u00e9faut) ;<\/li>\n<li><code>-package<\/code> : limite la documentation aux classes et aux classes et aux membres publics, prot\u00e9g\u00e9s et ceux accessibles aux classes d\u2019un m\u00eame package ;<\/li>\n<li><code>-private<\/code> : g\u00e9n\u00e8re la documentation pour toutes les classes et tous les membres.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<\/section>\n<section>Attention, pour utiliser correctement les accents avec la javadoc, il faut pr\u00e9ciser les encodages avec les options suivantes :<small><\/small><\/p>\n<ul>\n<li><code>-encoding<\/code> : sp\u00e9cifie l\u2019encodage utilis\u00e9 dans les sources java.<\/li>\n<li><code>-docencoding<\/code> : sp\u00e9cifie l\u2019encodage qui sera utilis\u00e9 pour g\u00e9n\u00e9rer les fichiers de documentation HTML.<\/li>\n<li><code>-charset<\/code> : permet d\u2019ajouter dans le code source HTML l\u2019header Content-Type avec l\u2019encodage sp\u00e9cifi\u00e9, ce qui permet au navigateur d\u2019utiliser directement le bon encodage.<\/li>\n<\/ul>\n<p><small><\/small>&nbsp;<\/p>\n<p>Pour obtenir une doc HTML en utf8 avec des sources en latin1 :<\/p>\n<pre><code class=\"bash\" data-trim=\"\">\r\njavadoc -encoding ISO-8859-1 -docencoding utf8 -charset utf8 *.java\r\n<\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemple : Documentation d&#8217;un package<\/h2>\n<p>Depuis Java 5.0 on peut utiliser directement la syntaxe javadoc pour documenter les packages.<br \/>\nPour cela, il faut ajouter dans le r\u00e9pertoire correspondant au package un fichier <code>package-info.java<\/code> qui contient une seule ligne java <code>package &lt;nomPackage&gt; ;<\/code>.<\/p>\n<pre><code class=\"java\" data-trim=\"\">\r\n  \/**\r\n  * Package contenant un super jeu\r\n  * @author Quentin Bramas\r\n  * @version 2.0\r\n  *\/\r\n  package supergame;\r\n<\/code><\/pre>\n<p>&nbsp;<\/p>\n<\/section>\n<section>\n<h2>Exemple : Documentation d&#8217;une classe<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npackage supergame ;\r\n\/**\r\n* Classe g\u00e9n\u00e9rique pour une IA\r\n* @see <a href=\"https:\/\/fr.wikipedia.org\/wiki\/Intelligence_artificielle\">wikipedia<\/a>\r\n* @author Quentin Bramas\r\n* @version 1.00\r\n*\/\r\npublic class IA {\r\n\r\n  int pos=0;\r\n  \/**\r\n  * M\u00e9thode simulant la course de l'IA\r\n  * @param dist distance parcourue par l'IA\r\n  * @return retourne la position actuelle\r\n  *\/\r\n  public int courir (int dist) {\r\n    return pos += dist ;\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Exemple : Documentation d&#8217;une classe<\/h2>\n<pre><code class=\"java\" data-trim=\"\">\r\npackage supergame ;\r\n\r\n\/**\r\n* Classe d'IA difficile\r\n* @author Quentin Bramas\r\n* @version 1.00\r\n*\/\r\npublic class IAHard extends IA {\r\n  private boolean visible = true ;\r\n  \/**\r\n  * Teste la visibilit\u00e9 de l'IA\r\n  * @return true si l'IA est visible\r\n  *\/\r\n  public boolean isVisible () {\r\n    return visible ;\r\n  }\r\n  \/** {@inheritDoc} et cache l'IA *\/\r\n  @Override\r\n  public int courir (int dist) {\r\n    this.hide();\r\n    return super.courir(dist);\r\n  }\r\n  \/**\r\n  * cache l'IA (du coup elle est vachement difficile \u00e0 battre)\r\n  *\/\r\n  private void hide() {\r\n    this.visible = false;\r\n  }\r\n}\r\n                      <\/code><\/pre>\n<\/section>\n<section>\n<h2>Commande <code>javadoc<\/code><\/h2>\n<pre><code class=\"bash\" data-trim=\"\">\r\njavadoc -author -private -version  -encoding utf8 -docencoding utf8 -charset utf8 -d doc supergame\/*.java<\/code><\/pre>\n<\/section>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>Probl\u00e8me de Fiabilit\u00e9 Tout programme comporte des erreurs (bugs) ou est susceptible de ge\u0301ne\u0301rer des erreurs (e.g suite a\u0300 une action de l\u2019utilisateur, de l\u2019environnement, etc &#8230;). La fiabilite\u0301 d\u2019un logiciel peut se de\u0301composer en deux grandes proprie\u0301te\u0301s : la robustesse qui est la capacite\u0301 du logiciel a\u0300 continuer de fonctionner en pre\u0301sence d\u2019e\u0301ve\u0301nements exceptionnels [&hellip;]<\/p>\n","protected":false},"author":55,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-55","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/55","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/users\/55"}],"replies":[{"embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/comments?post=55"}],"version-history":[{"count":1,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/55\/revisions"}],"predecessor-version":[{"id":56,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/posts\/55\/revisions\/56"}],"wp:attachment":[{"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/media?parent=55"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/categories?post=55"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wp-systeme.lip6.fr\/potop-butucaru\/wp-json\/wp\/v2\/tags?post=55"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}