[PYTHON] Das Ende der katastrophalen Programmierung # 04 "Fehlerhafter Ausnahmebereich"

Ein gewöhnlicher Programmierer versteht es intuitiv und reflexiv. Ich möchte einen Artikel über eine rudimentäre und einfache Geschichte schreiben. Wegen der rudimentären Natur ein schwerer Programmierer wie ich Ich mache es gut (auch wenn ich dachte, ich hätte es verstanden).

Wenn es Fehler oder unangemessene Inhalte gibt, kommentieren Sie bitte Wir werden Korrekturen und Anpassungen des Inhalts berücksichtigen.

1. Ausnahmebehandlung

(Obwohl es Vor- und Nachteile gibt), Viele Sprachen haben Ausnahmebehandlung als Sprachspezifikation.

Diesmal, Stellen Sie sich eine Ausnahme von der Methode try --catch vor. Java, C #, C ++, Python usw. sollten ähnliche Ausnahmemechanismen haben. (In Python kann try --except übertragen werden.)

Der Bereich, in dem Ausnahmen abgefangen werden können, ist sehr wichtig. Wenn Sie dies falsch verstehen, können Sie dies möglicherweise nicht tun.

2. Vergleichen wir die beiden Codes

Der folgende Code ist voll von anderen Dingen, in die man sich vertiefen kann. Ich möchte, dass Sie vorerst nur auf den Bereich des Try-Catch achten. (Ich möchte also ein einfaches Beispiel machen Ist es effizienter, Threads zu verwenden, oder ist es in Ordnung, null zu setzen? Vergiss das diesmal. )

Der Code ist C #, aber selbst wenn Sie Erfahrung mit anderen Sprachen haben, Ich denke du kannst es dir irgendwie vorstellen.

Stellen Sie sich eine Methode vor, die mehrere Benutzer über eine dringende Nachricht benachrichtigt. Wenn Sie eine Benutzerliste und eine Nachrichtenzeichenfolge übergeben, Es ist so, als würden Sie alle Benutzer in der Liste mit einer Nachricht benachrichtigen. Wir fangen Ausnahmen ab, weil Benachrichtigungen an jeden Benutzer Ausnahmen auslösen können.

/// <summary>
///Benachrichtigen Sie mehrere Benutzer über dringende Nachrichten.
/// </summary>
/// <param name="users">Benutzerliste der Ziele.</param>
/// <param name="message">Die zu sendende Nachricht.</param>
void NotifyUrgentMessage(User[] users, string message)
{
  try
  {
    //Benutzer auflisten.
    foreach (var user in users)
    {
      //Benachrichtigen Sie jeden Benutzer über eine Nachricht.
      user.NotifyMessage(message);
    }

  }
  catch(NotificationException ne)
  {
    //Ausgabe zum Protokollieren, da die Benachrichtigung fehlgeschlagen ist
    Log.ErrorFormat("Benachrichtigung fehlgeschlagen: ErrorCode = {0}", ne.ErrorCode, ne);
  }

}

Der andere Code ist fast der gleiche. Ich habe die gleiche Funktionalität auf die gleiche Weise implementiert. try - Der Bereich für den Fangversuch ist unterschiedlich. Davon abgesehen gibt es fast keinen Unterschied (tatsächlich unterscheidet sich der Inhalt der Protokollausgabe aufgrund des strukturellen Unterschieds geringfügig).

/// <summary>
///Benachrichtigen Sie mehrere Benutzer über dringende Nachrichten.
/// </summary>
/// <param name="users">Benutzerliste der Ziele.</param>
/// <param name="message">Die zu sendende Nachricht.</param>
void NotifyUrgentMessage(User[] users, string message)
{
  //Benutzer auflisten.
  foreach (var user in users)
  {

    try
    {
      //Benachrichtigen Sie jeden Benutzer über eine Nachricht.
      user.NotifyMessage(message);
    }
    catch(NotificationException ne)
    {
      //Ausgabe zum Protokollieren, da die Benachrichtigung fehlgeschlagen ist
      Log.ErrorFormat("Benachrichtigung fehlgeschlagen: ErrorCode = {0}, UserGUID = {1}", ne.ErrorCode, user.Guid, ne);
    }

  }

}

2. Betrachten Sie den Unterschied zwischen Implementierung 1 und Implementierung 2

In Situationen, in denen die Ausnahme "NotificationException" nicht auftritt, gibt es keinen betrieblichen Unterschied zwischen beiden. (Genau genommen gibt es Unterschiede in der Betriebsleistung.)

In Situationen, in denen eine NotificationException-Ausnahme auftritt, ist das Verhalten dasselbe und Es kann sich ganz anders verhalten. Im Wesentlichen verhält es sich ganz anders.

