Eine neue Art des Error-Handlings

Vor kurzem haben wir mit dem neuen Befehl throw() einen neuen Mechanismus für das Error-Handling eingeführt.
Dies war der erste Schritt in Richtung eines neuen Error-Handling-Systems, das so nah wie möglich an dem Code positioniert ist, der die Fehler erzeugt.
In der nächsten Phase mit 4D v20 R4 werden wir diesen Ansatz erweitern, um Fehler während der Ausführung von Ausdrücken abzufangen.
Schauen wir uns die Details an.

try(), ein neues hilfreiches Schlüsselwort

Mit der Einführung von 4D v20 R4 können Entwickler jetzt auf ein neues, nützliches Schlüsselwort zugreifen: Try(Expression). Mit dem Try()-Schlüsselwort können Entwickler einen in Klammern eingeschlossenen Ausdruck ausführen und dabei nahtlos alle Fehler abfangen, die während der Ausführung auftreten. Diese Fehler können mit dem Last errors Befehl unmittelbar nach der Ausführung des Ausdrucks behandelt werden. Auf diese Weise können Sie Ihr Error-Handling so nah wie möglich an dem Code definieren, der sie erzeugt hat, und eventuell lokale Variablen verwenden.

Beispielszenarien vor detaillierten Erklärungen

Division durch Null

Betrachten wir ein einfaches Szenario: Division durch Null. Das folgende Beispiel demonstriert eine euklidische Divisionsmethode, die einen Fehler auslöst und willkürlich Null zurückgibt, wenn der Divisor Null ist. Mit Try() können Entwickler Fehler eleganter behandeln:

#DECLARE($dividend: Real; $divisor: Real)->$result: Real
If ($divisor=0)
$result :=0
throw (-12345; "Division durch Null!")
Else
$result :=($dividend/$divisor)
End if

