Ausnahmebehandlung ist für jede Softwareentwicklungsmethodik eine gute Praxis. Ob testbasierte Entwicklung, agile Sprints oder eine Hacking-Session mit einer guten alten ToDo-Liste - wir alle können davon profitieren, dass unsere Grundlagen mit einem robusten Ansatz für die Fehlerbehebung abgedeckt werden.
Es ist äußerst wichtig, sicherzustellen, dass Fehler behoben werden, während sie ästhetisch ansprechend sind und natürlich mit kryptischen Nachrichten für den Endbenutzer logischerweise kein großes Problem werden, um die Bedeutung herauszufinden. Wenn Sie das tun, sind Sie sicherlich auf einem guten Weg, eine solide, stabile und klebrige App zu erstellen, mit der Benutzer gerne arbeiten und die Sie anderen weiterempfehlen werden.
Ideal für uns bietet Elixir eine umfangreiche Ausnahmebehandlung über verschiedene Mechanismen wie z versuchen / fangen
, wirft
, und das : Fehler, Grund
Tupel.
Um einen Fehler anzuzeigen, verwenden Sie erziehen
in Ihrer interaktiven Shell, um einen ersten Eindruck zu bekommen:
iex> "oh noez!" ** (Laufzeitfehler) Oh nein!
Wir können auch so einen Typ hinzufügen:
iex> ArgumentError erhöhen, Nachricht: "Fehlermeldung hier ..." ** (ArgumentError) Fehlermeldung hier ...
Einige der Vorgehensweisen, mit denen Fehler in Elixir behandelt werden, sind auf den ersten Blick nicht offensichtlich.
laichen
, Wir können unabhängige Prozesse schaffen. Das bedeutet, dass ein Fehler in einem Thread keinen anderen Prozess beeinträchtigen sollte, es sei denn, in irgendeiner Weise gab es eine Verknüpfung. Aber standardmäßig bleibt alles stabil.spawn_link
Makro. Dies ist eine bidirektionale Verbindung, dh wenn ein verknüpfter Prozess beendet wird, wird ein Beendigungssignal ausgelöst.:normal
, Wir wissen, dass wir ein Problem haben. Und wenn wir das Ausgangssignal mit einfangen Process.flag (: trap_exit, true)
, Das Beendigungssignal wird an die Mailbox des Prozesses gesendet, wo die Logik für die Verarbeitung der Nachricht festgelegt werden kann, um einen harten Absturz zu vermeiden.Spawn_links
, Dies sind jedoch unidirektionale Links, mit denen wir sie erstellen können Prozessmonitor
. Prozessmonitor
erhält die Fehlermeldung bei einem Fehler.Um einen Beispielfehler zu erhalten, fügen Sie einem Atom eine Zahl hinzu und Sie erhalten Folgendes:
iex>: foo + 69 ** (ArithmeticError) falsches Argument im arithmetischen Ausdruck: erlang. + (: foo, 69)
Um sicherzustellen, dass der Endbenutzer nicht fehlerbehaftet wird, können wir die von Elixir bereitgestellten Try-, Catch- und Rettungsmethoden verwenden.
Zunächst in unserer Toolbox für Ausnahmebehandlung versuchen / retten
, welche durch die Verwendung von erziehen
ist also am besten für Entwicklerfehler oder außergewöhnliche Umstände wie Eingabefehler geeignet.
versuchen / retten
ist in der Verwendung a ähnlich versuchen / fangen
Block, den Sie möglicherweise in anderen Programmiersprachen gesehen haben. Schauen wir uns ein Beispiel in Aktion an:
iex> try do…> "do failed!" erhöhen ...> rescue ...> e in RuntimeError -> IO.puts ("Error:" <> e.message) ...> Ende Fehler: do failed! :OK
Hier nutzen wir die versuchen / retten
Block und die zuvor genannten erziehen
das zu fangen Laufzeit Fehler
.
Das bedeutet das ** (Laufzeit Fehler)
Standardausgabe von erziehen
wird nicht angezeigt und durch eine schönere formatierte Ausgabe aus der ersetzt IO.puts
Anruf.
Als bewährte Methode müssen Sie die Fehlermeldung verwenden, um dem Benutzer eine nützliche Ausgabe in Englisch zu geben, die ihm bei der Problemlösung hilft. Wir werden das im nächsten Beispiel genauer betrachten.
Ein großer Vorteil von Elixir ist, dass Sie in einem davon mehrere Ergebnisse erzielen können versuchen / retten
Blöcke. Schau dir dieses Beispiel an:
probieren Sie die Optionen |> Keyword.fetch! (: source_file) |> File.read! rescue e in KeyError -> IO.puts "fehlt: source_file-Option" e in File.Error -> IO.puts "Quelldatei kann nicht gelesen werden" ende
Hier haben wir zwei Fehler in der Rettung
.
: Quelldatei
Symbol fehlt. Wie bereits erwähnt, können wir dies verwenden, um dem Endbenutzer leicht verständliche Fehlermeldungen zu geben.
Dieser leistungsstarke und minimale Syntaxansatz von Elixir macht das Schreiben mehrerer Überprüfungen für uns sehr leicht zugänglich, um viele mögliche Fehlerquellen auf eine übersichtliche und prägnante Weise zu überprüfen. Auf diese Weise können wir sicherstellen, dass wir keine ausführlichen Bedingungen schreiben müssen, die langwierige Skripts erstellen, die möglicherweise nur schwer vollständig visualisiert werden können und die während der späteren Entwicklung oder für einen neuen Entwickler korrekt debuggen können.
Wie immer, wenn Sie in Elixir arbeiten, ist KISS der beste Ansatz.
Es gibt Situationen, in denen Sie nach dem try / rescue-Block eine bestimmte Aktion ausführen müssen, unabhängig davon, ob ein Fehler aufgetreten ist. Für Java- oder PHP-Entwickler denken Sie möglicherweise an die versuchen / fangen / endlich
oder Ruby beginnen / retten / sicherstellen
.
Schauen wir uns ein einfaches Beispiel für die Verwendung an nach dem
.
iex> try do…> hebe "Ich möchte mit dem Manager sprechen!" ...> retten ...> e in RuntimeError -> IO.puts ("Ein Fehler ist aufgetreten:" <> e.message) ...> nach…> IO.puts "Egal was passiert, ich tauche immer wie ein böser Penny auf." ...> end Es ist ein Fehler aufgetreten: Ich möchte mit dem Manager sprechen! Egal was passiert, ich tauche immer wie ein böser Penny auf. :OK
Hier sehen Sie die nach dem
Wird verwendet, um ständig eine Nachricht anzuzeigen (oder dies kann jede Funktion sein, die Sie dort hineinwerfen möchten).
Eine üblichere Praxis, bei der Sie darauf zurückgreifen werden, ist der Zugriff auf eine Datei, beispielsweise hier:
: ok, file = File.open "would_defo_root.jpg" try do # Versuchen Sie, auf die Datei hier nach # zuzugreifen. Stellen Sie sicher, dass wir danach File.close (file) enden
Ebenso wie erziehen
und versuchen / fangen
Methoden, die wir zuvor beschrieben haben, haben wir auch die Wurf- und Fangmakros.
Verwendung der werfen
Methode beendet die Ausführung mit einem bestimmten Wert, nach dem wir in unserem suchen können Fang
blockieren und weiter wie folgt verwenden:
iex> try do…> für x <- 0… 10 do… > Wenn x == 3, mache: throw (x)…> IO.puts (x)…> Ende…> catch…> x -> "Gefangen: # x"…> Ende 0 1 2 "Gefangen: 3"
Also hier haben wir die Fähigkeit zu Fang
irgendetwas wir werfen
innerhalb des try-Blocks. In diesem Fall die Bedingung wenn x == 3
ist der Auslöser für unsere mach: werfen (x)
.
Die Ausgabe der Iteration, die von der for-Schleife erzeugt wird, gibt uns ein klares Verständnis dafür, was programmgesteuert aufgetreten ist. Inkrementell haben wir einen Schritt nach vorne gemacht, und die Hinrichtung wurde am gestoppt Fang
.
Aufgrund dieser Funktionalität kann es manchmal schwierig sein, sich ein Bild davon zu machen werfen
Fang
wäre in Ihrer App implementiert. Ein Hauptplatz wäre die Verwendung einer Bibliothek, bei der die API nicht für alle dem Benutzer präsentierten Ergebnisse über eine angemessene Funktionalität verfügt, und ein Haken würde ausreichen, um schnell durch das Problem zu navigieren, anstatt sich innerhalb der Bibliothek sehr viel weiterentwickeln zu müssen die Ausgabe und kehren Sie entsprechend zurück.
Schließlich haben wir in unserem Elixir Error Handling Arsenal das Ausfahrt
. Das Beenden erfolgt nicht über den Geschenkeladen, sondern explizit, wenn ein Prozess stirbt.
Ausgänge werden wie folgt signalisiert:
iex> spawn_link fn -> exit ("Du bist fertig, Sohn!") end ** (EXIT von #PID.)<0.101.0>) "Du bist fertig, Sohn!"
Ausgangssignale werden von Prozessen aus einem der folgenden drei Gründe ausgelöst:
Ausfahrt (0)
in C. Der Ausgangsgrund für diese Art des Ausgangs ist das Atom :normal
.versuchen / fangen / retten
blockieren oder werfen / fangen
damit klar kommen.:töten
, was den Empfangsprozess zum Abschluss zwingt.Zu jedem Update-Zeitpunkt am werfen
, Ausfahrt
oder Fehler
, die anrufen System.stacktrace
gibt das letzte Vorkommen im aktuellen Prozess zurück.
Der Stack-Trace kann ziemlich formatiert werden, dies kann sich jedoch in neueren Elixir-Versionen ändern. Weitere Informationen hierzu finden Sie auf der Handbuchseite.
Um den Stack-Trace für den aktuellen Prozess zurückzugeben, können Sie Folgendes verwenden:
Process.info (self (),: current_stacktrace)
Ja, Elixir kann das auch. Natürlich haben Sie immer die eingebauten Typen wie Laufzeit Fehler
zu deiner Verfügung. Aber wäre es nicht schön, wenn Sie noch einen Schritt weiter gehen könnten??
Das Erstellen Ihres eigenen benutzerdefinierten Fehlertyps ist mit der Enttäuschung
Makro, das bequem das akzeptiert :Botschaft
Option, um eine Standardfehlermeldung wie folgt festzulegen:
defmodule MyError do defexception message: "Ihr benutzerdefinierter Fehler ist aufgetreten" ende
So verwenden Sie es in Ihrem Code:
iex> try do…> myError erhöhen…> retten…> e in MyError -> e…> end% MyError Nachricht: "Ihr benutzerdefinierter Fehler ist aufgetreten"
Die Fehlerbehandlung in einer Meta-Programmiersprache wie Elixir hat eine ganze Reihe potenzieller Auswirkungen darauf, wie wir unsere Anwendungen entwerfen und robust genug machen, um die Produktionsumgebung streng zu beherrschen.
Wir können sicherstellen, dass dem Endbenutzer immer ein Hinweis bleibt - eine einfache und leicht verständliche Leitmitteilung, die ihre Aufgabe nicht erschwert, sondern eher umgekehrt. Fehlermeldungen müssen immer seinin reinem Englisch verfasst sein und viele Informationen geben. Kryptische Fehlercodes und Variablennamen sind für durchschnittliche Benutzer nicht geeignet und können Entwickler sogar verwirren!
In der Zukunft können Sie die in Ihrer Elixir-Anwendung angeführten Ausnahmen überwachen und eine bestimmte Protokollierung für bestimmte Problembereiche einrichten, sodass Sie die Fehlerbehebung analysieren und planen oder eine Standardlösung verwenden können.
Verbessern Sie die Genauigkeit unserer Debugging-Arbeit und ermöglichen Sie die Überwachung der Stabilität Ihrer Apps mit diesen für Elixir verfügbaren Drittanbieter-Services:
In Zukunft möchten Sie möglicherweise die Fehlerbehebungsfunktionen Ihrer App erweitern und den Code lesbarer machen. Ich empfehle Ihnen, dieses Projekt für eine elegante Fehlerbehandlung auf GitHub zu überprüfen.
!