Треки
/
Roc
Roc
/
Вправи
/
Обробка помилок
Обробка помилок

Обробка помилок

Середня

Вказівки

Реалізуйте різні види обробки помилок і керування ресурсами.

У програмуванні важливо вміти обробляти помилки та закривати ресурси, навіть якщо вони виникають.

У цій вправі потрібно обробити різні помилки. Оскільки обробка помилок досить специфічна для конкретної мови програмування, потрібно звернутися до тестів своєї мови, щоб побачити, що саме вимагається.

Реалізація

Ми створюємо крихітний вебсервер, який робить запити до ще крихітнішої бази даних користувачів. Звучить просто, але в реальному світі багато що може піти не так (і часто йде):

  • зʼєднання може бути незахищеним: URL має починатися з "https://"
  • імʼя домену може бути недійсним: у цій вправі воно має бути "example.com"
  • сторінку може бути не знайдено: дозволені лише "https://example.com/", "https://example.com/users/" і "https://example.com/users/<user_id>"
  • user_id може не бути додатним цілим числом
  • користувача з таким user_id може не бути в базі даних

Коли щось іде не так, важливо дати кінцевому користувачеві зрозуміле й корисне повідомлення про помилку, щоб він міг зарадити проблемі. Для цього потрібно, щоб наш код передавав інформативні помилки від місця, де помилку виявлено, до місця, де формується повідомлення про неї.

На щастя, Roc дозволяє передавати корисне навантаження (тобто дані) всередині тегу Err. Спокусливо передавати повідомлення про помилку напряму (наприклад, Err("User #42 was not found")), і в деяких простих випадках це цілком прийнятно, але має кілька обмежень:

  • усередині функції, яка виявляє помилку, може бракувати контексту, щоб скласти достатньо корисне повідомлення про помилку.
    • Наприклад, функцію Str.to_u64 можна використати, щоб розібрати найрізноманітніші цілі числа: дні, секунди, ідентифікатори користувачів тощо. Якщо повідомлення про помилку просто каже Could not convert string "0.5" to a positive integer, користувачеві може бракувати контексту, щоб зарадити проблемі.
  • у багатьох випадках код опрацювання помилок має обробляти одні помилки інакше, ніж інші. Однак якщо навантаженням помилки є лише рядок тексту (англ. string), кодові опрацювання помилок доведеться розбирати цей рядок, щоб зрозуміти, що сталося: це неефективно і легко ламається, варто лише трохи змінити повідомлення про помилку.
  • якщо наш вебсайт багатомовний, потрібно буде перекладати повідомлення про помилку мовою користувача. Це буде набагато простіше, якщо навантаженням помилки є машиночитні дані, а не англійський рядок тексту.

Тож у цій вправі наші помилки замість цього нестимуть змістовний тег разом із власним корисним навантаженням. Наприклад, якщо користувача не знайдено, помилка матиме такий вигляд: Err(UserNotFound(42)).

Гаразд, почнімо! Ось що потрібно зробити:

  1. Реалізуйте get_user, щоб повертати запитаного користувача з «бази даних» users (насправді це просто Dict). Обовʼязково повертайте Err(UserNotFound(user_id)), якщо користувача не знайдено, а не Err(KeyNotFound).
  2. Реалізуйте parse_user_id, щоб перетворювати шлях URL (наприклад, "/users/123") на додатне ціле число, тобто ідентифікатор користувача (123). У разі помилки повертайте Err(InvalidUserId(user_id_str)).
  3. Реалізуйте getPage:
    • Якщо URL дорівнює "https://example.com/", повертайте Ok("Home page")
    • Якщо URL дорівнює "https://example.com/users/", повертайте Ok("Users page")
    • Якщо URL дорівнює "https://example.com/users/<user_id>", розберіть ідентифікатор користувача, завантажте користувача з цим ідентифікатором і поверніть Ok("<user name>'s page")
    • Якщо префікс URL не "https://", повертайте Err(InsecureConnection(url))
    • Якщо імʼя домену URL не "example.com", повертайте Err(InvalidDomain(url))
    • Якщо шлях не /, не /users/ і не /users/<user id>, повертайте Err(PageNotFound(path))
    • Якщо ідентифікатор користувача не є додатним цілим числом, повертайте Err(InvalidUserId(user_id_str))
    • Якщо користувача не існує, повертайте Err(UserNotFound(user_id))
  4. Реалізуйте error_essage, щоб перетворювати попередні помилки на перекладені повідомлення про помилки. Функція має принаймні опрацьовувати англійську, але радимо спробувати й іншу мову. Англійські повідомлення про помилки мають мати такий вигляд:
  • "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"

Примітка: замість того щоб показувати користувачеві повідомлення про помилку, коли він використовує HTTP замість HTTPS, наш вебсервер міг би перенаправити його браузер на HTTPS, і користувач навіть не помітив би помилки. Оскільки в Roc помилки машиночитні, реалізувати це було б дуже просто.

Редагувати через GitHub Посилання відкривається в новому вікні або вкладці
Roc Exercism

Час розпочати Обробка помилок?

Зареєструйтеся на Exercism, щоб вивчати й опановувати Roc, а також 126 вправ та справжнє наставництво від людей, і все це безкоштовно.