web-dev-qa-db-fra.com

Devrais-je lancer des exceptions dans un bloc if-else?

Voici le code:

public Response getABC(Request request) throws Exception {
    Response res = new Response();
    try {
        if (request.someProperty == 1) {
            // business logic
        } else {
           throw new Exception("xxxx");
        }
    } catch (Exception e) {
        res.setMessage(e.getMessage); // I think this is weird
    }
    return res;
}

Ce programme fonctionne bien. Je pense qu'il devrait être repensé, mais comment?

28
Lauda Wang

Cela n'a aucun sens de lancer une exception dans un bloc try et de l'attraper immédiatement, à moins que le bloc catch ne lance une exception différente.

Votre code aurait plus de sens de cette façon:

public Response getABC(Request request) {
    Response res = new Response();
    if (request.someProperty == 1) {
        // business logic
    } else {
        res.setMessage("xxxx");
    }
    return res;
}

Vous n'avez besoin du bloc try-catch que si votre logique métier (exécutée lorsque la condition est true) peut générer des exceptions.

Si vous n'acceptez pas l'exception (ce qui signifie que l'appelant devra la gérer), vous pouvez vous passer de la clause else:

public Response getABC(Request request) throws Exception {
    if (request.someProperty != 1) {
        throw new Exception("xxxx");
    }

    Response res = new Response();
    // business logic
    return res;
}
44
Eran

si vous lancez l'exception de la méthode, alors pourquoi se donner la peine de l'attraper? vous pouvez soit renvoyer une réponse avec le message "xxxx", soit émettre une exception permettant à l'appelant de cette méthode de la gérer.

public Response getABC(Request requst) {
    Response res = new Response();
        if(request.someProperty == 1){
            //business logic
        else{
           res.setMessage("xxxx");
        }
    }
    return res;
}

OR

public Response getABC(Request requst) throw Excetpions {
    Response res = new Response();
        if(request.someProperty == 1){
            //business logic
        else{
           throw new Exception("xxxx");
        }
    return res;
}


public void someMethod(Request request) {
    try {
        Response r = getABC(request);
    } catch (Exception e) {
        //LOG exception or return response with error message
        Response response = new Response();
        response.setMessage("xxxx");
        retunr response;
    }

}
16
mkjh

ça ne semble pas juste quand on lance exprès une exception et qu'on l'attrape directement, ça peut être refait comme ça,
peut changer throw new Exception("xxxx"); avec res.setMessage("xxxx");,
et peut ensuite conserver la partie exception d’exception afin d’attraper l’exception pouvant se produire dans la logique métier.

public Response getABC(Request requst) {
  Response res = new Response();
  try{
      if(request.someProperty == 1){
          //business logic
      else{
         res.setMessage("xxxx");
      }
  }catch(Exception e){
      res.setMessage(e.getMessage);
  }
  return res;
}
9
m fauzan abdi

Je pense que vous pourriez manquer le point de cet essai/attraper. Le code utilise le système des exceptions pour masquer tout message d’exception à l’appelant. Cela pourrait être profondément dans une pile d'appels imbriqués - pas seulement celui "jette" que vous regardez.

En d'autres termes, la déclaration "throws" dans votre exemple de code tire parti de ce mécanisme pour transmettre un message au client, mais ce n'est certainement pas l'utilisateur principal prévu de try/catch. (En outre, c'est un moyen bâclé et peu coûteux de transmettre ce message - cela peut semer la confusion.)

Cette valeur de retour n’est de toute façon pas une bonne idée car Exceptions n’a souvent pas de message et peut être reformaté ... c’est mieux que rien. Les messages d'exception ne sont tout simplement pas le meilleur outil pour cela, mais la gestion d'une exception à un niveau aussi élevé est toujours une bonne idée.

Si vous refactorisez ce code, assurez-vous de rechercher les exceptions d’exécution pouvant être émises n'importe où dans votre base de code (du moins appelées pendant le traitement du message) - et même dans ce cas, vous devriez probablement conserver le message catch/return en tant que catch-all juste au cas où une exception d'exécution apparaît que vous ne vous attendiez pas. Vous n'avez pas à renvoyer l'erreur "Message" en tant que message de votre réponse. Il pourrait s'agir d'une erreur "Nous ne pouvons pas traiter votre demande pour l'instant", mais veillez à vider la trace de la pile dans un journal. . Vous êtes en train de le jeter.

7
Bill K

Tout d’abord, agissez avec plus de soin lorsque vous refactorisez une méthode de travail, surtout si vous effectuez une refactorisation manuelle. Cela dit, introduire une variable pour tenir message peut être un moyen de changer le design:

public Response getABC(Request requst) throw Excetpions {
    String message = "";
    try{
        if(request.someProperty == 1){
            //business logic
        else{
           message = "xxxx";
        }
    }catch(Exception e){
        message = e.getMessage();
    }
    Response res = new Response();
    res.setMessage(message);
    return res;
}

L'hypothèse est que le business logic fait son propre retour quand il réussit.

7

Pourquoi avez-vous utilisé l'instruction try/catch alors que vous avez déjà lancé Checked Exception ?

L'exception vérifiée est généralement utilisée dans certains langages tels que C++ ou Java, mais pas dans les nouveaux langages tels que Kotlin. Personnellement, je limite à l'utiliser.

Par exemple, j'ai un cours comme celui-ci:

class ApiService{
    Response getSomething() throw Exception(); 
} 

qui se sent propre et lisible, mais mine l'utilité du mécanisme de traitement des exceptions. Pratiquement, getSomething() ne déclenche pas une exception vérifiée mais doit quand même se comporter comme il le fait? Cela fonctionne quand il y a quelqu'un en amont d'ApiService qui sait comment traiter l'imprévisible ou inévitable des erreurs comme celle-ci. Et si vous savez vraiment comment vous en occuper, continuez et utilisez un exemple similaire à l'exemple ci-dessous, sinon, Une exception non vérifiée serait suffisante.

public Response getSomething(Request req) throws Exception{
    if (req.someProperty == 1) {
        Response res = new Response();
        // logic 
    } else {
        thows Exception("Some messages go here")
    }
}

Je vais encourager à faire de cette façon:

public Response getSomething(Request req){
if (req.someProperty == 1) {
        Response res = new Response();
        // logic 
        return res;
    } else {
        return ErrorResponse("error message"); // or throw RuntimeException here if you want to
    }
}

Pour plus d'informations, Kotlin dont j'ai déjà parlé ne supporte pas Exception contrôlée pour plusieurs raisons.

Voici un exemple d'interface de la classe JDK implémentée par la classe StringBuilder:

Appendable append(CharSequence csq) throws IOException;

Que dit cette signature? Il dit que chaque fois que j'ajoute une chaîne à quelque chose (un StringBuilder, une sorte de journal, une console, etc.), je dois attraper ces IOExceptions. Pourquoi? Parce qu'il peut être en train de jouer IO (Writer implémente également Appendable)… Donc, il en résulte ce genre de code partout:

try {
    log.append(message)
}
catch (IOException e) {
    // Must be safe
}

Et ce n’est pas bon, voir Effective Java, 3e édition, article 77: Ne pas ignorer les exceptions.

Jetez un coup d'oeil à ces liens:

5
nhp

Le mécanisme d'exception a trois objectifs:

  1. Désactivez immédiatement le déroulement normal du programme et remontez la pile d’appels jusqu’à ce qu’un bloc d’accès approprié soit trouvé.
  2. Fournissez le contexte sous la forme du type d'exception, du message et éventuellement de champs supplémentaires que le code de blocage peut utiliser pour déterminer la marche à suivre.
  3. Une trace de pile pour que les programmeurs puissent effectuer une analyse médico-légale. (Cela coûtait très cher à faire).

C’est beaucoup de fonctionnalités pour un mécanisme. Afin de garder les programmes aussi simples que possible - pour les futurs responsables - nous ne devrions donc utiliser ce mécanisme que si nous vraiment devons le faire.

Dans votre exemple de code, je m'attendrais à ce que toute instruction throw soit très sérieuse, indiquant que quelque chose ne va pas et que le code est censé gérer cette urgence quelque part. J'aurais besoin de comprendre ce qui n'allait pas et la gravité de la situation avant de continuer à lire le reste du programme. Ici, c’est juste un retour fantaisiste d’une Corde, et je me gratterais la tête en me demandant "Pourquoi était-ce nécessaire?" et cet effort supplémentaire aurait pu être mieux dépensé.

Ce code n’est donc pas aussi bon que possible, mais je ne le changerais que si vous aviez le temps de faire un test complet. Changer le déroulement du programme peut introduire des erreurs subtiles et vous devez avoir les changements à l’esprit si vous devez réparer quelque chose.

3

Idem si vous souhaitez que le message d’exception spécifique soit renvoyé par la JVM en cas d’erreur, vous pouvez utiliser la méthode try-catch avec les méthodes getMessage () ou printStackTrace () dans le bloc catch. Donc ici vous pouvez modifier votre code comme:

public Response getABC(Request request) throws Exception {
    Response res = new Response();
    try {
        if (request.someProperty == 1) {
            // business logic
        } 
    } catch (Exception e) {
        res.setMessage(e.getMessage); 
    }
    return res;
}
3
Deepak Bhavale