Angenommen, die Benutzerliste enthält 10 Benutzer. Wenn eine "NotificationException" an der 3. Stelle in der Liste auftritt (vorausgesetzt, sie beginnt an der 0. Stelle) In "Implementierung 1" verlassen Sie die for-Anweisung (foreach-Anweisung). Die Benachrichtigungsverarbeitung nach dem 4. in der Liste wird nicht ausgeführt. Sie können damit rechnen, drei Personen benachrichtigt zu werden.

Andererseits kann es in "Implementierung 2" nicht aus der for-Anweisung (foreach-Anweisung) entfernt werden. Der vierte und nachfolgende Benachrichtigungsprozess in der Liste wird ausgeführt. Wenn die "NotificationException" nur die dritte war, Sie können damit rechnen, 9 Personen benachrichtigt zu werden.

NotificationException, Wenn es am Ende der Liste auftritt, 9. (vorausgesetzt, es beginnt am 0.), Es ist zu erwarten, dass 9 Personen sowohl in "Implementierung 1" als auch in "Implementierung 2" benachrichtigt wurden. Wo jedoch in der Liste die "NotificationException" auftritt, ist Ich weiß es normalerweise nicht.

Der Punkt hängt von der Nummer in der Liste ab, bei der die Ausnahme auftritt. Die Anzahl der Benutzer, die Benachrichtigungen erhalten, ändert sich ebenfalls. Vor allem aufgrund eines Benachrichtigungsfehlers eines Benutzers (z. B. aufgrund einer Fehlkonfiguration) Dies wirkt sich auch auf Benachrichtigungen an andere Benutzer aus.

Wenn die "NotificationException" eine Ausnahme ist, die für jeden "Benutzer" unabhängig auftreten kann "Implementierung 2" scheint besser zu sein.

3. Das Ende

Nicht auf dieses Beispiel beschränkt, bei der Ausnahmebehandlung Schlechte Dinge können passieren, wenn Sie den Bereich, den Sie ausprobieren möchten, nicht richtig implementieren.

Vor allem versuchen - fangen, Strukturell, ob es drinnen oder draußen sein sollte, foreach, while, etc. Es kann notwendig sein, dies gründlich zu prüfen.

Selbst wenn die wiederholte Anweisung nicht enthalten ist, wird das Ergebnis von Prozess A in Prozess B usw. verwendet. Der Umfang des Ausnahmeversuchs ist nicht angemessen Ich ging zu Prozess B, obwohl ich das Ergebnis in Prozess A nicht erhalten konnte. In einigen Fällen werden nicht erfasste Ausnahmen an unerwartete Ziele gesendet.


ResultA result = null;

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

doB(result.Text)

(Obwohl dieses Beispiel zu einfach ist) Wenn "doA ()" eine "AException" auslösen kann, Wenn eine Ausnahme auftritt Sie sollten eine NullReferenceException (NullPointerException) im Teil result.Text erhalten, wenn Sie doB () aufrufen.

4. Gegenmaßnahmen

Grundsätzlich müssen Sie bei der Implementierung der Ausnahmebehandlung sorgfältig überlegen.

Der Umfang des Ausnahmebehandlungsversuchs ist

Ich denke das ist wichtig.

Für fast alle Ausnahmebehandlungen sollte ein angemessener Bereich vorhanden sein.

Im vorherigen Beispiel von "NullReferenceException" ("NullPointerException") Ich denke, es gibt eine Möglichkeit, nach Null zu suchen, aber In diesem Fall, wenn das Ergebnis von Prozess A Prozess B beeinflusst, denke ich, dass das Folgende sauberer ist. (Der Umgang mit Ausnahmen steht diesmal nicht im Mittelpunkt der Diskussion.)


try
{
  var result = doA();

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

Wenn der Bereich geringfügig abweicht und eine Ausnahme auftritt, Es kann sich insgesamt anders verhalten, Es muss sorgfältig überlegt werden, wie es sich verhält, wenn verschiedene Ausnahmen auftreten. Außerdem wäre es so schön wie möglich, das Verhalten testen zu können, wenn eine Ausnahme auftritt.

Recommended Posts

Das Ende der katastrophalen Programmierung # 04 "Fehlerhafter Ausnahmebereich"
Die Popularität von Programmiersprachen
Python-Grundkurs (Ende 15)
Das Ende der katastrophalen Programmierung # 02 "Es ist schwer, 5 und 6 Würfel zu bekommen ... Ich denke, es ist eine Zufallszahlenüberlegung."
Ich habe die Implementierung von range gelesen (Objects / rangeobject.c)
Angeben des Bereichs von Ruby- und Python-Arrays
Übergangsanimation der beliebtesten Programmiersprache (#Programmiersprache #popular)
Senden Sie Google Mail am Ende des Vorgangs [Python]
Entfernen Sie eine bestimmte Zeichenfolge am Ende von Python