4 ms·
I concur. Many people have an insufficient understanding of contracts - especially concerning the difference between refusing a service, and failing because of
by dawidloubser 11y ago
I concur. Many people have an insufficient understanding of contracts - especially concerning the difference between refusing a service, and failing because of an error.
An inherent requirement for any contract language is a signal to refuse a service if the pre-conditions are not met (for example, refusing to withdraw money because of insufficient funds in an account).
The most pragmatic solution to this inherent feature of contracts are typed (checked) exceptions - anything else is a less robust, incomplete solution.
- thrownaway2424 11y agoNothing in the first part of your post supported the conclusion. gRPC has an error code it can return, FAILED_PRECONDITION. Why are exceptions more robust or more complete than that?
- nbevans 11y agoThey aren't. He just wants to be able to leak stuff like "IOException: disk space full whilst writing to 'C:\some\path\that\probably\ought\to\not\be\revealed\outside\this\gRPC\server'." to his client app when all the client app really cares about is whether it is a transient or permanent failure.
- PaulHoule 11y agoHere is my thought. First of all for debugging it is a huge help to get as rich data back as you can from the other end and logged. As for the proper handling of exceptions, I think there are a number of semantic attributes that an exception can have: for instance, transient/permanent, and the scope of the exception (is the whole system hosed? just this record? etc.) In a greenfield application you can build an exception hierarchy that records this, but in the real world it is necessary to build a system that does some inference, or even guessing, to decide what to do about a failure. I just remember the bad old days when C programs would return an int and it would be -1 if the function failed, or maybe they set errno, and either way you could double the size of some functions if you add in error checking and probably get it wrong. Exceptions on the other hand are good for the normal kind of call stack and also work in "callback hell" situations since you can stuff them in a field or collection, pass them as a function method, etc.
- nostrademons 11y agoSo return an error message with structured data about the error, and then log it in your protocol layer. Most of the time, when you're handling RPCs, you're processing the responses asynchronously anyway, which makes the concept of an exception (which unwinds the stack) superfluous anyway. You should absolutely be handling error conditions. That doesn't mean you need to use the language mechanisms of exceptions to do so. CORBA got into trouble because it tried to make remote objects look too much like local objects. Don't think that way: think in terms of messages passed between communicating sequential processes, with an error indicating that the process will have to do something else.
- dawidloubser 11y agoAbsolutely not - the people who do that, don't understand the difference between refusal (precondition not met), and failure (unexpected system error). In your particular case above, I would never let IOException leak "up" into a client-facing contract. How could I? I would have designed that interface long before implementing it. No, in that case, this is an unexpected system error - for example, an unchecked RuntimeException in Java. Just because people don't know how to write software contracts properly, doesn't mean that languages and protocols should remove the notion of a checked exception. When used properly, they are an essential part of an understandable contract. And that's before we even look at it from a type system point of view, where it's absolutely silly to use the same response message to represent either success of failure, greatly increasing the cognitive overhead of the developer calling your service.
- nbevans 11y agoYou need to learn more languages. "Checked exception" is highly Java-specific and it is biasing your understanding. A checked exception is okay but it is still an exception with all the stack frame capturing overhead that brings. In better languages like ML variants (say F#) we have discriminated unions. These let us return structured, type safe, result codes and information. Without all the overhead and OO-ness of nasty exceptions. We can still throw exceptions but these are strictly, and I mean strictly, for those very exceptional and unexpected scenarios.