diff --git a/doc/ComparisonWithOtherLibraries.en.md b/doc/ComparisonWithOtherLibraries.en.md index 487592f..f7964de 100644 --- a/doc/ComparisonWithOtherLibraries.en.md +++ b/doc/ComparisonWithOtherLibraries.en.md @@ -3,93 +3,191 @@ 🌍 **Languages:** 🇬🇧 English (this file) | đŸ‡«đŸ‡· [Français](./ComparisonWithOtherLibraries.fr.md) -[ErrorOr](https://github.com/amantinband/error-or) and [FluentResults](https://github.com/altmann/FluentResults) are excellent, mature libraries. If your goal is a lightweight *Result* type — returning errors as values instead of throwing — they are focused, well-adopted choices for exactly that. +> Comparison reviewed on **2026-07-14** against the public documentation of [ErrorOr](https://github.com/error-or/error-or) and [FluentResults](https://github.com/altmann/FluentResults). Their APIs and goals may evolve; verify their current documentation before making a long-term choice. -FirstClassErrors answers a **different question**. It is not primarily a *Result* library: it is a way to make errors **first-class, documented and diagnosable knowledge** about your system — errors you can *carry* as values **or** *throw* as exceptions, using one and the same model. +ErrorOr, FluentResults, and FirstClassErrors all help applications represent failure explicitly, but they optimize for different primary goals. -This page highlights what FirstClassErrors does differently. +This page does not try to rank them in general. -## 🎯 A different centre of gravity +The scenario below deliberately emphasizes error stability, diagnosis, and documentation: that is the primary focus of FirstClassErrors, so it naturally plays to its strengths. Other scenarios, such as heavy multi-error validation or intensive functional composition, can favor ErrorOr or FluentResults. -| Library | The question it answers | -|---|---| -| **ErrorOr** | *How do I return one or more errors as a value instead of throwing?* | -| **FluentResults** | *How do I return a result carrying errors, successes and causal reasons?* | -| **FirstClassErrors** | *How do I turn errors into documented, diagnosable knowledge — and move them through my system however each layer needs?* | +The goal is to show the same situation through three different centres of gravity, so you can choose the model that best matches your system. -For ErrorOr and FluentResults, the **error is a payload of the result type**. For FirstClassErrors, the **error is the model**, and the result type (`Outcome`) is just one of several ways to transport it. +## The scenario -## đŸ§© One error model, three transports +A payment provider refuses an authorization request. The application needs to: -The `Error` model is decoupled from the way it travels. The *same* error can be: +- return a failure without crashing the process; +- expose a safe message to the caller; +- preserve an internal diagnostic message; +- keep a stable code for logs and support; +- possibly document how the failure should be investigated. -- kept as **data** — an `Error` value you inspect, log or enrich; -- **thrown** — turned into a typed exception with `error.ToException()`, then caught and routed by type; -- **carried** — wrapped in an `Outcome` / `Outcome` and composed without throwing. +## ErrorOr: a discriminated union of value or errors -Bridges connect all three, so you are never locked into one style. You can *carry* errors inside your domain and *throw* them at a boundary — with **the same error object**, no re-modeling in between. +ErrorOr centres the API on `ErrorOr`, which carries either a successful value or one or more errors. -ErrorOr and FluentResults are, by design, *errors-as-values only*: the error is coupled to the result type and the model deliberately avoids throwing. FirstClassErrors treats the exception path as a **first-class citizen** alongside the value path. +```csharp +private static readonly Error PaymentDeclined = Error.Failure( + code: "PAYMENT_DECLINED", + description: "The payment was declined."); -## 📖 Errors that carry meaning, not just an identifier +public ErrorOr Pay(Order order) +{ + if (provider.Declines(order)) + { + return PaymentDeclined; + } -An ErrorOr `Error` is a code, a description, a `Type` and a metadata bag. A FluentResults error is a message with metadata and nested reasons. That is enough to *handle* an error at runtime. + return new Receipt(order.Id); +} +``` -A FirstClassErrors error is described for **humans**: a title, a plain-language explanation, the **business rule** that was violated, and representative examples. The error stops being a technical token and becomes something a developer — or a support engineer — can actually *understand*. +A caller can inspect, match, switch on, or compose the result. Built-in error types and metadata support categorization and application-specific information. -## 🔎 Diagnostics built for investigation +Choose this style when the central need is an ergonomic value-or-errors flow, especially when multiple validation errors are common, or when error types are mapped to HTTP responses. -Where the others *classify* an error (an `ErrorType` enum, a metadata entry), FirstClassErrors lets an error declare **how to investigate it**: +## FluentResults: a result with reasons and metadata -- one or more **possible causes**; -- the likely **origin** of each one (`Internal`, `External`, `InternalOrExternal`); -- an **analysis lead** — where to start looking. +FluentResults centres the API on `Result` and `Result`. Failures carry one or more reasons, and reasons can contain metadata and nested causes. -This turns the error from *"what failed"* into *"what probably went wrong, and where to begin"* — the difference between an error message and an on-call runbook. +```csharp +public Result Pay(Order order) +{ + if (provider.Declines(order)) + { + return Result.Fail( + new Error("The payment was declined.") + .WithMetadata("Code", "PAYMENT_DECLINED")); + } -## 📚 Documentation generated from your code + return Result.Ok(new Receipt(order.Id)); +} +``` -Because errors are described in code with the `DescribeError` DSL, their documentation is **generated automatically into an error catalog** — a living reference that stays in sync with the code and is ready for developers and support teams alike. +The reasons model is useful when an application wants to enrich both successes and failures, keep hierarchical causes, and compose several results. -Neither ErrorOr nor FluentResults produces documentation from your error definitions; the description lives, at best, in scattered strings and metadata. Here, **documenting an error and defining it are the same act**. +Choose this style when the result and its reason graph are the primary abstraction you want to compose. -## đŸŽšïž Fluent where it helps, plain code where it doesn't +## FirstClassErrors: an error model with several transports -`Outcome` offers a fluent pipeline (`Then`, `To`, `Recover`, `Finally`) to compose steps without throwing — use it when it genuinely makes the flow clearer. +FirstClassErrors centres the API on the error itself. In the recommended usage, a named factory defines and creates the error; an `Outcome` (the library's success-or-failure result type) is one way to carry — or transport — that error as a value: -But that pipeline is an **optional transport, not the centre of gravity**. When a plain `if` returning a well-named domain error reads closer to the business, FirstClassErrors encourages you to *write that instead*. Your error handling stays at **business altitude**; you are never pushed into long fluent chains just to remain "idiomatic". +```csharp +public Outcome Pay(Order order) +{ + if (provider.Declines(order, out string providerCode)) + { + return Outcome.Failure( + PaymentError.PaymentDeclined(providerCode, order.PaymentId)); + } -Railway-oriented result libraries tend to make the fluent pipeline the primary idiom. Here, the pipeline serves the error — not the other way around. + return Outcome.Success(new Receipt(order.Id)); +} +``` -## đŸ›ïž Architecture- and operations-aware +At this level the three libraries look alike: a method returns a success or a failure the caller inspects. The difference is where the failure's meaning lives — [what FirstClassErrors adds](#what-firstclasserrors-adds-to-the-result-model) is shown below. -The model speaks the language of layered / hexagonal design out of the box: +Choose this style when the error definition itself must remain stable, documented, diagnosable, and independent from whether a caller returns or throws it. -- a taxonomy of `DomainError`, `InfrastructureError`, and primary / secondary **port** errors; -- infrastructure concerns such as `Transience` (transient / non-transient) and `InteractionDirection` (incoming / outgoing); -- an **occurrence identity** on every error — a unique `InstanceId` and a UTC timestamp — to correlate logs and diagnostic events. +## What FirstClassErrors adds to the result model -ErrorOr and FluentResults are deliberately architecture-agnostic and keep the error lightweight; these concepts are simply outside their scope. +The transport above looks like the other two. The difference is that the error is defined once, in a named factory that carries its code, messages, occurrence context, and a link to documentation: -## 📊 At a glance +```csharp +internal static DomainError PaymentDeclined( + string providerCode, + Guid paymentId) +{ + // Code.PaymentDeclined and ContextKey.PaymentId are application-defined + // constants: ErrorCode.Create("PAYMENT_DECLINED") and a typed context key. + return DomainError.Create( + Code.PaymentDeclined, + diagnosticMessage: + $"Provider refused payment {paymentId} with code {providerCode}.", + configureContext: context => + context.Add(ContextKey.PaymentId, paymentId)) + .WithPublicMessage( + shortMessage: "The payment was declined.", + detailedMessage: + "Use another payment method or contact your bank."); +} +``` -| | FirstClassErrors | ErrorOr | FluentResults | -|---|:---:|:---:|:---:| -| Return errors as values (railway style) | ✅ (optional) | ✅ | ✅ | -| Throw the *same* error as a typed exception | ✅ | ➖ | ➖ | -| Human-facing error model (title, business rule, explanation) | ✅ | ➖ | ➖ | -| Diagnostics: cause + origin + analysis lead | ✅ | ➖ | ➖ | -| Documentation generated from the code | ✅ | ➖ | ➖ | -| Architecture taxonomy (domain / infrastructure / port) | ✅ | ➖ | ➖ | -| Per-occurrence identity (id + timestamp) | ✅ | ➖ | ➖ | -| Fluent pipeline | Optional, by design | Central | Central | +The same factory feeds exception flow. The error travels as a structured, category-typed exception (`DomainException` here) carrying the same `Error`: -*➖ means "not a goal of that library", not "done badly": ErrorOr and FluentResults are focused on being lean result types.* +```csharp +throw PaymentError + .PaymentDeclined(providerCode, paymentId) + .ToException(); +``` -## 🧭 Which one should you pick? +The error can additionally be linked to structured documentation describing its title, rule, possible causes, analysis leads, and examples. The generated catalog (a human-readable reference of every documented error) and the versioning workflow that guards it against breaking changes are part of the library's intended use. -- Reach for **ErrorOr** when you want a tiny, ergonomic result type with clean, HTTP-friendly error categorization. -- Reach for **FluentResults** when you want a result carrying rich reason chains and metadata. -- Reach for **FirstClassErrors** when you want your errors to be **documented, diagnosable knowledge** — described once in code, carried as values or thrown as exceptions, and turned into a catalog your whole team can rely on. +None of this changes the `Pay` method above: the transport stays small, and the durable knowledge lives with the error's definition, not in each call site. -They are not really competing for the same job: the first two make errors easy to *return*; FirstClassErrors makes them easy to *understand, support and document*. +## What changes between the approaches? + +| Concern | ErrorOr | FluentResults | FirstClassErrors | +| --- | --- | --- | --- | +| Primary abstraction | value or errors | result with reasons | structured error | +| Value-based failure flow | central | central | available through `Outcome` | +| Multiple errors or reasons | built in | built in | structured causes; aggregating independent errors is left to the application | +| Metadata / occurrence facts | metadata | metadata | typed `ErrorContext` | +| Dedicated public vs internal messages | application-defined | application-defined | explicit in the core model | +| Exception transport from the same error definition | not the primary model | not the primary model | built in via `ToException()` — a structured, category-typed exception | +| Domain / infrastructure / port (incoming/outgoing boundary) taxonomy | application-defined | application-defined | built in | +| Transience (is retrying meaningful?) and interaction direction (incoming vs outgoing) | application-defined | application-defined | built in for infrastructure errors | +| Generated human documentation | outside the library's main scope | outside the library's main scope | built in | +| Catalog compatibility checks | outside the library's main scope | outside the library's main scope | built in | + +“Application-defined” or “outside the main scope” does not mean impossible. It means the concern is not the library's central abstraction and may be implemented by application conventions or surrounding tooling. + +## Decision guide + +Choose **ErrorOr** when: + +- you primarily want a concise `T`-or-errors union; +- multiple validation errors are common; +- matching and functional composition are the main interaction style; +- a lightweight error representation is sufficient. + +Choose **FluentResults** when: + +- you want both success and failure reasons; +- nested reason chains and metadata are central; +- the result graph itself is the model you want to enrich and compose. + +Choose **FirstClassErrors** when: + +- errors are durable concepts used by developers, support, operations, or clients; +- public and diagnostic messages must have explicit audiences; +- the same error must travel as data, an `Outcome`, or an exception; +- domain and infrastructure failures require different operational meaning; +- generated documentation and compatibility checks are part of the requirement. + +## A combination may also be valid + +These choices are not always exclusive. An application may use a general-purpose result library at some boundaries while keeping a separate documented error catalog. + +Before combining models, decide which type owns the stable error identity. Duplicating codes, messages, metadata, and mappings across two competing error models usually creates more work than it saves. + +## Questions to ask before choosing + +1. Is the primary problem **control flow**, **reason composition**, or **shared error knowledge**? +2. Must one error definition support both return and exception paths? +3. Who consumes the error model: only code, or also support and operations? +4. Are stable codes and context keys treated as a versioned contract? +5. Is generated documentation a requirement or an external concern? +6. Does the application need built-in domain and infrastructure semantics? +7. How much convention are you prepared to build around a smaller result type? + +The best choice is the smallest model that covers the real requirements without forcing the application to recreate its missing semantics elsewhere. + +--- + + + +--- \ No newline at end of file diff --git a/doc/ComparisonWithOtherLibraries.fr.md b/doc/ComparisonWithOtherLibraries.fr.md index 354458e..52b0a46 100644 --- a/doc/ComparisonWithOtherLibraries.fr.md +++ b/doc/ComparisonWithOtherLibraries.fr.md @@ -1,95 +1,193 @@ -# Comparaison avec les librairies de gestion d’erreurs +# Comparaison avec les bibliothĂšques de gestion d’erreurs -🌍 **Langues:** +🌍 **Langues :** 🇬🇧 [English](./ComparisonWithOtherLibraries.en.md) | đŸ‡«đŸ‡· Français (ce fichier) -[ErrorOr](https://github.com/amantinband/error-or) et [FluentResults](https://github.com/altmann/FluentResults) sont d’excellentes librairies, matures. Si votre objectif est un type *Result* lĂ©ger — retourner les erreurs comme des valeurs plutĂŽt que de les lever — ce sont des choix ciblĂ©s et largement adoptĂ©s, faits exactement pour ça. +> Comparaison revue le **14 juillet 2026** Ă  partir des documentations publiques d’[ErrorOr](https://github.com/error-or/error-or) et de [FluentResults](https://github.com/altmann/FluentResults). Leurs API et leurs objectifs peuvent Ă©voluer : vĂ©rifiez leur documentation actuelle avant un choix Ă  long terme. -FirstClassErrors rĂ©pond Ă  une **question diffĂ©rente**. Ce n’est pas d’abord une librairie *Result* : c’est une maniĂšre de faire des erreurs une **connaissance de premiĂšre classe, documentĂ©e et diagnosticable** sur votre systĂšme — des erreurs que vous pouvez *transporter* comme valeurs **ou** *lever* comme exceptions, avec un seul et mĂȘme modĂšle. +ErrorOr, FluentResults et FirstClassErrors permettent toutes de reprĂ©senter explicitement un Ă©chec, mais elles optimisent des besoins principaux diffĂ©rents. -Cette page met en avant ce que FirstClassErrors fait diffĂ©remment. +Cette page ne cherche pas Ă  Ă©tablir un classement gĂ©nĂ©ral. -## 🎯 Un centre de gravitĂ© diffĂ©rent +Le scĂ©nario ci-dessous met volontairement l’accent sur la stabilitĂ©, le diagnostic et la documentation des erreurs : il correspond donc au pĂ©rimĂštre principal de FirstClassErrors et joue naturellement en sa faveur. D’autres scĂ©narios, comme la validation multiple intensive ou la composition fonctionnelle poussĂ©e, peuvent favoriser ErrorOr ou FluentResults. -| Librairie | La question Ă  laquelle elle rĂ©pond | -|---|---| -| **ErrorOr** | *Comment retourner une ou plusieurs erreurs comme valeur au lieu de les lever ?* | -| **FluentResults** | *Comment retourner un rĂ©sultat portant erreurs, succĂšs et raisons causales ?* | -| **FirstClassErrors** | *Comment transformer les erreurs en connaissance documentĂ©e et diagnosticable — et les faire circuler selon les besoins de chaque couche ?* | +L’objectif est de montrer une mĂȘme situation Ă  travers trois centres de gravitĂ© afin de choisir le modĂšle qui correspond rĂ©ellement au systĂšme. -Pour ErrorOr et FluentResults, l’**erreur est une charge utile du type rĂ©sultat**. Pour FirstClassErrors, l’**erreur est le modĂšle**, et le type rĂ©sultat (`Outcome`) n’est que l’une des façons de la transporter. +## Le scĂ©nario -## đŸ§© Un modĂšle d’erreur, trois transports +Un fournisseur de paiement refuse une demande d’autorisation. L’application doit : -Le modĂšle `Error` est dĂ©couplĂ© de la maniĂšre dont il voyage. La *mĂȘme* erreur peut ĂȘtre : +- retourner un Ă©chec sans faire planter le processus ; +- exposer un message sĂ»r Ă  l’appelant ; +- conserver un message de diagnostic interne ; +- garder un code stable pour les logs et le support ; +- Ă©ventuellement documenter la maniĂšre d’investiguer cet Ă©chec. -- conservĂ©e comme **donnĂ©e** — une valeur `Error` que vous inspectez, journalisez ou enrichissez ; -- **levĂ©e** — transformĂ©e en exception typĂ©e via `error.ToException()`, puis attrapĂ©e et routĂ©e par type ; -- **transportĂ©e** — encapsulĂ©e dans un `Outcome` / `Outcome` et composĂ©e sans lever. +## ErrorOr : une union discriminĂ©e entre valeur et erreurs -Des passerelles relient les trois : vous n’ĂȘtes jamais enfermĂ© dans un style. Vous pouvez *transporter* les erreurs dans votre domaine et les *lever* Ă  une frontiĂšre — avec **le mĂȘme objet erreur**, sans re-modĂ©lisation entre les deux. +ErrorOr place `ErrorOr` au centre de son API. Ce type porte soit une valeur de succĂšs, soit une ou plusieurs erreurs. -ErrorOr et FluentResults sont, par conception, *uniquement erreurs-comme-valeurs* : l’erreur est soudĂ©e au type rĂ©sultat et le modĂšle Ă©vite dĂ©libĂ©rĂ©ment de lever. FirstClassErrors traite le chemin exception comme une **citoyenne de premiĂšre classe**, au mĂȘme titre que le chemin valeur. +```csharp +private static readonly Error PaymentDeclined = Error.Failure( + code: "PAYMENT_DECLINED", + description: "The payment was declined."); -## 📖 Des erreurs qui portent du sens, pas seulement un identifiant +public ErrorOr Pay(Order order) +{ + if (provider.Declines(order)) + { + return PaymentDeclined; + } -Une `Error` d’ErrorOr, c’est un code, une description, un `Type` et un sac de mĂ©tadonnĂ©es. Une erreur FluentResults, c’est un message avec mĂ©tadonnĂ©es et raisons imbriquĂ©es. C’est suffisant pour *traiter* une erreur au runtime. + return new Receipt(order.Id); +} +``` -Une erreur FirstClassErrors est dĂ©crite pour des **humains** : un titre, une explication en langage clair, la **rĂšgle mĂ©tier** violĂ©e et des exemples reprĂ©sentatifs. L’erreur cesse d’ĂȘtre un jeton technique pour devenir quelque chose qu’un dĂ©veloppeur — ou un ingĂ©nieur support — peut rĂ©ellement *comprendre*. +L’appelant peut inspecter, faire un `Match`, un `Switch` ou composer le rĂ©sultat. Les types d’erreurs intĂ©grĂ©s et les mĂ©tadonnĂ©es permettent de catĂ©goriser l’échec et d’ajouter des informations propres Ă  l’application. -## 🔎 Des diagnostics faits pour l’investigation +Choisissez cette approche lorsque le besoin central est un flux ergonomique « valeur ou erreurs », notamment lorsque plusieurs erreurs de validation sont courantes, ou lorsque les types d’erreurs sont mappĂ©s vers des rĂ©ponses HTTP. -LĂ  oĂč les autres *classifient* une erreur (une enum `ErrorType`, une entrĂ©e de mĂ©tadonnĂ©es), FirstClassErrors permet Ă  une erreur de dĂ©clarer **comment l’investiguer** : +## FluentResults : un rĂ©sultat portant des raisons et des mĂ©tadonnĂ©es -- une ou plusieurs **causes probables** ; -- l’**origine** probable de chacune (`Internal`, `External`, `InternalOrExternal`) ; -- une **piste d’analyse** — par oĂč commencer. +FluentResults place `Result` et `Result` au centre de son API. Les Ă©checs portent une ou plusieurs raisons, auxquelles peuvent ĂȘtre associĂ©s des mĂ©tadonnĂ©es et des causes imbriquĂ©es. -L’erreur passe ainsi de *« ce qui a Ă©chouĂ© »* Ă  *« ce qui a probablement mal tournĂ©, et par oĂč commencer »* — la diffĂ©rence entre un message d’erreur et un runbook d’astreinte. +```csharp +public Result Pay(Order order) +{ + if (provider.Declines(order)) + { + return Result.Fail( + new Error("The payment was declined.") + .WithMetadata("Code", "PAYMENT_DECLINED")); + } -## 📚 Une documentation gĂ©nĂ©rĂ©e depuis votre code + return Result.Ok(new Receipt(order.Id)); +} +``` -Parce que les erreurs sont dĂ©crites dans le code avec le DSL `DescribeError`, leur documentation est **gĂ©nĂ©rĂ©e automatiquement sous forme de catalogue d’erreurs** — une rĂ©fĂ©rence vivante qui reste synchronisĂ©e avec le code, prĂȘte pour les dĂ©veloppeurs comme pour les Ă©quipes support. +Le modĂšle de raisons est utile lorsqu’une application souhaite enrichir aussi bien les succĂšs que les Ă©checs, conserver des causes hiĂ©rarchiques et composer plusieurs rĂ©sultats. -Ni ErrorOr ni FluentResults ne produisent de documentation Ă  partir de vos dĂ©finitions d’erreurs ; la description vit, au mieux, dans des chaĂźnes et des mĂ©tadonnĂ©es Ă©parpillĂ©es. Ici, **documenter une erreur et la dĂ©finir sont un seul et mĂȘme geste**. +Choisissez cette approche lorsque le rĂ©sultat et son graphe de raisons sont l’abstraction principale que vous souhaitez enrichir et composer. -## đŸŽšïž Le fluent lĂ  oĂč il aide, du code simple lĂ  oĂč il gĂȘne +## FirstClassErrors : un modĂšle d’erreur avec plusieurs transports -`Outcome` offre un pipeline fluent (`Then`, `To`, `Recover`, `Finally`) pour composer des Ă©tapes sans lever — utilisez-le quand il rend vraiment le flux plus clair. +FirstClassErrors place l’erreur elle-mĂȘme au centre. Dans l’usage recommandĂ©, une factory nommĂ©e dĂ©finit et crĂ©e l’erreur ; `Outcome` (le type rĂ©sultat succĂšs-ou-Ă©chec de la bibliothĂšque) est une façon de faire circuler — ou de transporter — l’erreur comme une valeur : -Mais ce pipeline est un **transport optionnel, pas le centre de gravitĂ©**. Quand un simple `if` retournant une erreur de domaine bien nommĂ©e lit plus prĂšs du mĂ©tier, FirstClassErrors vous encourage Ă  *Ă©crire ça Ă  la place*. Votre gestion d’erreurs reste Ă  **hauteur mĂ©tier** ; vous n’ĂȘtes jamais poussĂ© vers de longues chaĂźnes fluent juste pour rester « idiomatique ». +```csharp +public Outcome Pay(Order order) +{ + if (provider.Declines(order, out string providerCode)) + { + return Outcome.Failure( + PaymentError.PaymentDeclined(providerCode, order.PaymentId)); + } -Les librairies *Result* orientĂ©es railway tendent Ă  faire du pipeline fluent l’idiome principal. Ici, le pipeline sert l’erreur — pas l’inverse. + return Outcome.Success(new Receipt(order.Id)); +} +``` -## đŸ›ïž Consciente de l’architecture et de l’exploitation +À ce niveau, les trois bibliothĂšques se ressemblent : une mĂ©thode retourne un succĂšs ou un Ă©chec que l’appelant inspecte. La diffĂ©rence tient Ă  l’endroit oĂč vit le sens de l’échec — [ce que FirstClassErrors ajoute](#ce-que-firstclasserrors-ajoute-au-modĂšle-de-rĂ©sultat) est montrĂ© plus bas. -Le modĂšle parle nativement le langage de la conception en couches / hexagonale : +Choisissez cette approche lorsque la dĂ©finition de l’erreur doit rester stable, documentĂ©e, diagnosticable et indĂ©pendante du fait qu’un appelant la retourne ou la lĂšve. -- une taxonomie de `DomainError`, `InfrastructureError`, et d’erreurs de **port** primaire / secondaire ; -- des prĂ©occupations d’infrastructure comme `Transience` (transitoire / non transitoire) et `InteractionDirection` (entrant / sortant) ; -- une **identitĂ© d’occurrence** sur chaque erreur — un `InstanceId` unique et un horodatage UTC — pour corrĂ©ler journaux et Ă©vĂšnements de diagnostic. +## Ce que FirstClassErrors ajoute au modĂšle de rĂ©sultat -ErrorOr et FluentResults sont dĂ©libĂ©rĂ©ment agnostiques de l’architecture et gardent l’erreur lĂ©gĂšre ; ces concepts sont simplement hors de leur pĂ©rimĂštre. +Le transport ci-dessus ressemble aux deux autres. La diffĂ©rence, c’est que l’erreur est dĂ©finie une seule fois, dans une factory nommĂ©e qui porte son code, ses messages, son contexte d’occurrence et un lien vers sa documentation : -## 📊 En un coup d’Ɠil +```csharp +internal static DomainError PaymentDeclined( + string providerCode, + Guid paymentId) +{ + // Code.PaymentDeclined et ContextKey.PaymentId sont des constantes dĂ©finies + // par l'application : ErrorCode.Create("PAYMENT_DECLINED") et une clĂ© de contexte typĂ©e. + return DomainError.Create( + Code.PaymentDeclined, + diagnosticMessage: + $"Provider refused payment {paymentId} with code {providerCode}.", + configureContext: context => + context.Add(ContextKey.PaymentId, paymentId)) + .WithPublicMessage( + shortMessage: "The payment was declined.", + detailedMessage: + "Use another payment method or contact your bank."); +} +``` -| | FirstClassErrors | ErrorOr | FluentResults | -|---|:---:|:---:|:---:| -| Retourner les erreurs comme valeurs (style railway) | ✅ (optionnel) | ✅ | ✅ | -| Lever la *mĂȘme* erreur comme exception typĂ©e | ✅ | ➖ | ➖ | -| ModĂšle d’erreur orientĂ© humain (titre, rĂšgle mĂ©tier, explication) | ✅ | ➖ | ➖ | -| Diagnostics : cause + origine + piste d’analyse | ✅ | ➖ | ➖ | -| Documentation gĂ©nĂ©rĂ©e depuis le code | ✅ | ➖ | ➖ | -| Taxonomie d’architecture (domaine / infrastructure / port) | ✅ | ➖ | ➖ | -| IdentitĂ© par occurrence (id + horodatage) | ✅ | ➖ | ➖ | -| Pipeline fluent | Optionnel, par conception | Central | Central | +La mĂȘme factory alimente le flux par exception. L’erreur voyage alors comme une exception structurĂ©e et typĂ©e par catĂ©gorie (`DomainException` ici) portant la mĂȘme `Error` : -*➖ signifie « pas un objectif de cette librairie », pas « mal fait » : ErrorOr et FluentResults sont concentrĂ©es sur le fait d’ĂȘtre des types rĂ©sultat Ă©purĂ©s.* +```csharp +throw PaymentError + .PaymentDeclined(providerCode, paymentId) + .ToException(); +``` -## 🧭 Laquelle choisir ? +L’erreur peut en outre ĂȘtre liĂ©e Ă  une documentation structurĂ©e dĂ©crivant son titre, sa rĂšgle, ses causes possibles, ses pistes d’analyse et ses exemples. Le catalogue gĂ©nĂ©rĂ© (une rĂ©fĂ©rence lisible de toutes les erreurs documentĂ©es) et le workflow de versionnage qui le protĂšge des changements cassants font partie de l’usage prĂ©vu de la bibliothĂšque. -- Prenez **ErrorOr** quand vous voulez un type rĂ©sultat minimal et ergonomique, avec une catĂ©gorisation d’erreurs propre et adaptĂ©e au HTTP. -- Prenez **FluentResults** quand vous voulez un rĂ©sultat portant des chaĂźnes de raisons riches et des mĂ©tadonnĂ©es. -- Prenez **FirstClassErrors** quand vous voulez que vos erreurs soient une **connaissance documentĂ©e et diagnosticable** — dĂ©crite une fois dans le code, transportĂ©e comme valeur ou levĂ©e comme exception, et transformĂ©e en catalogue sur lequel toute l’équipe peut s’appuyer. +Rien de tout cela ne change la mĂ©thode `Pay` ci-dessus : le transport reste lĂ©ger, et la connaissance durable vit avec la dĂ©finition de l’erreur, pas dans chaque site d’appel. -Elles ne se disputent pas vraiment le mĂȘme rĂŽle : les deux premiĂšres rendent les erreurs faciles Ă  *retourner* ; FirstClassErrors les rend faciles Ă  *comprendre, supporter et documenter*. +## Qu’est-ce qui change entre les approches ? + +| PrĂ©occupation | ErrorOr | FluentResults | FirstClassErrors | +| --- | --- | --- | --- | +| Abstraction principale | valeur ou erreurs | rĂ©sultat avec raisons | erreur structurĂ©e | +| Flux d’échec sous forme de valeur | central | central | disponible via `Outcome` | +| Erreurs ou raisons multiples | intĂ©grĂ© | intĂ©grĂ© | causes structurĂ©es ; l’agrĂ©gation d’erreurs indĂ©pendantes est Ă  la charge de l’application | +| MĂ©tadonnĂ©es / faits propres Ă  l’occurrence | mĂ©tadonnĂ©es | mĂ©tadonnĂ©es | `ErrorContext` typĂ© | +| SĂ©paration dĂ©diĂ©e entre messages publics et internes | dĂ©finie par l’application | dĂ©finie par l’application | explicite dans le modĂšle central | +| Transport par exception depuis la mĂȘme dĂ©finition d’erreur | pas le modĂšle principal | pas le modĂšle principal | intĂ©grĂ© via `ToException()` — une exception structurĂ©e et typĂ©e par catĂ©gorie | +| Taxonomie domaine / infrastructure / ports (frontiĂšres entrantes/sortantes) | dĂ©finie par l’application | dĂ©finie par l’application | intĂ©grĂ©e | +| Transience (retenter peut-il rĂ©ussir ?) et direction de l’interaction (entrante ou sortante) | dĂ©finies par l’application | dĂ©finies par l’application | intĂ©grĂ©es pour les erreurs d’infrastructure | +| Documentation humaine gĂ©nĂ©rĂ©e | hors du pĂ©rimĂštre principal de la bibliothĂšque | hors du pĂ©rimĂštre principal de la bibliothĂšque | intĂ©grĂ©e | +| VĂ©rification de compatibilitĂ© du catalogue | hors du pĂ©rimĂštre principal de la bibliothĂšque | hors du pĂ©rimĂštre principal de la bibliothĂšque | intĂ©grĂ©e | + +« DĂ©fini par l’application » ou « hors du pĂ©rimĂštre principal » ne signifie pas impossible. Cela signifie que la prĂ©occupation n’est pas l’abstraction centrale de la bibliothĂšque et qu’elle peut ĂȘtre prise en charge par des conventions applicatives ou un outillage externe. + +## Guide de dĂ©cision + +Choisissez **ErrorOr** lorsque : + +- vous voulez principalement une union concise entre `T` et une ou plusieurs erreurs ; +- les erreurs de validation multiples sont courantes ; +- le matching et la composition fonctionnelle sont le style d’interaction principal ; +- une reprĂ©sentation lĂ©gĂšre de l’erreur suffit. + +Choisissez **FluentResults** lorsque : + +- vous souhaitez reprĂ©senter des raisons de succĂšs comme d’échec ; +- les chaĂźnes de raisons imbriquĂ©es et les mĂ©tadonnĂ©es sont centrales ; +- le graphe de rĂ©sultat est lui-mĂȘme le modĂšle que vous voulez enrichir et composer. + +Choisissez **FirstClassErrors** lorsque : + +- les erreurs sont des concepts durables utilisĂ©s par les dĂ©veloppeurs, le support, l’exploitation ou les clients ; +- les messages publics et de diagnostic doivent avoir des audiences explicites ; +- une mĂȘme erreur doit circuler comme donnĂ©e, `Outcome` ou exception ; +- les Ă©checs mĂ©tier et infrastructurels doivent porter un sens opĂ©rationnel diffĂ©rent ; +- la documentation gĂ©nĂ©rĂ©e et les contrĂŽles de compatibilitĂ© font partie du besoin. + +## Une combinaison peut aussi ĂȘtre valable + +Ces choix ne sont pas toujours exclusifs. Une application peut utiliser une bibliothĂšque de rĂ©sultat gĂ©nĂ©raliste Ă  certaines frontiĂšres tout en conservant un catalogue d’erreurs documentĂ© sĂ©parĂ©. + +Avant de combiner les modĂšles, dĂ©cidez quel type possĂšde l’identitĂ© stable de l’erreur. Dupliquer les codes, les messages, les mĂ©tadonnĂ©es et les mappings entre deux modĂšles concurrents crĂ©e gĂ©nĂ©ralement plus de travail que cela n’en Ă©conomise. + +## Questions Ă  poser avant de choisir + +1. Le problĂšme principal est-il le **contrĂŽle du flux**, la **composition des raisons** ou la **connaissance partagĂ©e des erreurs** ? +2. Une mĂȘme dĂ©finition d’erreur doit-elle supporter le retour et l’exception ? +3. Qui consomme le modĂšle : seulement le code, ou Ă©galement le support et l’exploitation ? +4. Les codes et les clĂ©s de contexte sont-ils considĂ©rĂ©s comme un contrat versionnĂ© ? +5. La documentation gĂ©nĂ©rĂ©e est-elle une exigence ou une prĂ©occupation externe ? +6. L’application a-t-elle besoin d’une sĂ©mantique intĂ©grĂ©e pour le domaine et l’infrastructure ? +7. Combien de conventions ĂȘtes-vous prĂȘt Ă  construire autour d’un type rĂ©sultat plus petit ? + +Le meilleur choix est le plus petit modĂšle qui couvre les besoins rĂ©els sans obliger l’application Ă  reconstruire ailleurs les sĂ©mantiques manquantes. + +--- + + + +--- \ No newline at end of file diff --git a/doc/DocumentationMap.en.md b/doc/DocumentationMap.en.md new file mode 100644 index 0000000..1df9e4a --- /dev/null +++ b/doc/DocumentationMap.en.md @@ -0,0 +1,116 @@ +# Documentation map + +🌍 **Languages:** +🇬🇧 English (this file) | đŸ‡«đŸ‡· [Français](./DocumentationMap.fr.md) + +FirstClassErrors documentation is organized by **reader intent**, not by implementation namespace. + +The project README introduces the library and lists every document by area. This page is different: it helps you choose *what to read next* based on what you are trying to accomplish. + +Start with the question you are trying to answer. The primary pages then point you toward the focused guides and references for advanced details. + +## I am discovering the library + +Follow this path when you are deciding whether FirstClassErrors fits your application. + +1. [Getting Started](GettingStarted.en.md) — install the library, create an error, and generate a first human-readable error catalog. +2. [Design Principles](DesignPrinciples.en.md) — understand why the error is the model and how it travels (exception or return value) is a separate choice. +3. [When Not to Use FirstClassErrors](WhenNotToUseFirstClassErrors.en.md) — identify cases where the library would add more ceremony than value. +4. [Comparison with error-handling libraries](ComparisonWithOtherLibraries.en.md) — compare FirstClassErrors with ErrorOr and FluentResults through one concrete scenario. + +## I need to understand the model + +Read these pages to understand the model before defining your own usage or a project's conventions. + +- [Core Concepts](CoreConcepts.en.md) — `Error`, factories, documentation, exceptions, and `Outcome`. +- [Error Taxonomy and Composition](ErrorTaxonomy.en.md) — domain, infrastructure, and port errors, and how errors nest as structured causes. +- [Error Context Guide](ErrorContext.en.md) — structured facts attached to one occurrence. + +## I am writing an error + +Use these pages when adding or reviewing an application error. + +- [Writing Errors Guide](WritingErrorsGuide.en.md) — code, title, description, rule, diagnostics, and examples. +- [Best Practices](BestPractices.en.md) — project and pull-request review checklist. + +Then, as optional complements: + +- [Internationalization](Internationalization.en.md) — localize public and documentation content while keeping stable identifiers invariant. +- [Analyzer rules](analyzers/README.md) — the compile-time checks that protect the model and its documentation links. + +## I am using errors in application code + +- [Usage Patterns](UsagePatterns.en.md) — select the right representation for common situations. +- [Error Context Guide](ErrorContext.en.md) — attach useful, safe occurrence-level facts. +- [Testing Guide](Testing.en.md) — assert outcomes and errors without manual plumbing. + +## I am integrating delivery and operations + +1. [CI/CD and Operational Integration](OperationalIntegration.en.md) — generate and publish the catalog as part of delivery. +2. [Catalog Versioning — overview and workflow](CatalogVersioning.en.md) — understand snapshots, baselines, and compatibility. +3. [Catalog Versioning — command reference](CatalogVersioningReference.en.md) — find exact CLI options and exit codes. +4. [Catalog Versioning — CI/CD integration](CatalogVersioningCI.en.md) — implement read-only contract checks in pipelines. + +To connect runtime failures back to the catalog: + +- [Integrate with structured logging](LoggingIntegration.en.md) — what to log, how to preserve inner errors, and how to link an occurrence to the generated catalog. + +## I am extending the documentation pipeline + +- [Architecture of the Documentation Pipeline](ArchitectureOfTheDocumentationPipeline.en.md) — understand the end-to-end model and component responsibilities. +- [Extraction and Project Discovery Reference](DocumentationExtractionReference.en.md) — select projects and assemblies, configure isolated extraction, and handle its failures. +- [Writing a custom renderer](WritingACustomRenderer.en.md) — implement and register another output format. +- [Internationalization](Internationalization.en.md) — understand the extraction/rendering culture boundary. + +## I need a reference, not a tutorial + +Use these pages when you already understand the model and need exact behavior. + +- [Extraction and Project Discovery Reference](DocumentationExtractionReference.en.md) — projects, assemblies, isolated extraction, and failure handling. +- [Catalog Versioning command reference](CatalogVersioningReference.en.md) — exact CLI options and exit codes. +- [Analyzer rules (FCExxx)](analyzers/README.md) — the full list of compile-time diagnostics. + +## I am stuck or unsure about a decision + +Use these pages when you need to make a design call or weigh options. + +- [FAQ](FAQ.en.md) — resolve common design questions and find the relevant focused guide. +- [Usage Patterns](UsagePatterns.en.md) — choose the right representation for a situation. +- [When Not to Use FirstClassErrors](WhenNotToUseFirstClassErrors.en.md) — recognize when the library adds more ceremony than value. +- [Comparison with error-handling libraries](ComparisonWithOtherLibraries.en.md) — compare FirstClassErrors with ErrorOr and FluentResults. + +## Suggested team reading order + +For a team adopting FirstClassErrors, a practical sequence is: + +1. Getting Started; +2. Design Principles; +3. Core Concepts; +4. Writing Errors Guide; +5. Usage Patterns; +6. Testing Guide; +7. CI/CD and Operational Integration; +8. Catalog Versioning. + +After that shared foundation, specialists can read the architecture, renderer, internationalization, logging, analyzer, and command-reference material relevant to their work. + +## Keep one source of truth + +Avoid copying large explanations between project guidelines and this documentation. + +Project-specific rules should state the local decision and link to the relevant guide. For example: + +```text +Application errors must be created through named factories. +See Writing Errors Guide and Best Practices. +``` + +This keeps local conventions short while allowing the library documentation to evolve without creating several conflicting explanations. + +--- + + + +--- \ No newline at end of file diff --git a/doc/DocumentationMap.fr.md b/doc/DocumentationMap.fr.md new file mode 100644 index 0000000..f749388 --- /dev/null +++ b/doc/DocumentationMap.fr.md @@ -0,0 +1,116 @@ +# Carte de la documentation + +🌍 **Langues :** +🇬🇧 [English](./DocumentationMap.en.md) | đŸ‡«đŸ‡· Français (ce fichier) + +La documentation de FirstClassErrors est organisĂ©e selon **l’intention du lecteur**, et non selon les namespaces d’implĂ©mentation. + +Le README du projet prĂ©sente la bibliothĂšque et recense les documents par domaine. Cette page est diffĂ©rente : elle vous aide Ă  choisir *quoi lire ensuite* selon ce que vous cherchez Ă  accomplir. + +Partez de la question Ă  laquelle vous cherchez Ă  rĂ©pondre. Les pages principales vous orientent ensuite vers les guides et rĂ©fĂ©rences spĂ©cialisĂ©s utiles. + +## Je dĂ©couvre la bibliothĂšque + +Suivez ce parcours pour dĂ©terminer si FirstClassErrors correspond Ă  votre application. + +1. [Premiers pas](GettingStarted.fr.md) — installer la bibliothĂšque, crĂ©er une erreur et gĂ©nĂ©rer un premier catalogue d’erreurs lisible par des humains. +2. [Principes de conception](DesignPrinciples.fr.md) — comprendre pourquoi l’erreur est le modĂšle et pourquoi sa façon de voyager (exception ou valeur de retour) est un choix sĂ©parĂ©. +3. [Quand ne pas utiliser FirstClassErrors](WhenNotToUseFirstClassErrors.fr.md) — reconnaĂźtre les situations oĂč la bibliothĂšque apporterait plus de formalisme que de valeur. +4. [Comparaison avec les bibliothĂšques de gestion d’erreurs](ComparisonWithOtherLibraries.fr.md) — comparer FirstClassErrors, ErrorOr et FluentResults Ă  partir d’un mĂȘme scĂ©nario concret. + +## Je dois comprendre le modĂšle + +Lisez ces pages pour comprendre le modĂšle avant de dĂ©finir vos usages ou les conventions d’un projet. + +- [Concepts fondamentaux](CoreConcepts.fr.md) — `Error`, factories, documentation, exceptions et `Outcome`. +- [Taxonomie et composition des erreurs](ErrorTaxonomy.fr.md) — erreurs de domaine, d’infrastructure et de ports, et comment les erreurs s’imbriquent en causes structurĂ©es. +- [Guide du contexte d’erreur](ErrorContext.fr.md) — faits structurĂ©s propres Ă  une occurrence. + +## J’écris une erreur + +Utilisez ces pages lors de l’ajout ou de la revue d’une erreur applicative. + +- [Guide d’écriture des erreurs](WritingErrorsGuide.fr.md) — code, titre, description, rĂšgle, diagnostics et exemples. +- [Bonnes pratiques](BestPractices.fr.md) — checklist de projet et de pull request. + +Puis, comme complĂ©ments facultatifs : + +- [Internationalisation](Internationalisation.fr.md) — localiser le contenu public et documentaire tout en gardant les identifiants stables invariants. +- [RĂšgles d’analyse](analyzers/README.fr.md) — les contrĂŽles de compilation qui protĂšgent le modĂšle et les liens documentaires. + +## J’utilise les erreurs dans le code applicatif + +- [Cas d’usage](UsagePatterns.fr.md) — choisir la bonne reprĂ©sentation selon la situation. +- [Guide du contexte d’erreur](ErrorContext.fr.md) — attacher des faits utiles, sĂ»rs et propres Ă  l’occurrence. +- [Guide des tests](Testing.fr.md) — vĂ©rifier les outcomes et les erreurs sans plomberie manuelle. + +## J’intĂšgre la livraison et l’exploitation + +1. [IntĂ©gration CI/CD et exploitation](OperationalIntegration.fr.md) — gĂ©nĂ©rer et publier le catalogue dans la chaĂźne de livraison. +2. [Versionnage du catalogue — vue d’ensemble et workflow](CatalogVersioning.fr.md) — comprendre snapshots, baseline et compatibilitĂ©. +3. [Versionnage du catalogue — rĂ©fĂ©rence des commandes](CatalogVersioningReference.fr.md) — retrouver les options exactes de la CLI et les codes de sortie. +4. [Versionnage du catalogue — intĂ©gration CI/CD](CatalogVersioningCI.fr.md) — mettre en place des contrĂŽles de contrat en lecture seule dans les pipelines. + +Pour relier les Ă©checs d’exĂ©cution au catalogue : + +- [IntĂ©gration au logging structurĂ©](LoggingIntegration.fr.md) — quoi logger, comment prĂ©server les erreurs internes et relier une occurrence au catalogue gĂ©nĂ©rĂ©. + +## J’étends le pipeline documentaire + +- [Architecture du pipeline de documentation](ArchitectureOfTheDocumentationPipeline.fr.md) — comprendre le modĂšle de bout en bout et la responsabilitĂ© de chaque composant. +- [RĂ©fĂ©rence de l’extraction et de la dĂ©couverte des projets](DocumentationExtractionReference.fr.md) — sĂ©lectionner les projets et assemblies, configurer l’extraction isolĂ©e et traiter ses Ă©checs. +- [Écrire son propre renderer](WritingACustomRenderer.fr.md) — implĂ©menter et enregistrer un nouveau format de sortie. +- [Internationalisation](Internationalisation.fr.md) — comprendre la frontiĂšre de culture entre extraction et rendu. + +## J’ai besoin d’une rĂ©fĂ©rence, pas d’un tutoriel + +Utilisez ces pages lorsque vous connaissez dĂ©jĂ  le modĂšle et recherchez un comportement exact. + +- [RĂ©fĂ©rence de l’extraction et de la dĂ©couverte des projets](DocumentationExtractionReference.fr.md) — projets, assemblies, extraction isolĂ©e et traitement des Ă©checs. +- [RĂ©fĂ©rence des commandes de versionnage](CatalogVersioningReference.fr.md) — options exactes de la CLI et codes de sortie. +- [RĂšgles d’analyse (FCExxx)](analyzers/README.fr.md) — la liste complĂšte des diagnostics de compilation. + +## Je suis bloquĂ© ou j’hĂ©site sur une dĂ©cision + +Utilisez ces pages lorsque vous devez trancher une dĂ©cision de conception ou peser des options. + +- [FAQ](FAQ.fr.md) — rĂ©soudre les questions de conception courantes et trouver le guide spĂ©cialisĂ© pertinent. +- [Cas d’usage](UsagePatterns.fr.md) — choisir la bonne reprĂ©sentation selon la situation. +- [Quand ne pas utiliser FirstClassErrors](WhenNotToUseFirstClassErrors.fr.md) — reconnaĂźtre les situations oĂč la bibliothĂšque apporterait plus de formalisme que de valeur. +- [Comparaison avec les bibliothĂšques de gestion d’erreurs](ComparisonWithOtherLibraries.fr.md) — comparer FirstClassErrors, ErrorOr et FluentResults. + +## Ordre de lecture conseillĂ© pour une Ă©quipe + +Pour une Ă©quipe qui adopte FirstClassErrors, un ordre pratique est : + +1. Premiers pas ; +2. Principes de conception ; +3. Concepts fondamentaux ; +4. Guide d’écriture des erreurs ; +5. Cas d’usage ; +6. Guide des tests ; +7. IntĂ©gration CI/CD et exploitation ; +8. Versionnage du catalogue. + +AprĂšs ce socle commun, les spĂ©cialistes peuvent lire les contenus d’architecture, de renderer, d’internationalisation, de logging, d’analyseurs et de rĂ©fĂ©rence CLI utiles Ă  leur travail. + +## Garder une seule source de vĂ©ritĂ© + +Évitez de recopier de longues explications entre les conventions du projet et cette documentation. + +Les rĂšgles propres au projet devraient exprimer la dĂ©cision locale et renvoyer vers le guide correspondant. Par exemple : + +```text +Les erreurs applicatives doivent ĂȘtre créées via des factories nommĂ©es. +Voir le Guide d’écriture des erreurs et les Bonnes pratiques. +``` + +Les conventions locales restent ainsi courtes, tandis que la documentation de la bibliothĂšque peut Ă©voluer sans crĂ©er plusieurs explications contradictoires. + +--- + + + +--- \ No newline at end of file diff --git a/doc/FAQ.fr.md b/doc/FAQ.fr.md index 0d7c77f..19a129b 100644 --- a/doc/FAQ.fr.md +++ b/doc/FAQ.fr.md @@ -15,7 +15,7 @@ Vous pourriez. Transporter l’`Error` de la bibliothĂšque dans un type rĂ©sulta `Outcome` est cette idĂ©e, spĂ©cialisĂ©e pour ce modĂšle d’erreur. Son cĂŽtĂ© Ă©chec est toujours une `Error` — et non un second paramĂštre de type Ă  propager dans chaque signature — et sa petite API (`Then`, `Recover`, `Finally`) est nommĂ©e par intention plutĂŽt qu’avec la mĂ©canique de la programmation fonctionnelle (`Map`, `Bind`, `Match`). L’objectif : du code de domaine et des use cases qui se lisent comme un flux mĂ©tier, pas comme de la tuyauterie de rĂ©sultat gĂ©nĂ©rique. -Voir [Cas d’usage](UsagePatterns.fr.md) et [Comparaison avec les librairies de gestion d’erreurs](ComparisonWithOtherLibraries.fr.md). +Voir [Cas d’usage](UsagePatterns.fr.md) et [Comparaison avec les bibliothĂšques de gestion d’erreurs](ComparisonWithOtherLibraries.fr.md). ## Est-ce trop lourd pour une application simple ?