[meta:edit-log]: # "2020/08/10"
[meta:title]: # "Error, Snag handling & Bug reporting and more"
[meta:keywords]: # "error, snag, bug, expert, glue, library, module, service, script"
[meta:description]: # "Error is basic data, throw & catch is a way to send event; An Error thrown can be a Snag or Bug, expected or unexpected; Expert code do Snag handling while Glue code don't; code packed as Module/Library/Service/Script required different focus;"


> More thought on Error, after [Exot, Error handling, and Bugs](./20200730-exot-error-handling-and-bugs.md)
> May need more sorting, since not all topic is directly & naturally linked.
> For now may be the ".md" version will be easier to read.


## `Error`, `throw`, and `try-catch`

`Error` is a special kind of event, contains a message and stacktrace.

The keyword `throw` cause the error to bubble up the callstack.

If the code thrown `Error` is inside the try block of `try {} catch (error) {}`,
  the catch block will get the error and run,
  else if the top callstack is reached, the program will log the error and exit.

Using `try-catch` and `throw` have effect similar to `label` and `goto`,
  and often the use of `goto` is considered bad, unlike the more limited `if-else`,
  for it can cause the code to skip/jump past hugh amount of code scopes and callstacks,
  and most bug/leak happen when the skipped code contain destructor/clear-up.
  Interestingly, some may abuse this `goto` behavior and use it for additional control flow.

And instead of rely on `throw` and rewind the callstack to `try-catch` to process `Error`,
  there's alternative to just return/pass `Error` to next function and `if-else` to do the handling,
  like in most callback `(error, result) => {}` and functional programming.

In the end, `Error` is still just basic data,
  it is us who decided to honor some contract to treat it specially.
And `Error` should always be well-defined, classified, can be enumerated easily,
  it's a comment prepared for later debugging.

Whatever the method can reduce the complexity is fine,
  but since most language choose `try-catch` and `throw`,
  later discuss will also adopt this form of contract.


## Snag & Bug

First a sync of words,
  we leave existing words used in code as-is: `Error, throw, try-catch`,
  and use the following words for the topic:
- Snag: or Snag-typed Error,
    expected, should be well-defined and enumerable,
    mostly from failure of some runtime code check,
    like `ENOENT`, 404, bad user input, network lost, legacy protocol...
- Bug: or Bug-typed Error,
    unexpected, and hard to predict,
    mostly caused by logically or structurally wrong code/stack or leak,
    often cause program stall or crash.

We need Snag to be clearly defined and correctly handled,
  and try eliminate Bug all the time.

Whether an `Error` is Snag or Bug depends on the actual code.
If some check code `throw` a well-defined `Error`,
  and outer code already setup `try-catch` to receive it and correctly retry,
  this `Error` is a Snag.
But if for the same situation, the outer code forget to trap the error,
  causing it leaks to higher stack, or even to the top callstack and cause an exit,
  the same `Error` is a Bug.
So for an `Error` end up to be Snag but not Bug,
  the good `Error` `throw` code need to pair with in-time `try-catch` code.

And for the record:
- Some known `Error` will be intentionally be left unhandled to exit the program,
  can still be Snag
- Some non-strict `try-catch` may consume all `Error`,
  causing unrelated/important-debug `Error` get masked as Snag,
  and this is still a Bug

For the expected and unexpected Error, we use different strategy: (Error handling)
- Snag handling:
    Often means add retry at a proper level,
    some may do data patching/fixing/filtering.
- Bug report:
    For unexpected Bug there's few we can do except expose it clearly,
    so often we try do Bug report and collect for later investigation,
    and just crash or retry at a very high level to keep program available for other work.

Not all code need Error handling in the first place,
  most function with no external resource (IO) involved can be made 100% correct.
And it's simpler to limit and reduce the Snag & Bug scope, less work is better.
On the other side, more checks and `Error` do make Bug surface quicker,
  keep a balance.
Often to apply Snag handling to IO related code:
- For short function call like file open,
    just in-place `try catch` should be enough.
