Exceptions B. Liskov, Program Development in Java, chap. 4 Exceptions
Objectif Apprendre à manipuler et à documenter systématiquement les exceptions Vers la spécification de programmes
Des procédures partielles vers les exceptions Procédure Domaine : arguments doivent en être membres Range: le résultat /** * REQUIRES: n, d > 0 * EFFECTS : returns the greatest common divisor of n and d. */ public static int gcd( int n, int d) Procédure partielle Spécification -> l’appelant doit s’assurer que d > 0 -> l’implémentation peut ignorer ce test
Des procédures partielles vers les exceptions En général, l’usage des procédures partielles est une mauvaise idée car si l’argument n’appartient pas au domaine, le comportement de la procédure est imprévisible (boucle infinie, valeur erronée..) Les erreurs ne seront pas nécessairement détectée immédiatement Difficile à déverminer, source d’erreurs plus graves Les programmes ne sont pas robustes Un programme est robuste s’il continue à se comporter raisonnablement même en présence d’erreurs. Dégradation gracieuse Il continue à fournir des résultats (approximatifs) même en présence d’erreurs Donne un message d’erreur significatif Ne cause pas de dommages aux données persistentes
Informer l’appelant d’un problème Utiliser des procédures totales Informer l’appelant d’un problème /** * REQUIRES: * EFFECTS : if n > 0, returns n! else return 0 */ public static int fact( int n) Utiliser un résultat pour fournir cette information Pas satisfaisant z = x + Num.fact(y) est valide quelque soit y Int r = Num.fact(y) If (r > 0) z = x + r; else … Il n’y a peut-être pas de valeur disponible, new Vector().get(i) Lancer une exception Approche qui permet de donner de l’information sur les situations non usuelles dans tous les cas.
Mécanisme des exceptions Distinguer les situations non usuelles des situations normales Les séparer du flot normal de contrôle
Spécifications Signature : throws liste_exceptions; Description dans la clause EFFECTS /** * EFFECTS : if “n” is non-positive, throws NonPositiveException, * else returns the factorial of “n” */ public static int fact (int n) throws NonPositiveException
Spécifications et exceptions Lorsqu’une procédure a des effets de bords, il faut expliquer clairement quel est l’effet des exceptions sur ceux-ci Les modifications doivent être décrites explicitement dans chaque cas où elles se produisent; si aucune modification n’est décrite, cela indique qu’il n’y en a aucune. /** * REQUIRES: all elements of “v” are Integers * MODIFIES: v * EFFECTS : if “v” is null, throws NullPointerException, * if “v” contains an element larger than “x” throws NotSmallException; * else add ”x” to “v” */ public static void addMax (Vector v, Integer x) throws NullPointerException, NotSmallException « v » est modifié seulement si la procédure se termine normalement
Hiérarchie des exceptions Checked exception: L’exception doit être énumérée dans la signature de la méthode L’appelant doit la traiter obligatoirement sinon erreur de compilation, e.g. PropertyVetoException Unchecked exception : l’exception n’a pas besoin d’apparaître dans la signature Le compilateur ne vérifie pas si l’appelant traite l’exception, e.g. ClassCastException Pour les spécifications, toutes les exceptions (checked et unchecked) doivent apparaître dans la signature Throwable Error Exception checked exception RuntimeException (uncheckedException) An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch e.g. VirtualMachineError
Définition des exceptions public class NonPositiveIntegerException extends Exception { public NonPositiveIntegerException() { super();} public NonPositiveIntegerException(String arg0) { super(arg0); } public NonPositiveIntegerException(String arg0, Throwable arg1) { super(arg0, arg1); } public NonPositiveIntegerException(Throwable arg0) { super(arg0); } Convention : le nom de la classe se termine par exception Bonne pratique : définir un package qui regroupe les exceptions A throwable contains a snapshot of the execution stack of its thread at the time it was created. a message string that gives more information about the error. a cause: another throwable that caused this throwable to get thrown. The cause facility is new in release 1.4. It is also known as the chained exception facility, as the cause can, itself, have a cause, and so on, leading to a "chain" of exceptions, each caused by another
Lancer, capturer, propager les exceptions Lancer une exception If (n < 0) throws new NotPositiveException(« Num.fact »); try … catch … finally L’exception, si elle n’est pas capturée dans la procédure appelante, sera automatiquement propagée à l’appelant de l’appelant si La classe de l’exception ou aucune de ses superclasses n’est énumérée dans l’entête de la procédure appelante Ou si la classe de l’exception hérite de RuntimeException
//TCP client makes connection to server, sends request and receives reply import java.net.*; import java.io.*; public class TCPClient { public static void main (String args[]) { // arguments supply message and hostname of destination Socket s = null; try{ int serverPort = 7896; s = new Socket(args[1], serverPort); DataInputStream in = new DataInputStream( s.getInputStream()); DataOutputStream out = new DataOutputStream( s.getOutputStream()); out.writeUTF(args[0]); // UTF is a string encoding String data = in.readUTF(); System.out.println("Received: "+ data) ; }catch (UnknownHostException e) { System.out.println("Sock:"+e.getMessage()); }catch (EOFException e){System.out.println("EOF:"+e.getMessage()); }catch (IOException e){System.out.println("IO:"+e.getMessage());} }finally {if(s!=null) try {s.close();} catch (IOException e) {System.out.println("close:"+e.getMessage());}} }
Design Quand utiliser une exception? Quel type d’exception utiliser (checked ou unchecked)? Exception =/= erreur Un mécanisme pour attirer l’attention de l’appelant sur un cas particulier L’élément recherché n’est pas dans la liste Une exception à un niveau peut correspondre à un cas normal à l’autre IndexOutOfRangeException -> Fin de boucle au niveau supérieur Pas toutes les erreurs qui mènent à des exceptions Enregistrement erroné sauter l’enregistrement et continuer Doit être documenté le cas échéant dans la spécification
Quand utiliser les exceptions ? Pour éliminer les contraintes des clauses REQUIRES Ces contraintes ne devraient demeurer que pour des raisons d’efficacité Ex.: searchSorted si le contexte d’utilisation est tellement limité que l’on peut être assuré que ces contraintes seront respectées Pour éviter d’encoder de l’information dans des résultats Ne pas rendre -1, mais lancer une exception Rendre une valeur encodant une telle information serait par contre acceptable dans un contexte d’utilisation très local
Checked vs unckecked exceptions ? Checked exception Ces exceptions doivent être traitées dans l’appelant ou déclarées dans la clause throws Une certaine protection est assurée par le compilateur
Checked vs unckecked exceptions ? Unchecked exception Implicitement propagée vers l’appelant Ne pas s’appuyer sur le code (qui devrait éventuellement être écrit) pour tenir compte des erreurs de programmation L’exception peut être capturée par inadvertance try { x=y[n]; i = Arrays.search(z, x); } catch (indexOutOfBoundsException e) { // handle IndexOutOfBoundsException from use of array « y » } // code continues assuming problem has been fixed D’où vient le problème ? Celui de y[n] ou celui de search ? La source d’une erreur ultérieure peut devenir très difficile à retracer
Checked vs unckecked exceptions ? Utiliser les exception unchecked Seulement si On s’attend à ce que les programmeurs vont écrire du code qui va assurer que l’exception ne surviendra pas parce que Il existe une façon pratique et peu coûteuse d’éviter l’exception IndexOutOfBounds Le contexte d’utilisation est local Autrement utiliser les exception checked
Programmation défensive Écrire chaque procédure pour qu’elle se protège des erreurs Source d’erreurs Autres procédures Matériel L’usager Un moyen de donner de l’information sur les erreurs sans encombrer le flot normal d’exécution