Meilleures pratiques pour la gestion des exceptions Java


J'ai écrit le code suivant récemment; il utilise beaucoup de gestion des exceptions. Je pense que cela rend le code très illisible. Je pourrais raccourcir le code en attrapant une exception générique, telle que

catch (Exception e){
    e.printStackTrace();
}

Mais j'ai aussi entendu dire que la capture d'une exception générique n'est pas une bonne pratique de codage.

public class DataAnalyzerTester {
    /**
     * @param args args[0] stores the filename
     * @exception NoSuchElementException if user attempts to access empty list element
     * @exception ArithmeticException if user attempts to divide by 0
     * @exception ArrayIndexOutOfBoundsException if user supplied less than 3 arguments
     * @exception IOException problems with creating and writing files
     * @exception RuntimeException if user attempts to pass empty list to constructor
     */
    public static void main(String[] args) {

    try{
        //some code

    } catch (NoSuchElementException e) {
        System.out.println("Accessing element that does not exist: " + e.toString());
    } catch (ArithmeticException e) {
        System.out.println("Division by zero: " + e.toString());
    } catch (ArrayIndexOutOfBoundsException e) {
        System.out.println("Please supply a command line arguement that specifies your file path: " + e.toString());
    } catch (IOException e) {
        System.out.println("Other IO errors: " + e.toString());
    } catch (RuntimeException e) {
        System.out.println(e.toString());
    } 
    }
}

Je voudrais savoir s'il existe un moyen meilleur et plus propre d'attraper plusieurs exceptions.

Author: Guan Summy Huang, 2015-09-13

2 answers

Tout d'Abord, sauf si vous avez très une bonne raison, jamais attraper RuntimeException, Exception ou Throwable. Ceux-ci attraperont la plupart de tout ce qui est lancé, et {[3] } attrapera tout, même ces choses que vous n'êtes pas signifiaient pour attraper, comme OutOfMemoryError.

Deuxièmement, évitez d'attraper des exceptions d'exécution à moins qu'elles n'entravent directement le fonctionnement critique de votre programme. (Mais sérieusement, si quelqu'un vous voit attraper un NullPointerException, ils sont dans leur plein les droits de vous appeler sur elle.) Les seules exceptions que vous devriez déranger sont celles que vous devez gérer. De votre liste d'exceptions, la seule avec laquelle vous devriez est IOException. Le reste est le résultat de tests insuffisants ou d'un codage bâclé; ceux-ci ne devraient pas se produire pendant l'exécution normale de votre application.

Troisième, dans Java 7, vous avez la possibilité de faire un multi-catch instruction pour vos exceptions, si les exceptions sont mutuellement exclusif. L'exemple lié fait un bon travail pour l'expliquer, mais si vous rencontriez du code qui lançait à la fois un {[7] } et un SQLException, vous pourriez le gérer comme ceci:

try {
    // Dodgy database code here
catch (IOException|SQLException ex) {
    logger.log(ex);
    throw ex;
}

Cela nettoie un peu les choses, car vous n'avez pas d'énormes chaînes d'exceptions à attraper.

 12
Author: Makoto, 2015-09-13 01:03:45

Tout d'abord, le problème avec les conseils de "meilleure pratique" est qu'il a tendance à trop simplifier la question et la réponse. Puis quelqu'un (comme vous) arrive et remarque que c'est contradictoire.

OMI, la meilleure pratique consiste à prendre des conseils sur les "meilleures pratiques" et les personnes qui utilisent régulièrement cette expression avec un niveau de suspicion sain. Essayez de comprendre vous-même les vrais problèmes et de tirer vos propres conclusions ... plutôt que de simplement compter sur quelqu'un d'autre pour vous dire ce qui est " le mieux pratique".


Alors quel est le problème ici? C'est cette déclaration:

Mais j'ai aussi entendu dire que la capture d'une exception générique n'est pas une bonne pratique de codage.

En fait, ce n'est pas normalement une bonne pratique de codage pour attraper des exceptions génériques comme Exception. Mais c'est la bonne chose à faire dans certaines circonstances. Et votre exemple est celui où il est approprié.

Pourquoi?

Eh bien regardons un cas où attraper Exception est un mauvais idée:

    public void doSomething(...) {
        try {
            doSomethingElse(...);
        } catch (Exception ex) {
            // log it ... and continue
        }
    }

Pourquoi est-ce une mauvaise idée? Parce que ce catchva attraper et gérer des exceptions inattendues; c'est-à-dire des exceptions que vous (le développeur) ne pensiez pas possibles, ou que vous n'avez même pas considérées. C'est OK ... mais ensuite, le code enregistre l'exception et continue de s'exécuter comme si de rien n'était.

C'est le vrai problème ... tentative de récupération d'une exception inattendue.

Les (soi-disant) "meilleures pratiques" "never catch generic exceptions" traite du problème, mais d'une manière grossière qui ne traite pas des cas périphériques. L'un des cas périphériques est que la capture (et la journalisation) d'une exception générique est OK si vous fermez immédiatement l'application ... comme vous êtes en train de faire.

    public void main(...) {
        try {
            // ...
        } catch (Exception ex) {
            // log exception
            System.err.println("Fatal error; see log file");
            System.exit(1);
        }
    }

Comparez maintenant cela avec la version (soi-disant) bonne pratique de votre question. Quelle est la différence?

  1. Votre version produit des diagnostics plus conviviaux / moins alarmants ... jusqu'à une point.
  2. Votre version est beaucoup plus de code.
  3. Votre version n'est pas utile à quelqu'un qui essaie de diagnostiquer le problème car les stacktraces ne sont pas enregistrées.

Et les contrepoints à 1 et 2 sont:

  1. Vous pouvez passer un temps illimité à peaufiner les diagnostics "conviviaux" pour une application, et ne parvenez toujours pas à aider le type d'utilisateur qui ne peut pas ou ne veut pas comprendre ...
  2. Cela dépend également de l'utilisateur type.

Comme vous pouvez le voir, c'est beaucoup plus nuancé que "attraper des exceptions génériques est une mauvaise pratique".

 6
Author: Stephen C, 2018-10-10 03:06:12