[PYTHON] The End of Catastrophic Programming # 04 "Mistaken Exception Catch Range"

Un programmeur ordinaire le comprend intuitivement et par réflexe, Je voudrais écrire un article sur une histoire rudimentaire et simple. En raison de la nature rudimentaire, un programmeur lourd comme moi Je le fais bien (même si je pensais l'avoir compris).

S'il y a des erreurs ou du contenu inapproprié, veuillez commenter Nous examinerons les corrections et ajustements du contenu.

1. Traitement des exceptions

(Bien qu'il y ait des avantages et des inconvénients), De nombreux langages ont la gestion des exceptions comme spécification de langage.

Cette fois, Imaginez une exception à la méthode try --catch. Java, C #, C ++, Python, etc. doivent avoir des mécanismes d'exception similaires. (En Python, essayez - sauf peut être transmis.)

La gamme des endroits où attraper les exceptions est très importante. Si vous ne comprenez pas cela, vous ne pourrez peut-être pas le faire.

2. Comparons les deux codes

Le code ci-dessous est plein d'autres choses à explorer, Pour le moment, j'aimerais que vous ne prêtiez attention qu'à la plage de try --catch. (Je veux faire un exemple simple, donc Est-il plus efficace d'utiliser des threads ou est-il acceptable de null? Oubliez ça cette fois. )

Le code est C #, mais même si vous avez de l'expérience avec d'autres langages, Je pense que vous pouvez l'imaginer d'une manière ou d'une autre.

Considérez une méthode qui avertit plusieurs utilisateurs d'un message urgent. Si vous passez une liste d'utilisateurs et une chaîne de message, C'est comme informer tous les utilisateurs de la liste avec un message. Nous attrapons des exceptions car les notifications à chaque utilisateur peuvent générer des exceptions.

/// <summary>
///Avertissez plusieurs utilisateurs des messages urgents.
/// </summary>
/// <param name="users">Liste des utilisateurs des destinations.</param>
/// <param name="message">Le message à envoyer.</param>
void NotifyUrgentMessage(User[] users, string message)
{
  try
  {
    //Liste des utilisateurs.
    foreach (var user in users)
    {
      //Avisez chaque utilisateur d'un message.
      user.NotifyMessage(message);
    }

  }
  catch(NotificationException ne)
  {
    //Sortie dans le journal car la notification a échoué
    Log.ErrorFormat("La notification a échoué: ErrorCode = {0}", ne.ErrorCode, ne);
  }

}

L'autre code est presque le même. J'ai implémenté la même fonctionnalité de la même manière, try - La plage de try for catch est différente. En dehors de cela, il n'y a presque aucune différence (en fait, le contenu de sortie du journal est légèrement différent en raison de la différence structurelle).

/// <summary>
///Avertissez plusieurs utilisateurs des messages urgents.
/// </summary>
/// <param name="users">Liste des utilisateurs des destinations.</param>
/// <param name="message">Le message à envoyer.</param>
void NotifyUrgentMessage(User[] users, string message)
{
  //Liste des utilisateurs.
  foreach (var user in users)
  {

    try
    {
      //Avisez chaque utilisateur d'un message.
      user.NotifyMessage(message);
    }
    catch(NotificationException ne)
    {
      //Sortie dans le journal car la notification a échoué
      Log.ErrorFormat("La notification a échoué: ErrorCode = {0}, UserGUID = {1}", ne.ErrorCode, user.Guid, ne);
    }

  }

}

2. Examinez la différence entre la mise en œuvre 1 et la mise en œuvre 2

Dans les situations où l'exception NotificationException ne se produit pas, il n'y a pas de différence opérationnelle entre les deux. (À proprement parler, il existe des différences de performance opérationnelle.)

Dans les situations où une exception NotificationException se produit, le comportement est le même et Il peut se comporter complètement différemment. En substance, il se comporte complètement différemment.

«Supposons que la liste des utilisateurs» contient 10 utilisateurs. Si une NotificationException se produit à la 3ème place dans la liste (en supposant qu'elle commence à la 0ème place) Dans «Mise en œuvre 1», vous quitterez l'instruction for (instruction foreach). Le traitement des notifications après le 4e de la liste n'est pas exécuté. Vous pouvez vous attendre à être notifié à trois personnes.

En revanche, dans "Implementation 2", il ne peut pas être supprimé de l'instruction for (instruction foreach). Le quatrième processus de notification et les suivants de la liste seront exécutés. Si la NotificationException n'était que la troisième, Vous pouvez vous attendre à être notifié à 9 personnes.

NotificationException, S'il se produit à la fin de la liste, 9e (en supposant qu'il commence à 0e), On peut s'attendre à ce que 9 personnes aient été informées à la fois de «Mise en œuvre 1» et de «Mise en œuvre 2». Cependant, où dans la liste se produit l'exception de notification est Je ne sais pas d'habitude.

Le point dépend du nombre dans la liste où l'exception se produit. Le nombre d'utilisateurs qui reçoivent des notifications changera également. Surtout, en raison d'une erreur de notification d'un utilisateur (par exemple, l'effet d'une mauvaise configuration) Cela affecte également les notifications aux autres utilisateurs.

Si NotificationException est une exception qui peut se produire indépendamment pour chaque ʻUser` «La mise en œuvre 2» semble être meilleure.

3. La fin

Non limité à cet exemple, dans la gestion des exceptions De mauvaises choses peuvent arriver si vous n'implémentez pas correctement la plage que vous souhaitez essayer.

Surtout, essayez - attraper, Structurellement, que ce soit à l'intérieur ou à l'extérieur pour, foreach, while, etc. Il peut être nécessaire de l'examiner attentivement.

De plus, même si l'instruction répétée n'est pas incluse, lorsque le résultat du processus A est utilisé dans le processus B, etc. La portée de l'essai d'exception n'est pas appropriée Je suis allé au processus B même si je ne pouvais pas obtenir le résultat dans le processus A. Dans certains cas, des exceptions non interceptées sont lancées vers des destinations inattendues.


ResultA result = null;

try
{
  result = doA();
}
catch(AException ae)
{
   Log.Error(ae);
}

doB(result.Text)

(Bien que cet exemple soit trop simple) Si doA () peut lancer ʻAException, Si une exception se produit Vous devriez obtenir une NullReferenceException ( NullPointerException) dans la partie result.Text lorsque vous appelez doB ()`.

4. Contre-mesures

Fondamentalement, vous devez réfléchir attentivement lors de la mise en œuvre de la gestion des exceptions.

La portée de l'essai de gestion des exceptions est

Je pense que c'est important.

Il devrait y avoir une plage raisonnable pour presque tous les traitements d'exception.

Dans l'exemple précédent de NullReferenceException ( NullPointerException), Je pense qu'il existe un moyen de vérifier null, mais Dans ce cas, si le résultat du processus A affecte le processus B, je pense que ce qui suit est plus propre. (La manière de traiter les exceptions n'est pas au centre de la discussion cette fois.)


try
{
  var result = doA();

  doB(result.Text)
}
catch(AException ae)
{
   Log.Error(ae);
}
catch(BException be)
{
   Log.Error(be);
}

Si la plage est légèrement différente, lorsqu'une exception se produit, Il peut se comporter différemment dans son ensemble, Une attention particulière doit être accordée à son comportement lorsque diverses exceptions se produisent. Aussi, autant que possible, il serait bien de pouvoir tester le comportement lorsqu'une exception se produit.

Recommended Posts

The End of Catastrophic Programming # 04 "Mistaken Exception Catch Range"
La popularité des langages de programmation
Cours de base Python (à la fin de 15)
La fin de la programmation catastrophique # 02 "Il est difficile d'obtenir 5 et 6 de dés ... J'en ai envie, alors considérez les nombres aléatoires"
J'ai lu l'implémentation de range (Objects / rangeobject.c)
Spécification de la plage des tableaux ruby et python
Animation de transition du langage de programmation le plus populaire (#programming language #popular)
Envoyer Gmail à la fin du processus [Python]
Supprimer une chaîne spécifique à la fin de python