Tr

Try/Rescue en Elixir

1 exercice

À propos de Try/Rescue

try .. rescue permet d'intercepter et d'évaluer les erreurs levées à l'intérieur d'un bloc.

Par exemple :

try do
  raise RuntimeError, "error"
rescue
  e in RuntimeError -> :error
end
  • Ligne 1, le bloc est déclaré avec try.
  • Ligne 2, l'appel de fonction susceptible de générer une erreur est placé ici ; dans ce cas, on appelle raise/1.
  • Ligne 4, dans la section rescue, on filtre par motif sur le nom du Module de l'erreur levée
    • du côté gauche de -> :
      • e est associé à la struct d'erreur.
      • in est un mot-clé.
      • RuntimeError est le module à faire correspondre, mais tu peux faire correspondre n'importe quel module d'erreur, ou _ pour toutes les erreurs.
    • du côté droit :
      • les instructions à exécuter si l'erreur correspond.

Les structs d'erreur

Les erreurs (parfois aussi appelées « exceptions ») que tu interceptes de cette façon sont des structs. Chaque struct d'erreur possède ses propres clés. Dans la section « exceptions » de la bibliothèque standard, tu trouveras une liste de toutes les erreurs prédéfinies.

# 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}

En Elixir, on intercepte très rarement les erreurs. En général, l'erreur interceptée est journalisée ou envoyée à un service de surveillance externe, puis relevée à nouveau. Cela signifie que la structure interne d'une struct d'erreur particulière ne nous intéresse généralement pas.

Le concept Exceptions décrit comment définir des structs d'erreur personnalisées.

Évite les anti-patterns

  • Évite les schémas de programmation qui utilisent les erreurs pour contrôler le flux logique. C'est un anti-pattern en 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
    

Lever une erreur, ou ne pas en lever, telle est la question

Comme l'explique le guide de démarrage d'Elixir :

C'est à ton application de décider si une erreur, pendant qu'elle [effectue une action], est exceptionnelle ou non. C'est pourquoi Elixir n'impose pas d'exceptions aux [...] fonctions. Il laisse plutôt au développeur le soin de choisir la meilleure façon de procéder.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet

Apprends Try/Rescue