Files
saselang-bible/examples/018-result-erreurs-et-exceptions-examples.md
2026-09-13 10:20:16 +02:00

160 lines
2.9 KiB
Markdown

# Exemples / DO-DON'T — Chapitre 18 — `Result`, erreurs, exceptions et faults
> Document compagnon. Les exemples illustrent les règles du chapitre ; la formulation normative reste dans le chapitre lui-même.
## Hiérarchie
```text
Object
└── Error
├── ResultError
├── Exception
└── Fault
```
```text
public final class ParseError extends ResultError {
}
public final class FileNotFoundException extends Exception {
}
public final class IndexOutOfBoundsFault extends Fault {
}
```
## `ResultError`
DO : utiliser `Result` lorsque l'échec est une valeur normale à inspecter explicitement.
```text
func parseExternalInput(String input) -> Result<Value, ParseError> {
...
}
```
DON'T : placer une `Exception` ou un `Fault` dans le paramètre erreur de `Result`.
```text
Result<Value,FileNotFoundException> // ERROR
Result<Value,IndexOutOfBoundsFault> // ERROR
```
## `Exception`, `throw` et `throws`
```text
func readConfig(String path) -> Config
throws IOException
{
...
}
```
Un retour direct est compatible avec `throws`.
```text
throw FileNotFoundException(...); // OK
throw IndexOutOfBoundsFault(...); // ERROR
throw ParseError(...); // ERROR
```
## `Fault`, `fault` et `faults`
```text
method elementAt(uint64 index) -> T
faults IndexOutOfBoundsFault
{
if (index >= this::length()) {
fault IndexOutOfBoundsFault(index, this::length());
}
...
}
```
La clause `faults` est optionnelle et non exhaustive.
DO : appeler sans cérémonie lorsque le fault n'est pas un chemin normal à traiter.
```text
T value = list::elementAt(index);
```
DO : capturer explicitement lorsque le programme veut réellement récupérer ce cas.
```text
try {
T value = list::elementAt(index);
} catch (IndexOutOfBoundsFault faultValue) {
...
}
```
Aucune propagation de `faults` n'est obligatoire :
```text
func outer() -> Void {
inner(); // inner peut déclarer faults SomeFault
return Void;
}
```
## `catch`
Valide :
```text
catch (IOException error) {
...
}
catch (IteratorInvalidatedFault faultValue) {
...
}
```
Invalide :
```text
catch (Error error) // ERROR
catch (ResultError error) // ERROR
```
`catch` ne peut cibler que `Exception`, `Fault` ou leurs descendants.
## Direct versus valeur conditionnelle
Accès affirmatif :
```text
User user = users[id]; // absence -> KeyNotFoundFault
```
Absence normale :
```text
Option<User> user = users::get(id);
```
Le Core ne doit pas créer automatiquement une variante `tryOp()` uniquement pour transporter le même échec dans `Result`.
## Erreur statique versus fault runtime
```text
StaticArray<int32,3> values = [1, 2, 3];
int32 a = values[5]; // ERROR compilation
```
```text
uint64 index = readIndex();
int32 b = values[index]; // peut produire IndexOutOfBoundsFault au runtime
```
Un statement `fault` explicite reste évidemment valide :
```text
if (!state::isValid()) {
fault InvalidStateFault(...);
}
```