Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Checked Exceptions are just a small instance of a more general drive towards what Erik Meijer calls <em>type honesty</em>. I.e. procedures, methods, functions should not lie with their types. If you see a type signature, you should be able to trust its type.</p> <p>This is not true for Java today (especially if you imagine a Java-- without Checked Exceptions).</p> <p>If you have a type signature like this in Java:</p> <pre><code>Foo bar(Baz) </code></pre> <p>it says "I take a <code>Baz</code> as input and produce a <code>Foo</code> as output". But that's a lie.</p> <p>Actually, <code>bar</code> takes <em>either</em> a <code>Baz</code> <em>or</em> <code>null</code> as input. It also takes the <em>entire</em> global state, class state and instance state as input, as well as the entire universe, really (via e.g. file I/O, network I/O, database I/O and so forth). And it does not produce a <code>Baz</code> as output either: it produces <em>either</em> a <code>Foo</code> <em>or</em> <code>null</code> <em>or</em> an Exception <em>or</em> <code>Bottom</code> (i.e. nothing at all). <em>Plus</em> its output also includes the entire global state, the entire class state, the entire instance state and really also the entire state of the universe.</p> <p><code>bar</code>'s <em>actual</em> type is:</p> <pre><code>(IO&lt;Foo | null | Exception&gt; | Bottom) bar(IO&lt;Baz | null&gt;) </code></pre> <p>or something like that.</p> <p>This needs to be fixed, and Checked Exceptions are a (very small) part of that. I personally think that the other parts are more important and the Java designers should have concentrated on fixing <em>those</em> rather than exceptions (especially since exceptions are just side-effects, anyway and so you actually pretty much automatically fix exceptions for free when you fix side-effects).</p> <p>Anyway, this is why I believe that the general idea <em>behind</em> Checked Exceptions is a Good Thing&trade;, even if the specific implementation in Java might be a bit cumbersome.</p> <p>How to fix Checked Exceptions depends a lot on what exactly you think is actually <em>wrong</em> with them.</p> <p>Some people believe that the problem with Checked Exceptions is that when you change the internal implementation of your method to use a different helper method than it did before, which throws a different set of exceptions than the old one, you need to either explicitly handle those exceptions or declare them, thus breaking all your clients. Now, if that is what you think is wrong with Checked Exceptions, then there is only way to fix them: don't have them in the first place. Changing the exceptions you throw <em>is</em> a breaking change in your API contract, and breaking changes in your API contract <em>should</em> break client code. (Or more precisely: you shouldn't make breaking changes to your API contract, in order to <em>not</em> break client code.)</p> <p>I believe that the main problem with Checked Exceptions as implemented by Java is that they break one of the main features of exceptions: non-local error handling. An error happens way over here, and is handled way over there, and these two are the only ones that need to know about it. If a different kind of error can happen over here, then the <em>only</em> place that needs to know about that new error and the only place that needs to <em>change</em> is the error handler over there.</p> <p>With Checked Exceptions as implemented in Java, every piece of code in between <em>also</em> needs to change.</p> <p>One proposal to fix this problem, are <a href="http://WWW.CS.KULeuven.Be/publicaties/rapporten/cw/CW407.abs.html" rel="noreferrer">Anchored Exception Declarations</a>. (Improved in <a href="http://WWW.CS.KULeuven.Be/publicaties/rapporten/cw/CW544.abs.html" rel="noreferrer">Modular Anchored Exception Declarations</a>.)</p> <p>The idea of Anchored Exception Declarations is basically to use <em>delegation</em> for the exception declarations the same way that you use delegation in the method body, which is after all what creates the problem in the first place.</p> <p>Say you have some file reader method which delegates to another method:</p> <pre><code>String fileReader(String filename) { return this.fileHelper.read(filename); } </code></pre> <p>Now you go into the JavaDoc for <code>FileHelper#read</code> and cut&amp;paste the exception list into your method:</p> <pre><code>String fileReader(String filename) throws IOException, CustomFileReaderEx </code></pre> <p>Now the author of <code>FileHelper#read</code> decides that he uses a different implementation strategy. Now he makes sure that the <em>actual</em> file read never can fail, by first ensuring that the file exists, can be opened, and is of the right format. So, naturally, the set of exceptions changes. It is no longer possible to get an <code>IOException</code> or a <code>CustomFileReaderEx</code>. Instead you can get a <code>InvalidFilenameEx</code> or <code>CorruptDataEx</code>. So, you cut&amp;paste again:</p> <pre><code>String fileReader(String filename) throws InvalidFilenameEx, CorruptDataEx </code></pre> <p>Not only did <em>you</em> have to make that change, but everybody else who calls <code>fileReader</code> (and everybody who calls them and everybody who calls them and ...) as well. That's crazy! The reason why you delegated the call to the <code>fileHelper</code> in the first place was so that you need not concern yourself with those details.</p> <p>So, the idea of Anchored Exception Declarations is to use this delegation for the Exception Declarations themselves. Instead of saying which <em>precise</em> exceptions you throw, you just blame someone else. "He did it!":</p> <pre><code>String fileReader(String filename) throws like this.fileHelper.read </code></pre> <p>And your clients just say:</p> <pre><code>Foo whatever() throws like fileReader </code></pre> <p>That way, when <code>FileHelper</code> changes its exceptions, then the <em>only</em> code that needs to change is the very top-level exception handling code, just like I described above for the <em>unchecked</em> case.</p> <p>There are restrictions, of course. For example, in order to not break encapsulation, you can only use identifiers in your <code>throws like</code> clause which are accessible to all your clients. If, in this case, <code>fileHelper</code> is a <code>private</code> field, you cannot use it. You would need some other way. For example, if the <code>FileHelper</code> class is <code>public</code> (or if it is package private <em>and</em> all your clients live in the same package), you could instead say</p> <pre><code>String fileReader(String filename) throws like FileHelper.read </code></pre> <p>There are other restrictions listed in the paper as well. (One of those is lifted in the Modular Anchored Exception Declarations paper.)</p> <p>Anyway, this is <em>one</em> way to ameliorate some of the problems with Checked Exceptions. However, Checked Exceptions have been around for almost 40 years now, and we still haven't figured them out, so it's <em>obviously</em> a hard problem.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
    1. COThe problem with exceptions as currently implemented in most languages is that they tightly couple the type of exception with the action to be taken, when the two things are largely orthogonal. What I'd like to see would be an exception object with a virtual HasBeenSatisfied function; if an exception's HasBeenSatisfied property returns false at the end of a 'catch' block, the exception would propagate up the call stack. Many types of exception would report HasBeenSatisfied as soon as they were caught. For example, Dictionary.GetValue, when given a key that doesn't exist...
      singulars
    2. CO...has to throw an exception because it can't otherwise satisfy its post-conditions (returning a value associated with a key). Once the exception has propagated outside Dictionary.GetValue, however, the system is--as far as the Dictionary can tell--in a consistent state. It's possible that the failure to get the value will mean the object containing the dictionary is in an inconsistent state, but if that object is in an inconsistent state, such inconsistency will be implied by the fact that TryGetValue failed, rather than the particular reason for the failure.
      singulars
    3. CO@supercat: Your example of `Dictionary.GetValue` isn't a very good example of exceptions, rather it's an example of very bad API design. It shouldn't throw an exception at all, it should return a `Maybe<TValue>`.
      singulars
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload