←Older revision | Revision as of 08:45, 16 December 2016 | ||
Line 46: | Line 46: | ||
[[Category:APIDesignPatterns]] | [[Category:APIDesignPatterns]] | ||
- | [[Category:APIDesignPatterns: | + | [[Category:APIDesignPatterns:Exceptions]] |
←Older revision | Revision as of 08:45, 16 December 2016 | ||
Line 46: | Line 46: | ||
[[Category:APIDesignPatterns]] | [[Category:APIDesignPatterns]] | ||
- | [[Category:APIDesignPatterns: | + | [[Category:APIDesignPatterns:Exceptions]] |
Usage in Truffle
←Older revision | Revision as of 10:54, 15 July 2016 | ||
Line 41: | Line 41: | ||
==== Usage in [[Truffle]] ==== | ==== Usage in [[Truffle]] ==== | ||
- | This is the approach [[I]] am now trying to follow during my work on the [[Truffle]] [[API]]: clients using the system and | + | This is the approach [[I]] am now trying to follow during my work on the [[Truffle]] [[API]]: clients using the system and evaluating their code snippets don't need to care about any [[checked exception]]s. On the other hand people who implement [[Truffle]] languages (e.g. [[ProviderAPI]]) can throw any exception and it is the responsibility of the system (e.g. the [[Truffle]] [[API]]) to convert the (for example) parsing exception into something clients can swallow. Right now we are ''unchecking any [[checked exception]]'' so it can easily propagate, but other more intrinsic ways of handling them communication between [[ProviderAPI]] and [[ClientAPI]] (while keeping their [[cluelessness]]) are certainly possible. |
←Older revision | Revision as of 09:56, 15 July 2016 | ||
Line 1: | Line 1: | ||
This essay is most useful when dealing with [[Checked exception]]s as known from [[Java]], however even in systems without compile time exception checking it may be useful. The same principle of [[Covariance]]/[[Contravariance]] of [[Exception]]s applies in any language. | This essay is most useful when dealing with [[Checked exception]]s as known from [[Java]], however even in systems without compile time exception checking it may be useful. The same principle of [[Covariance]]/[[Contravariance]] of [[Exception]]s applies in any language. | ||
- | When creating both sides of an [[API]] - e.g. its [[ClientAPI]] facade as well as its [[ProviderAPI]] part, it is interesting to note that the way one deals with [[exception]]s is (or at least should be) different. | + | When creating both sides of an [[API]] - e.g. its [[ClientAPI]] facade as well as its [[ProviderAPI]] part, it is interesting to note that the way one deals with [[exception]]s is (or at least should be) different. |
+ | |||
+ | ==== The [[ClientAPI]] Point of View ==== | ||
The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them and there is no reasonable recovery. How we can prevent that? Well, the easiest thing is to not throw any [[checked exception]]s to the client. Then the clients don't need to care about the exceptions at compile time. Btw. [[I]] have to mention that [[I]] believe there are situations when clients should care about [[exception]]s and then use the [[checked exception]]s seems OK. But, if we want to take things to the extreme and if we want to make life of our [[clueless] [[API]] users absolutely [[exception]]-checkless: the less of [[checked exception|compile time checked exception]]s we throw - the easier for them during compilation. | The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them and there is no reasonable recovery. How we can prevent that? Well, the easiest thing is to not throw any [[checked exception]]s to the client. Then the clients don't need to care about the exceptions at compile time. Btw. [[I]] have to mention that [[I]] believe there are situations when clients should care about [[exception]]s and then use the [[checked exception]]s seems OK. But, if we want to take things to the extreme and if we want to make life of our [[clueless] [[API]] users absolutely [[exception]]-checkless: the less of [[checked exception|compile time checked exception]]s we throw - the easier for them during compilation. | ||
+ | |||
+ | ==== The [[ProviderAPI]] Point of View ==== | ||
However if we are creating a [[ProviderAPI]] - e.g. some interface others have to implement - the situation is quite different. We may ask them sum two numbers, but who knows what they need to do to compute that!? Maybe then need to read some files (and that in [[Java]] automatically yields {{JDK|java/io|IOException}} [[checked exception]]) or connect to network (also requires users to deal with their [[checked exception]]s). If we don't allow them to propagate the exceptions, what can they do? They have to catch them, recover from them or re-throw them. That is often correct, but certainly not [[clueless]]. What can we do to increase [[cluelessness]] of people who implement methods in a [[ProviderAPI]] that we created? Yes, we should declare that these methods can throw any {{JDK|java/lang|Exception}}. | However if we are creating a [[ProviderAPI]] - e.g. some interface others have to implement - the situation is quite different. We may ask them sum two numbers, but who knows what they need to do to compute that!? Maybe then need to read some files (and that in [[Java]] automatically yields {{JDK|java/io|IOException}} [[checked exception]]) or connect to network (also requires users to deal with their [[checked exception]]s). If we don't allow them to propagate the exceptions, what can they do? They have to catch them, recover from them or re-throw them. That is often correct, but certainly not [[clueless]]. What can we do to increase [[cluelessness]] of people who implement methods in a [[ProviderAPI]] that we created? Yes, we should declare that these methods can throw any {{JDK|java/lang|Exception}}. | ||
+ | |||
+ | ==== Don't Mix [[ClientAPI]] and [[ProviderAPI]] ==== | ||
This is just another example of [[APIvsSPI]] difference! These needs and expectations for dealing with [[exception]]s when using a [[ClientAPI]] are different then when implementing a [[ProviderAPI]]. Obvious conclusion: never mix [[ClientAPI]] and [[ProviderAPI]] as then you cannot satisfy the different needs. | This is just another example of [[APIvsSPI]] difference! These needs and expectations for dealing with [[exception]]s when using a [[ClientAPI]] are different then when implementing a [[ProviderAPI]]. Obvious conclusion: never mix [[ClientAPI]] and [[ProviderAPI]] as then you cannot satisfy the different needs. | ||
Line 33: | Line 39: | ||
now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exception]]s. | now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exception]]s. | ||
- | + | ==== Usage in [[Truffle]] ==== | |
+ | This is the approach [[I]] am now trying to follow during my work on the [[Truffle]] [[API]]: clients using the system and evaluation their code snippets don't need to care about any [[checked exception]]s. On the other hand people who implement [[Truffle]] languages (e.g. [[ProviderAPI]]) can throw any exception and it is the responsibility of the system (e.g. the [[Truffle]] [[API]]) to convert the (for example) parsing exception into something clients can swallow. Right now we are ''unchecking any [[checked exception]]'' so it can easily propagate, but other more intrinsic ways of handling them communication between [[ProviderAPI]] and [[ClientAPI]] (while keeping their [[cluelessness]]) are certainly possible. | ||
←Older revision | Revision as of 18:02, 14 July 2016 | ||
Line 33: | Line 33: | ||
now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exception]]s. | now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exception]]s. | ||
- | + | This is the approach [[I]] am now trying to follow during my work on the [[Truffle]] [[API]]: clients using the system and evaluation their code snippets don't need to care about any [[checked exception]]s. On the other hand people who implement [[Truffle]] languages (e.g. [[ProviderAPI]]) can throw any exception and it is the responsibility of the system (e.g. the [[Truffle]] [[API]]) to convert the (for example) parsing exception into something clients can swallow. Right now we are ''unchecking any [[checked exception]]'' so it can easily propagate, but other more intrinsic ways of handling them communication between [[ProviderAPI]] and [[ClientAPI]] (while keeping their [[cluelessness]]) are certainly possible. | |
←Older revision | Revision as of 17:55, 14 July 2016 | ||
Line 31: | Line 31: | ||
</source> | </source> | ||
- | now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked | + | now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exception]]s. |
←Older revision | Revision as of 17:55, 14 July 2016 | ||
Line 7: | Line 7: | ||
However if we are creating a [[ProviderAPI]] - e.g. some interface others have to implement - the situation is quite different. We may ask them sum two numbers, but who knows what they need to do to compute that!? Maybe then need to read some files (and that in [[Java]] automatically yields {{JDK|java/io|IOException}} [[checked exception]]) or connect to network (also requires users to deal with their [[checked exception]]s). If we don't allow them to propagate the exceptions, what can they do? They have to catch them, recover from them or re-throw them. That is often correct, but certainly not [[clueless]]. What can we do to increase [[cluelessness]] of people who implement methods in a [[ProviderAPI]] that we created? Yes, we should declare that these methods can throw any {{JDK|java/lang|Exception}}. | However if we are creating a [[ProviderAPI]] - e.g. some interface others have to implement - the situation is quite different. We may ask them sum two numbers, but who knows what they need to do to compute that!? Maybe then need to read some files (and that in [[Java]] automatically yields {{JDK|java/io|IOException}} [[checked exception]]) or connect to network (also requires users to deal with their [[checked exception]]s). If we don't allow them to propagate the exceptions, what can they do? They have to catch them, recover from them or re-throw them. That is often correct, but certainly not [[clueless]]. What can we do to increase [[cluelessness]] of people who implement methods in a [[ProviderAPI]] that we created? Yes, we should declare that these methods can throw any {{JDK|java/lang|Exception}}. | ||
- | This is just another example of [[APIvsSPI]] difference! | + | This is just another example of [[APIvsSPI]] difference! These needs and expectations for dealing with [[exception]]s when using a [[ClientAPI]] are different then when implementing a [[ProviderAPI]]. Obvious conclusion: never mix [[ClientAPI]] and [[ProviderAPI]] as then you cannot satisfy the different needs. |
+ | |||
+ | What shall we do (to increase [[cluelessness]] of everyone)? We have to adopt the [[APIvsSPI]] separation - e.g. have a special types for [[ClientAPI]], have another special types for [[ProviderAPI]] and let our [[API]] internals to be a mediator between these two. Let's try to demonstrate the approach on a decryption example. The client may have an array of bytes and wants to ask the system to decode them: | ||
+ | |||
+ | <source lang="java"> | ||
+ | byte[] arr = ...; | ||
+ | byte[] output = new byte[arr.length]; | ||
+ | if (Decoder.decode(arr, output)) { // doesn't throw any checked exceptions | ||
+ | System.out.println("The result is " + output); | ||
+ | } else { | ||
+ | System.err.println("Cannot decode"); | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | in this example the client doesn't have to deal with any exceptions. The only problem that can appear is that the decoding isn't allowed, but that one is signaled by a '''false''' return value (not that [[I]] would consider such return value as a best alternative, but it shows the point). Now imagine a [[ProviderAPI]] for those who want to write their own decoder: | ||
+ | |||
+ | <source lang="java"> | ||
+ | public interface DecoderImplementation { | ||
+ | public void decode(byte[] input, byte[] output) throws Exception; // yes, let's allow any error | ||
+ | } | ||
+ | public final class CannotDecodeException extends Exception { | ||
+ | } | ||
+ | </source> | ||
+ | |||
+ | now: whoever provides the decoder implementation, isn't limited by any exceptions. It is possible to throw anything - yet, some exceptions make bigger sense than other. For example the '''CannotDecodeException''' is well understood by the system and gets converted into '''false''' return value from the [[ClientAPI]] call to decode something. The other [[exception]]s then just propagate. How can that be done? It can be done because the [[ClientAPI]] doesn't deal directly with '''DecoderImplementation'''s, but rather thru a mediator - the [[API]]. And the [[API]] makes sure it converts the well understood [[ProviderAPI]] exceptions into the output [[ClientAPI]] can understand too, while allowing both sides to be almost completely [[clueless]] about the [[checked exceptions]]. | ||
+ | |||
+ | |||
+ | |||
+ | |||
[[Category:APIDesignPatterns]] | [[Category:APIDesignPatterns]] | ||
[[Category:APIDesignPatterns:Exceptional]] | [[Category:APIDesignPatterns:Exceptional]] |
←Older revision | Revision as of 17:35, 14 July 2016 | ||
Line 4: | Line 4: | ||
The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them and there is no reasonable recovery. How we can prevent that? Well, the easiest thing is to not throw any [[checked exception]]s to the client. Then the clients don't need to care about the exceptions at compile time. Btw. [[I]] have to mention that [[I]] believe there are situations when clients should care about [[exception]]s and then use the [[checked exception]]s seems OK. But, if we want to take things to the extreme and if we want to make life of our [[clueless] [[API]] users absolutely [[exception]]-checkless: the less of [[checked exception|compile time checked exception]]s we throw - the easier for them during compilation. | The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them and there is no reasonable recovery. How we can prevent that? Well, the easiest thing is to not throw any [[checked exception]]s to the client. Then the clients don't need to care about the exceptions at compile time. Btw. [[I]] have to mention that [[I]] believe there are situations when clients should care about [[exception]]s and then use the [[checked exception]]s seems OK. But, if we want to take things to the extreme and if we want to make life of our [[clueless] [[API]] users absolutely [[exception]]-checkless: the less of [[checked exception|compile time checked exception]]s we throw - the easier for them during compilation. | ||
+ | |||
+ | However if we are creating a [[ProviderAPI]] - e.g. some interface others have to implement - the situation is quite different. We may ask them sum two numbers, but who knows what they need to do to compute that!? Maybe then need to read some files (and that in [[Java]] automatically yields {{JDK|java/io|IOException}} [[checked exception]]) or connect to network (also requires users to deal with their [[checked exception]]s). If we don't allow them to propagate the exceptions, what can they do? They have to catch them, recover from them or re-throw them. That is often correct, but certainly not [[clueless]]. What can we do to increase [[cluelessness]] of people who implement methods in a [[ProviderAPI]] that we created? Yes, we should declare that these methods can throw any {{JDK|java/lang|Exception}}. | ||
+ | |||
+ | This is just another example of [[APIvsSPI]] difference! | ||
+ | |||
+ | |||
+ | [[Category:APIDesignPatterns]] | ||
+ | [[Category:APIDesignPatterns:Exceptional]] |
←Older revision | Revision as of 17:27, 14 July 2016 | ||
Line 3: | Line 3: | ||
When creating both sides of an [[API]] - e.g. its [[ClientAPI]] facade as well as its [[ProviderAPI]] part, it is interesting to note that the way one deals with [[exception]]s is (or at least should be) different. | When creating both sides of an [[API]] - e.g. its [[ClientAPI]] facade as well as its [[ProviderAPI]] part, it is interesting to note that the way one deals with [[exception]]s is (or at least should be) different. | ||
- | The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them | + | The biggest drawback of [[Checked exception]]s in [[Java]] is when they force callers to catch them and there is no reasonable recovery. How we can prevent that? Well, the easiest thing is to not throw any [[checked exception]]s to the client. Then the clients don't need to care about the exceptions at compile time. Btw. [[I]] have to mention that [[I]] believe there are situations when clients should care about [[exception]]s and then use the [[checked exception]]s seems OK. But, if we want to take things to the extreme and if we want to make life of our [[clueless] [[API]] users absolutely [[exception]]-checkless: the less of [[checked exception|compile time checked exception]]s we throw - the easier for them during compilation. |
New page: This essay is most useful when dealing with Checked exceptions as known from Java, however even in systems without compile time exception checking it may be useful. The same princi...
New page