> On Feb 22, 2021, at 8:33 AM, Wojciech S. Czarnecki <o...@fairbe.org> wrote:
>
> Dnia 2021-02-21, o godz. 11:23:24
> robert engels <reng...@ix.netcom.com> napisał(a):
>
>> Can someone please explain the benefit of ‘error return’ over ‘checked
>> exceptions’ ?
>
> May you please explain the benefit of ‘checked exceptions’ over ‘return
> error value’?
>
> I stated and restated benefits of 'Go-way' earlier in this thread twice. I
> can only add what IMO is wrong with java exceptions:
>
> - failure context in scope is lost. Welcome back to the early C times and
> declare everything you might need before you open the try block.
Much of this was alleviated with try-with-resource. Even Go’s defer is not
perfect here, since the parameters are captured early - which leaves no choice
but to use the same pattern in Go/Java.
>
> - you have to handle failures at distance. (Or sprinkle your code with
> 'try-catch-es in density similar to Go's if-err-not-nil-es.)
>
> - you need to be aware of exceptional flows within flow of exceptions -
> accounting for niceties that may vary from implementation to implementation
> of prosthetic added to alleviate practical shortcomings of the whole
> exceptions concept:
>
>>>> If an exception is thrown from the try block and one or more exceptions are
>>>> thrown from the try-with-resources statement, then those exceptions thrown
>>>> from the try-with-resources statement are suppressed, and the exception
>>>> thrown
>>>> by the block is the one that is thrown by the writeToFileZipFileContents
>>>> method.
>>>> You can retrieve these suppressed exceptions by calling the
>>>> Throwable.getSuppressed
>>>> method from the exception thrown by the try block.
>
> Exceptions in all their glory as seen in the wild (in Oracle Java docs).
This is exactly the Scan() / ErrWriter pattern as expressed in the blog post -
but superior as you have a top-level exception generated - no such capability
in the Go model.
>
>
I am not sure what you would expect to happen here. If the primary failure was
due to a disk controller failure, and yet you try to close the file in the
exception handler, you are going to get another exception. In either case, this
should propagated as a ‘unable to write file’ (not an unable to close file).
Now, your handler could attempt to write the file elsewhere, and again would
ignore any exception (or log) any exception on the original write or close. It
all depends on the semantics of the method and what it is expected to achieve.
>> The ‘handle where they occur claim’ is weak, as you can handle exceptions at
>> the call site with similar LOC and constructs - but why
>> when in most cases (of non-trivial software) the error value is just
>> returned up.
>
> IMO "when in most cases…is just returned/thrown up" is an accessory damage
> done to the generation exposed to exceptionally toxic fumes of convoluted
> exception flows ;). No offense to Robert.
See the Scan() and ErrWriter in the blog post - this is essentially what is
done. If you have no possibly way of knowing the intermediary errors all you
can do is throw up your hands because you can’t possibly know the state of the
system. When this pattern is mixed with other code look out below.
>
>> No offense to Wojciech - the rpc transport layer doesn’t do the retires, it
>> passes up an error, and a higher level performs retry logic, if all retries
>> fail, it will pass up another error that the rpc failed, etc. This pattern
>> is used throughout well designed software.
>
>> If you hard using this pattern you are creating very hard to maintain
>> software.
>
> I hardly use other working with std libraries. But where I can I keep the
> unit sealed, testable as a black-box and replaceable. Go helps with that.
>
>> Checked exceptions are ‘error values’ with more information (e.g stack
>> traces, causes, etc.)
>
> This (more information everywhere) is also a fallacy stem mostly from the
> exceptions philosophy. I need not to build objects and move piles of data my
> code can not deal with. In Go I log this at the place of occurrence (for the
> human consumption at debug/forensics time). All what code up needs to know is
> whether this was a recoverable failure or an error. Try to recover if former,
> give up and tell supervisor if later.
Ah, but then you have brittle software, or at least limited re-use. Every time
you make the decision to I’ll just log here and ignore because I know best,
limits the ability of some other system using the code. You can argue that code
re-use is a falicy - I would not.
>
>> Can be enforced by the compiler (declared) and inspected by modern IDE’s for
>> code complete.
>
> Um... What compiler can enforce inside an 'foff/todo' (empty) catch block?
> Note that this empty catch can be silently placed way out of sight to not
> bother us in our happy flow reading experience. In Go this attitude, while it
> takes just two strokes, is visible in-place as a glaring lhs underscore.
>
That is not what I am saying. How does one write a Go program and verify that
all potential errors returned by a method are handled?
>> BUT you should not be using exceptions - or error values - for flow control.
> WUT?
>
> Every Java book 'exceptions' chapter starts along the 'use checked exceptions
> for the flow control' lines:
>
>>>> [Joshua Bloch, Effective java] Item 40: Use checked exceptions for
>>>> recoverable conditions and runtime exceptions for programming errors. E.g.
>>>> host is down, throw checked exception so the caller can either pass in a
>>>> different host address or move on to something else.
>>>> Item 41: Avoid unnecessary use of checked exceptions.
>
Those are not ‘flow’ in my definition. Flow is common expected conditions -
like ‘end of file/stream’ - that do not require “recovery". Checked exceptions
are for uncommon expected and recoverable conditions. Unchecked exceptions are
for unexpected, usually unrecoverable, conditions.
>
>> This is the fundamental problem to me with Go’s error handling -
>> the flow control and errors are mixed
>
> Whether you want it or not, you must choose the path if a failure or an error
> happens.
>
>> leading to very difficult code to read
>
> (In Go) leading to code that does what it says. And a code that says explicit
> what it is about to do if just called piece of code did not know what to do.
> All in sight. The happy path can be exposed in an IDE with a fold switch [see
> PS].
>
>> code difficult to validate that all potential paths are handled now and in
>> the future.
>
> Java compiler can validate only sad paths that it has been explicitly told of
> using 'throws' clause. Hardly 'all potential…and in the future'.
>
Not true, if you checked exceptions are added the called method, existing
caller code will fail to compile, or run (without recompilation).
> All in all: both java and Go ways are already established and used. Both are
> slowly evolving. Arguing them here over and over will not change Go usage
> patterns with even an iota for the simple fact Go does not support exceptions.
>
> P.S. You, Robert, could make a gift for others who'd like to have "lucid
> happy path view" by amending mainstream IDEs folding code with "fold to
> finger" functionality. I mean, let the IDE hide every `if err != nil` {;
> return err }` block and display 👆 (U+1F446) next to the lhs err symbol
> instead:
>
> /// Where such code
> file, err := f.Open(name)
> if err != nil {
> return err
> }
> /// would display folded as
> file, err👆 := f.Open(name)
> ///
>
> That would be way more constructive than our yak-shaving here :)
That I agree and is also why I am open to alternatives to exceptions in Go,
like forcing a method to declare all errors it might return?
>
> TC,
>
> --
> Wojciech S. Czarnecki
> << ^oo^ >> OHIR-RIPE
--
You received this message because you are subscribed to the Google Groups
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/9D5C7147-28D8-4183-9A56-E2B18202B947%40ix.netcom.com.