Abbiamo recentemente introdotto un nuovo meccanismo di gestione degli errori, utilizzando il nuovo comando throw().
Questo ha segnato il primo passo verso un nuovo sistema di gestione degli errori, posizionato il più vicino possibile al codice che li genera.
Nella fase successiva, con 4D v20 R4, amplieremo questo approccio per intercettare gli errori durante l’esecuzione delle espressioni.
Entriamo nei dettagli.
try(), una nuova parola chiave utile
Con l’introduzione di 4D v20 R4, gli sviluppatori possono accedere a una nuova e utile parola chiave: Try(Expression). La parola chiave Try() consente agli sviluppatori di eseguire un’espressione racchiusa tra parentesi e di intercettare senza problemi eventuali errori lanciati durante l’esecuzione. Questi errori possono essere gestiti con il comando Last errors subito dopo l’esecuzione dell’espressione. Ciò consente di definire la gestione degli errori il più vicino possibile al codice che li ha generati e di utilizzare eventualmente variabili locali.
Scenari di esempio prima delle spiegazioni dettagliate
Divisione per zero
Consideriamo uno scenario semplice: la divisione per zero. L’esempio seguente mostra un metodo di divisione euclidea che lancia un errore e restituisce arbitrariamente zero se il divisore è zero. Con Try(), gli sviluppatori possono gestire gli errori in modo più elegante:
#DECLARE($dividend: Real; $divisor: Real)->$result: Real
If ($divisor=0)
$result :=0
throw (-12345; "Divisione per zero!")
Else
$result :=($dividend/$divisor)
End if
$result:=Try(division($dividend; $divisor))
If (Last errors#Null)
// Error management
logErrors (Last errors)
End if
ACCESSO A UN DOCUMENTO
La gestione degli errori di accesso a un documento diventa più semplice se il documento non esiste.
Per evitare che venga visualizzata la finestra di dialogo di errore 4D, è necessario installare un gestore di errori e scrivere il codice di gestione degli errori all’interno di questo gestore:
$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 :="Errore nella lettura del file"
End if
End if
ON ERR CALL ($previousErrorHandler)
Con la parola chiave Try(), tutto può essere scritto nella stessa sezione di codice, accedendo alle variabili locali e semplificando la leggibilità:
var $fileHandle : 4D.FileHandle:=Try(File($path).open())
If ($fileHandle#Null)
$text :=Try($fileHandle.readText()) || "Errore nella lettura del file"
End if
Funzione di salvataggio ORDA
Un altro caso d’uso robusto riguarda la funzione ORDA save(), che può generare errori prevedibili e imprevedibili.
Gli errori prevedibili, come il blocco di un’entità, possono essere gestiti direttamente attraverso l’attributo result success. Tuttavia, gli errori imprevedibili, come i duplicati delle chiavi primarie, richiedono un gestore di errori installato con il comando ON ERR CALL altrimenti si visualizzerebbe la finestra di dialogo di errore 4D:
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
Ma ora la parola chiave Try() diventa un prezioso alleato per gestire errori prevedibili e imprevedibili senza mostrare la finestra di dialogo degli errori 4D:
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
Esecuzione dell’espressione
La parola chiave Try() accetta qualsiasi espressione 4D tra le parentesi, siano esse variabili, assegnazioni, metodi, funzioni o altro. In caso di errore, il flusso di esecuzione si interrompe e ritorna all’ultima parola chiave Try() incontrata (la prima trovata nello stack delle chiamate). Di conseguenza, è sufficiente controllare lo stack degli errori dopo l’esecuzione dell’espressione per sapere se si sono verificati errori.
Si noti che se viene generato un errore utilizzando il comando throw() in modalità differita, il flusso di esecuzione continua fino alla fine dell’esecuzione del metodo/funzione corrente, fornendo un modo semplice per gestire la propagazione degli errori.
Risultati
Se l’esecuzione ha successo, Try() restituisce il risultato dell’espressione.
In caso di errore, restituisce l’ultimo risultato dell’espressione o ‘undefined’ se non disponibile.
Se l’espressione non definisce alcun risultato (ad esempio, un metodo o un comando senza risultato), la parola chiave try restituisce ‘undefined’.
Informazioni sullo stack degli errori
La pila degli errori corrente viene cancellata prima dell’esecuzione dell’espressione, offrendo una tabula rasa per la gestione degli errori nel contesto di Try(). Gli errori riscontrati durante l’esecuzione dell’espressione vengono aggiunti allo stack degli errori, fornendo agli sviluppatori informazioni complete per il debug.
Gestione degli errori
Se non è stato definito alcun gestore di errori utilizzando il comando ON ERR CALL la finestra di dialogo degli errori non interromperà l’esperienza dell’utente con Try().
I gestori di errori globali e locali impostati prima di entrare nel blocco Try() non verranno richiamati, garantendo una separazione netta tra il contesto Try e il resto del codice.
Se l’espressione definisce un gestore di errori globale o locale per il database corrente, questo verrà invocato quando si verifica un errore durante l’esecuzione.
Esplorare nuovi orizzonti nella gestione degli errori
Questa nuova funzione apre un mondo di possibilità per la gestione degli errori. Ma è solo il secondo passo nella nuova era della gestione degli errori 4D, che apre la strada ai blocchi try-catch multilinea!
Condividete i vostri pensieri e le vostre esperienze sul nostro forum e fateci sapere cosa ne pensate di questa nuova funzionalità.
Buona programmazione!