- For long-lasting code like incoming HTTP request,
    a proper coding patten may help limit the scope,
    and prevent the Snag handling code spread all over.

And for general code from low to high:
- decide if the function can be Error free (non IO code)
- add check and `throw` detailed `Error`
- some lower-level narrow-focused Snag handling
- some higher-level wide-range `try-catch` for Bug report

And in short:
- Error
    == (Snag || Bug)
    == an Object with message and stacktrace
- Error handling
    == (Snag handling || Bug reporting)
    == specific code in catch block


## Expert & Glue

Next we divide the code quality:
- Expert code:
    with full or deep enough understand of the related system,
    all or most Error thrown is handled as Snag,
    very stable, but often hard to get totally correct,
    takes many test and long time to polish,
    most comes with heavy comment, some maybe harder to read
- Glue(non-expert) code:
    send all caught Error to Bug report,
    or just don't `try-catch` and let outer code do the work,
    simple & quick to write, read, and change,
    but may explode on many edge cases

Both quality standard have some use case,
and most of the time:
- Code should be Expert code:
  - reusable low level library
  - main code path for a long-running server/game
- Code can be Glue code:
  - one-shot script/CLI-tool
  - boilerplate API, business logic (just connecting the dots, no hard-logic on the surface)
  - mundane test code

Note that event Glue code should have clear structure and direct logic,
  and though there's less Snag handled, don't mean it should have Bugs.
Messy Bugged code is just failed Bad code,
  and problem to be fixed.


## Module, Library, Service, and Script

For different usage, we group code as:
- Module:
    Pack of type/constant/function for one common purpose.
    Mostly a single file or folder.
    Suggest all Expert code.
    Need Test, Comment.
- Library:
    Pack of related Module, may have wrapper for stable API.
    Mostly a repo.
    Suggest all Expert code, or only Glue code for wrapper API.
    Need Tooling, Test, Comment.
- Service:
    Depend on some Library(vendor) and may have some Module(lib),
      with many wiring code to perform each specific operation/action,
      often long-running as separate process or remote,
      have some boundary with the user code and require interact with a protocol.
    Mostly a repo, may have sub-repo.
    Suggest Expert code for data-facing part and whole structure/pattern/framework,
      Glue code for each protocol/business logic.
    Need Comment, if needed add good Tooling and do Test,
      since most code is wiring Glue code.
- Script:
    Passing data though Module/Library/Service as a pipeline or test.
    Mostly one or more files.
    Suggest most to be Glue code,
      only write Expert code for import part for later reuse as Module/Library.
    Need some Comment for thought, reference, and the hard/weird part.

For most project,
  85% Expert code in Library/Module +
  15% Glue code on top Service/Script
  may be a good choice.


## Tie it all up

So `Error` can end up being Snag or Bug,
  in both Expert or Glue code,
  packed as Module/Library/Service/Script.

Suppose we are creating a repo for:
- a tar-like CLI program:
    the Module/Library for tar-like should be Expert code;
    the CLI option parser many be either Expert/Library or Glue/Script;
    most Error can be no-handling Snag with a good message output;
    Bug better be reported/logged before crash the program;
- the same tar-like program with GUI:
    the Module/Library for GUI rendering should be Expert code;
    a pattern may be needed to clearly bind tar-like lib with GUI;
    most Snag need to be handled and shown in a Dialog Box to bee seen;
    Bug better be reported/logged before crash the program;
- a wordpress-like server connect to a database:
    the Service for the database should be external Expert code;
    the Module/Library for the server should be Expert code;
    the Module/Library for wordpress-like CMS framework can be Expert code;
    for each API/request maybe Glue/Script;
    some remote data/IO access pattern will be needed;
    some server request/response pattern & routing pattern will be needed;
    most Snag need to be handled and logged;
    Snag can support retry, or request fail (400);
    Bug better be reported/logged, and be limited to cause only the request to fail (500);


## reference

https://en.wikipedia.org/wiki/Exception_handling#In_software