62 votes

Est-ce une bonne pratique connue d'utiliser un gros try-catch par méthode en java ?

J'ai passé un entretien récemment et l'examinateur voulait que je fasse un test technique pour vérifier mes connaissances. Après l'avoir terminé, il m'a donné son avis sur la manière dont je m'en étais sorti, ce à quoi je ne m'attendais pas et que j'ai apprécié, car peu d'examinateurs le font s'ils ne veulent pas vous engager.

Il m'a dit que l'une des choses qu'il trouvait mauvaises dans mon code était que j'utilisais plus d'un bloc try-catch dans chaque méthode que j'écrivais. Cela attire mon attention car je trouve cela intéressant.

Je pense actuellement que je devrais créer des blocs try-catch dans lesquels il y a un bloc de code sémantiquement distinct qui a une ou plusieurs méthodes qui peuvent lancer des exceptions devant être attrapées. La seule exception à cette règle que j'ai suivie est que si deux méthodes lèvent le même type d'exception, je ferais mieux de les placer dans des blocs try-catch différents afin de distinguer clairement lors du débogage où et pourquoi une exception a été levée.

Cela diffère fortement de ce que l'interviewer voulait que je fasse. L'utilisation d'un seul bloc try-catch par méthode est-elle une bonne pratique connue ? S'il s'agit d'une bonne pratique connue, quels en sont les avantages ?

EDIT : J'apprécie grandement vos réflexions à ce sujet, c'est très bien. Mais notez bien que je demande si c'est une bonne pratique connue. C'est à dire, si la plupart des programmeurs sont d'accord sur ce point, et ou si cela est écrit comme une bonne pratique dans un livre.

0 votes

0 votes

J'ai posé une question similaire : Combien d'instructions dans une instruction try/catch ?

11 votes

Je suis d'accord avec votre point de vue. Les intervieweurs n'ont pas toujours raison.

44voto

Bartosz Bilicki Points 304

Pour moi, deux blocs try-catch rendent la plupart des méthodes trop longues. Cela obscurcit l'intention si la méthode fait plusieurs choses.

Avec deux blocs try-catch, il fait au moins quatre choses, pour être précis

  • deux cas pour le flux principal (deux blocs d'essai)
  • deux cas pour la gestion des erreurs (blocs catch)

Je préférerais faire des méthodes courtes et claires pour chaque bloc try-catch, comme par exemple

private getHostNameFromConfigFile(String configFile, String defaultHostName) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(configFile));
        return reader.readLine();
    } catch (IOException e) {
        return defaultHostName;
    }
}
public Collection<String> readServerHostnames(File mainServerConfigFile, File  backupServerConfigFile) {
    String mainServerHostname=getHostNameFromConfigFile(mainServerConfigFile,"default- server.example.org");
    String backupServerHostName=getHostNameFromConfigFile(backupServerConfigFile,"default- server.example.ru")
    return Arrays.asList(mainServerHostname,backupServerHostName);
}

Robert C. Martin, dans "Clean Code", passe au niveau supérieur en suggérant :

si le mot clé "try" existe dans une fonction, il doit être le tout premier mot de la fonction et il ne doit rien y avoir après les blocs catch/finally.

Je remanierais certainement la méthode avec deux blocs try/catch séparés en méthodes plus petites.

4 votes

J'aime plus votre réponse car vous avez trouvé ce que j'essayais de trouver ; c'est-à-dire une bonne référence renommée qui suggère ou encourage d'écrire seulement un try-catch par méthode/fonction, et dit les raisons de le faire. Il semble que finalement je vais apprendre quelque chose de mon interlocuteur.

35voto

OldCurmudgeon Points 16615

Je dirais que si vous vous retrouvez à emballer deux blocs de code distincts avec try/catch vous devriez envisager de refactoriser ces blocs en méthodes distinctes. Si vous avez utilisé ce modèle lors de votre entretien, vous avez peut-être mal compris votre interlocuteur.

Il est parfaitement possible d'utiliser deux try/catch si l'algorithme l'exige. J'ai souvent utilisé un try/catch dans un bloc de capture pour assurer un nettoyage sûr, de sorte qu'une déclaration générale n'est pas possible.

6 votes

+1 Accepté. Une méthode ne doit servir qu'à un seul objectif.

3 votes

En outre, si vous intégrez deux blocs de code distincts dans un même try/catch, vous ne pouvez pas mettre en œuvre un algorithme de récupération approprié dans le bloc catch sans devoir faire la distinction entre les deux cas, en utilisant un "if", ce qui va à l'encontre de l'objectif du catch et le rend plus compliqué que nécessaire.

2 votes

