And because our error handling code rarely, if ever gets executed(I often see trivial mistakes that lead to crashes in error handling case), I think the erlang philosophy of “let it crash” is the best approach IMHO.
I like to pepper my code with asserts for that reason. But you can also get the case where the process crashes and get restarted in an infinite loop, so it's not a panacea either.
That’s where Erlang’s supervision model comes to the rescue. Restart until it becomes obvious something more serious is wrong and then raise a flag.
The nice thing about Erlang is that practically every line of code is an assertion and they’re all live in production. Such a huge advantage over development assertions that get thrown away for prod.
I think Rust got this right, too. No Exceptions, but a Result<R,E> enum return type and the compiler forces you to handle the error case as well by doing exhaustiveness checks.
Doesn't that lead to a lot of error handling code?
Another nice feature of the Erlang model is that, often, you can code the happy path and forget the error checking. Makes for much tighter/cleaner/easier-to-read code.
I too like to do this yet I feel hobbled by the infinite loop problem on bare iron (watchdog fires off, provided it's not preprocessed out in the release). A sibling brings up the Erlang supervisor and I like failing fast and often when someone's around to see that the log's littered with restarts.
Is that the best one can hope for - to leave traces for my successor to pick up the pieces?
This is how you should use exceptions also. Let it throw. The top level exception handler (aka the supervisor) decides how deep the application is allowed to crash.