Track
/
Roc
Roc
/
Esercizi
/
Gestione degli errori
Gestione degli errori

Gestione degli errori

Medio

Istruzioni

Implementa diverse forme di gestione degli errori e delle risorse.

Un punto importante della programmazione è come gestire gli errori e chiudere le risorse anche quando si verificano degli errori.

Questo esercizio ti chiede di gestire vari errori. Dato che la gestione degli errori dipende parecchio dal linguaggio di programmazione, dovrai consultare i test del tuo track per vedere esattamente cosa è richiesto.

Implementazione

Stai costruendo un piccolo web server che interroga un database di utenti ancora più piccolo. Sembra facile, ma nel mondo reale molte cose possono (e spesso lo fanno) andare storte:

  • la connessione potrebbe non essere sicura: l'URL deve iniziare con "https://"
  • il nome di dominio potrebbe non essere valido: in questo esercizio, dovrebbe essere "example.com"
  • la pagina potrebbe non esistere: sono consentiti solo "https://example.com/", "https://example.com/users/" e "https://example.com/users/<user_id>"
  • il user_id potrebbe non essere un numero intero positivo
  • potrebbe non esistere alcun utente nel database con questo user_id

Quando qualcosa va storto, è importante dare all'utente finale un messaggio di errore chiaro e utile, così che possa risolvere il problema. Per farlo, devi assicurarti che il codice propaghi errori informativi dal punto in cui l'errore viene rilevato al punto in cui viene prodotto il messaggio di errore.

Per fortuna, Roc ti permette di trasportare un payload (cioè dei dati) all'interno del tag Err. È tentante trasportare direttamente un messaggio di errore (ad esempio, Err("User #42 was not found")), ed in alcuni casi semplici può andare bene, ma questo approccio ha diversi limiti:

  • potresti non avere abbastanza contesto all'interno della funzione che rileva l'errore per produrre un messaggio di errore sufficientemente utile.
    • Per esempio, la funzione Str.to_u64 può essere usata per interpretare ogni genere di numero intero: giorni, secondi, ID utente e altro ancora. Se il messaggio di errore dice solo Could not convert string "0.5" to a positive integer, l'utente potrebbe non avere abbastanza contesto per risolvere il problema.
  • in molti casi, il codice di gestione degli errori potrebbe dover gestire alcuni errori in modo diverso dagli altri. Tuttavia, se gli errori trasportano solo payload di tipo stringa, il codice di gestione degli errori dovrà interpretare quella stringa per capire quale problema si è verificato: è inefficiente e può rompersi facilmente se il messaggio di errore viene modificato.
  • se il sito web è multilingue, dovrai tradurre il messaggio di errore nella lingua dell'utente. Sarà molto più facile farlo se il payload dell'errore è un dato comprensibile alla macchina invece di una stringa in inglese.

Quindi in questo esercizio, gli errori trasporteranno invece un tag significativo insieme al suo payload utile. Per esempio, se l'utente non viene trovato, l'errore sarà simile a Err(UserNotFound(42)).

Bene, iniziamo! Ecco cosa devi fare:

  1. Implementa get_user in modo che restituisca l'utente richiesto dal «database» users (in realtà è solo un Dict). Assicurati che la funzione restituisca Err(UserNotFound(user_id)) se l'utente non viene trovato, invece di Err(KeyNotFound).
  2. Implementa parse_user_id per convertire il percorso dell'URL (come "/users/123") in un ID utente intero positivo (123). In caso di errore, restituisci Err(InvalidUserId(user_id_str)).
  3. Implementa getPage:
    • Se l'URL è "https://example.com/", restituisci Ok("Home page")
    • Se l'URL è "https://example.com/users/", restituisci Ok("Users page")
    • Se l'URL è "https://example.com/users/<user_id>", interpreta l'ID utente, carica l'utente con quell'ID e restituisci Ok("<user name>'s page")
    • Se il prefisso dell'URL non è "https://", restituisci Err(InsecureConnection(url))
    • Se il nome di dominio dell'URL non è "example.com", restituisci Err(InvalidDomain(url))
    • Se il percorso non è / o /users/ o /users/<user id>, restituisci Err(PageNotFound(path))
    • Se l'ID utente non è un numero intero positivo, restituisci Err(InvalidUserId(user_id_str))
    • Se l'utente non esiste, restituisci Err(UserNotFound(user_id))
  4. Implementa error_essage per convertire gli errori precedenti in messaggi di errore tradotti. La funzione dovrebbe gestire almeno l'inglese, ma ti incoraggiamo a provare a gestire anche un'altra lingua. I messaggi di errore in inglese dovrebbero essere così:
  • "Insecure connection (non HTTPS): http://example.com/users/789"
  • "Invalid domain name: https://google.com/wrong"
  • "Page not found: /oops"
  • "User ID is not a positive integer: abc"
  • "User #42 was not found"

Nota: invece di mostrare un messaggio di errore all'utente quando usa HTTP al posto di HTTPS, il web server potrebbe reindirizzare il browser verso HTTPS, e l'utente non noterebbe nemmeno l'errore. Dato che in Roc gli errori sono comprensibili alla macchina, sarebbe molto facile da implementare.

Modifica tramite GitHub Il link si apre in una nuova finestra o scheda
Roc Exercism

Vuoi iniziare Gestione degli errori?

Iscriviti a Exercism per imparare e padroneggiare Roc con 126 esercizi e il mentoring di persone reali, tutto gratis.