top | item 40485553

(no title)

kdmccormick | 1 year ago

Unless you're using exclusively Java-style checked exceptions, then there literally (literally!) is huge difference. That is:

    def main():
        try:
            my_a = a()
        except ExA, ExB:
            my_a = None
        ...
         
    def a() -> A:
        ...
        my_b = b()
        ...

    def b() -> B:
        ...
If b changes its signature to return type C, then it is a type error in a. main doesn't need to worry about what b returns; only a does.

BUT if b begins raising ExC instead of ExB, then that will break main at runtime. That is, main needs to be aware of what b could raise, even though it doesn't directly call it.

discuss

order

wvenable|1 year ago

This is unrealistic example and has error handling completely backwards. The exception handler in main() only knows how to handle specific types of errors -- it doesn't know or care where they are thrown, that's not it's problem. Lets say, for example, it knows it can handle network errors by retrying the operation.

If b() changes to throw a different type of exception that main() doesn't know to handle them main will break. And breaking is entirely the correct behaviour.

Maybe b() is an interface and the actual implementation might not even have existed when main() was written. Maybe yesterday it was implemented with a file, tomorrow with a HTTP call, and maybe next week something else. But tomorrow, at least, it can retry the operation when it fails.

kdmccormick|1 year ago

That's all great in theory, but in practice, I see except clauses mostly used to handle particular exception classes that callees are known to throw.

otabdeveloper4|1 year ago

Literally the exact same thing happens if you use exception passing style and encapsulate all errors as a generic `Error` type. (Which is what everyone does in practice.)