Tr

Try/Rescue у Elixir

1 вправа

Про концепцію Try/Rescue

За допомогою try .. rescue можна перехоплювати та опрацьовувати помилки, які виникають усередині блоку.

Наприклад:

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • Рядок 1: блок оголошуємо за допомогою try.
  • Рядок 2: тут розміщено виклик функції, який може спричинити помилку, у цьому випадку ми викликаємо raise/1.
  • Рядок 4: у розділі rescue ми зіставляємо за зразком назву модуля помилки, яку було викликано
    • з лівого боку від ->:
      • e зіставляється зі структурою помилки.
      • in - це ключове слово.
      • RuntimeError - це модуль, з яким зіставляємо, але зіставляти можна з будь-яким модулем помилки, або з _, щоб зіставити всі помилки.
    • з правого боку:
      • інструкції, які потрібно виконати, якщо помилка збігається.

Структури помилок

Помилки (які іноді також називають «винятками»), які ми перехоплюємо в такий спосіб, - це структури. Різні структури помилок мають різні ключі. У розділі «Винятки» стандартної бібліотеки можна знайти перелік усіх наперед визначених помилок.

# ArithmeticError caused by division by zero
%ArithmeticError{message: "bad argument in arithmetic expression"}

# Protocol.UndefinedError caused by passing `nil` to `Enum.count/1`
%Protocol.UndefinedError{description: "", protocol: Enumerable, value: nil}

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

Концепція винятків описує, як визначати власні структури помилок.

Уникаймо антипатернів

  • Уникаймо програмних прийомів, які використовують помилки для керування логікою виконання. В Elixir це антипатерн.

    # Avoid using errors for control-flow.
    try do
      {:ok, value} = MyModule.janky_function()
      "All good! #{value}."
    rescue
      e in RuntimeError ->
        reason = e.message
        "Uh oh! #{reason}."
    end
    
    # Rather, use control-flow structures for control-flow.
    case MyModule.janky_function() do
      {:ok, value} -> "All good! #{value}."
      {:error, reason} -> "Uh oh! #{reason}."
    end
    

Викликати чи не викликати - ось питання

Як сказано в посібнику з початку роботи з Elixir:

Рішення про те, чи є помилка під час [виконання дії] винятковою, ухвалює сам застосунок. Саме тому Elixir не навʼязує винятків [...] функціям. Натомість він залишає розробникові вибір, як діяти найкраще.

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

Вивчити концепцію Try/Rescue