$result:=Try(division($dividend; $divisor))
If (Last errors#Null)
// Error management
logErrors (Last errors)
End if

ZUGRIFF auf ein Dokument

Der Umgang mit Fehlern beim Zugriff auf ein Dokument wird einfacher, wenn das Dokument nicht existiert.
Um zu verhindern, dass der 4D Fehlerdialog angezeigt wird, musste ein Error-Handler installiert und der Code innerhalb dieses Error-Handlers geschrieben werden:

$previousErrorHandler:=Method called on error
ON ERR CALL ("errorOpenDoc")
var $fileHandle : 4D.FileHandle:=File($path).open()
If ($fileHandle#Null)
ON ERR CALL ("errorReadDoc")
$text :=$fileHandle.readText()
If (Last errors#Null)
$text :="Error reading the file"
End if
End if
ON ERR CALL ($previousErrorHandler)

Mit dem Try()-Schlüsselwort kann alles in denselben Codeabschnitt geschrieben werden, wobei auf lokale Variablen zugegriffen wird und die Lesbarkeit vereinfacht wird:

var $fileHandle : 4D.FileHandle:=Try(File($path).open())
If ($fileHandle#Null)
$text :=Try($fileHandle.readText()) || "Fehler beim Lesen der Datei"
End if

ORDA-Speicherfunktion

Ein weiterer stabiler Anwendungsfall betrifft die ORDA save() -Funktion, die vorhersehbare und unvorhersehbare Fehler erzeugen kann.
Vorhersehbare Fehler, wie z.B. Entity Lock, können direkt über das Erfolgsattribut des Ergebnisses behandelt werden. Unvorhersehbare Fehler, wie z. B. Primärschlüsselduplikate, erfordern jedoch einen Error-Handler, der mit dem ON ERR CALL Befehl installiert werden; andernfalls würde der 4D Fehlerdialog angezeigt werden:

var $customer : cs.CustomerEntity
// Do something with the $customer entity
$previousErrorHandler :=Method called on error
ON ERR CALL ("errorSaveManagement")
$result :=$customer.save()
ON ERR CALL ($previousErrorHandler)
If (Not($result.success))
Case of
: ($result.status=3)
// Locked entity management
: ($result.status=4)
// Other error management
End case
End if

Aber jetzt wird das Schlüsselwort Try() zu einem wertvollen Verbündeten bei der Behandlung von vorhersehbaren und unvorhersehbaren Fehlern, ohne dass der 4D-Fehlerdialog angezeigt wird:

var $customer : cs.CustomerEntity
// Do something with the $customer entity
$result :=Try($customer.save())
If (Not($result.success))
Case of
: ($result.status=3)
// Locked entity management
: ($result.status=4)
// Other error management
End case
End if

Ausführung von Ausdrücken

Das Schlüsselwort Try() akzeptiert jeden 4D Ausdruck zwischen den Klammern, seien es Variablen, Zuweisungen, Methoden, Funktionen oder andere. Im Falle eines Fehlers stoppt der Ausführungsfluss und kehrt zum letzten Try()-Schlüsselwort zurück (dem ersten, das im Aufrufstapel gefunden wurde). Folglich müssen Sie nach der Ausführung des Ausdrucks nur den Fehlerstapel überprüfen, um zu wissen, ob Fehler aufgetreten sind.
Beachten Sie, dass bei der Erzeugung eines Fehlers mit dem throw() im verzögerten Modus ein Fehler erzeugt wird, wird der Ausführungsfluss bis zum Ende der aktuellen Methoden-/Funktionsausführung fortgesetzt, was eine einfache Möglichkeit zur Verwaltung der Fehlerfortpflanzung darstellt.

Ergebnisse

Bei erfolgreicher Ausführung gibt Try() das Ergebnis des Ausdrucks zurück.
Im Falle eines Fehlers wird das letzte Ergebnis des Ausdrucks zurückgegeben oder ‚undefiniert‘, wenn es nicht verfügbar ist.
Wenn der Ausdruck kein Ergebnis definiert (z.B. eine Methode oder ein Befehl ohne Ergebnis), gibt das Schlüsselwort try ‚undefined‘ zurück.

Über den Fehlerstapel

Der aktuelle Fehlerstapel wird vor der Ausführung des Ausdrucks geleert und bietet so eine saubere Grundlage für die Fehlerbehandlung im Try()-Kontext. Fehler, die während der Ausführung des Ausdrucks auftreten, werden dem Fehlerstapel hinzugefügt und bieten dem Entwickler umfassende Informationen für die Fehlersuche.

Fehlerbehandlung

Wenn kein aktueller Fehler-Handler definiert ist, indem der ON ERR CALL Befehls definiert ist, wird der Fehlerdialog den Benutzer nicht bei der Verwendung von Try() stören.
Globale und lokale Fehlerbehandlungen, die vor dem Eintritt in den Try()-Block gesetzt wurden, werden nicht aufgerufen, wodurch eine saubere Trennung zwischen dem Try-Kontext und dem Rest des Codes gewährleistet ist.
Wenn der Ausdruck einen globalen oder lokalen Fehlerhandler für die aktuelle Datenbank definiert, wird dieser aufgerufen, wenn während der Ausführung ein Fehler auftritt.

Neue Horizonte im Fehlermanagement erkunden

Diese neue Funktion eröffnet eine Welt von Möglichkeiten für das Error-Handling. Es ist jedoch nur der zweite Schritt in der neuen Ära des 4D-Fehlermanagements, der den Weg zu mehrzeiligen Try-Catch-Blöcken ebnet!
Tauschen Sie Ihre Gedanken und Erfahrungen in unserem Forum aus, und lassen Sie uns wissen, was Sie von dieser neuen Funktion halten.

Viel Spaß beim Programmieren!

Avatar
- Product Owner - Damien Fuzeau ist seit Februar 2019 Mitglied des 4D Produktteams. Als Product Owner ist er für das Schreiben von User Stories zuständig, die er dann in funktionale Spezifikationen umsetzt. Zu seinen Aufgaben gehört es auch, dafür zu sorgen, dass die gelieferten Funktionsimplementierungen den Anforderungen der Kunden entsprechen. Damien hat an der Universität von Nantes einen Abschluss in Softwaretechnik gemacht. Er verbrachte mehr als 23 Jahre in seinem früheren Unternehmen, zunächst als Entwickler (er entdeckte 4D im Jahr 1997) und später als technischer Leiter und Softwarearchitekt. Dieses Unternehmen ist ein 4D OEM Partner und hat 4D basierte Geschäftssoftware für Tausende von Usern auf Hunderten von Servern eingesetzt. Damien ist also mit der Entwicklung und dem Einsatz von 4D in einem mehrsprachigen Kontext vertraut.