C'est la meilleure réponse car elle reconnaît le problème réel.

14voto

dharam Points 2107

Pour répondre à votre question, lorsque nous parlons des JVM modernes qui appliquent en fait beaucoup d'optimisations dans le code, lorsque vous écrivez un code qui est inefficace, la JVM introduit automatiquement des optimisations.

Veuillez vous référer à la réponse dans ( Java : frais généraux liés à la saisie/utilisation de blocs "try-catch" ? ).

La question des bonnes pratiques n'a donc pas beaucoup d'importance.

À titre personnel, je pense qu'il ne faut pas encapsuler quoi que ce soit dans une try-catch , static , synchronized etc. inutilement.

Rendons notre code plus lisible pour ceux qui y travailleront. Si une exception est attrapée, il est préférable d'indiquer explicitement quelle partie du code la déclenche.

Pas de devinette pour le lecteur, c'est pour cela que les JVM sont intelligentes, écrivez comme vous voulez, améliorez la situation pour les humains et la JVM s'occupe de la partie optimisation.

EDITAR: J'ai lu beaucoup de livres et je n'ai pas trouvé d'endroit où il est dit qu'une seule grosse prise d'essai est meilleure que plusieurs petites.

D'ailleurs, de nombreux membres de la communauté des développeurs pensent le contraire.

2 votes

Merci @dharam, c'est le genre de réponse que je cherchais. Chacun d'entre nous a des raisons de penser d'une manière ou d'une autre à manipuler ces blocs try-catch pour un code plus propre, ou pour de meilleures performances. Bien que si les gens sont d'accord avec vous, c'est-à-dire que ce n'est pas une bonne pratique connue, alors je trouve que ce n'est pas une bonne façon d'utiliser une préférence personnelle pour juger un candidat à un emploi. Je m'attendrais à être jugé sur la base de ce qui est communément admis, puis à ce qu'on me dise de coder en suivant les préférences de l'équipe quant au style du code. Je m'attendais à apprendre quelque chose de l'interviewer, il semble que ce ne soit pas le cas. :/

9voto

Tom Anderson Points 22456

J'essaie d'éviter les doublons dans les blocs catch. Si toutes les exceptions d'une méthode reçoivent le même traitement dans le bloc catch, alors allez-y et attrapez-les toutes ensemble. Si vous avez besoin de faire différentes choses avec elles, alors attrapez-les séparément.

Par exemple, ici, nous pouvons attraper toutes les exceptions ensemble, car tout type d'exception signifie que la méthode entière échoue :

public PasswordAuthentication readAuthenticationDetails(File authenticationFile) {
    try {
        BufferedReader reader = new BufferedReader(new FileReader(authenticationFile));
        String username = reader.readLine();
        String password = reader.readLine();
        return new PasswordAuthentication(username, password.toCharArray());
    } catch (IOException e) {
        return null;
    }
}

Alors qu'ici, nous avons un comportement de repli différent pour chaque groupe d'appels, donc nous attrapons séparément :

public Collection<String> readServerHostnames(File mainServerConfigFile, File backupServerConfigFile) {
    String mainServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(mainServerConfigFile));
        mainServerHostname = reader.readLine();
    } catch (IOException e) {
        mainServerHostname = "default-server.example.org";
    }

    String backupServerHostname;
    try {
        BufferedReader reader = new BufferedReader(new FileReader(backupServerConfigFile));
        backupServerHostname = reader.readLine();
    } catch (IOException e) {
        backupServerHostname = "default-server.example.ru";
    }

    return Arrays.asList(mainServerHostname, backupServerHostname);
}

(Ce code existe uniquement pour illustrer ce point sur la capture des exceptions ; je vous prie de ne pas tenir compte du fait qu'il est tout à fait horrible à d'autres égards).

6voto

ssantos Points 7484

Quant à moi, c'est plus clair d'en avoir un seul. try-catch bloc enveloppant tout le code "dangereux" dans une méthode. En ce qui concerne la personne à blâmer lorsque deux lignes lèvent la même exception, vous aurez toujours la trace de la pile.

De plus, avoir plus d'un try-catch à l'intérieur d'une méthode signifie généralement avoir plus d'une return (ce qui peut également rendre difficile le suivi de l'exécution du code à vue), car il y a de fortes chances que si quelque chose ne va pas dans la première ligne de code, il y ait un risque d'erreur. try-catch il ne sera pas utile de continuer à exécuter le reste du code.

Vous trouverez ici quelques bonnes pratiques "standard", au cas où elles vous seraient utiles.

http://howtodoinjava.com/2013/04/04/java-exception-handling-best-practices/

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X