Some thoughts and an idea about Checked Exceptions

David Alayachew davidalayachew at gmail.com
Mon Dec 4 01:37:47 UTC 2023


Hello Brian,

Thank you for your response!

> > I actually like Checked Exceptions. I think that, when
> > used correctly, they enable an easy to read style of
> > programming that separates the mess from the happy
> > path.
>
> This is an important point; for all the folks out there
> who love to thump the table with "Checked exceptions were
> a failed experiment", there are plenty of people who see
> value in them quietly getting work done.

In their defense, it took me a long time to "see the light" too.

Long story short, I had the great pleasure to work on a codebase at work
that actually treats its Exceptions like first class citizens. Using my toy
example from above, we might have had the directory creation Exception have
a DirectoryNameClashException, which has subtypes clarifying the different
types of name clash (clash with another directory, vs clash with a file on
the rare OS that cares about that). So, you can use the Exception type to
decide what to fail on and what to recover on.

> > I think Checked Exceptions are at their best when only
> > one method of a try block can throw a specific
> > exception. Meaning, there is no overlap between the
> > Checked Exceptions of methodA and methodB. This is
> > great because, then, you can wrap all "Throwable"
> > methods in a single try block, and then each catch has
> > a 1-to-1 mapping with the code that can throw it.
>
> I know what you mean, but I think there are several
> moving parts here. There is the checked-vs-unchecked
> dimension (which is a declaration-site property), which
> ideally is about whether the exception has a reasonably
> forseeable recovery. (FileNotFoundException is
> recoverable -- you can prompt the user for another file
> name, whereas getting an IOException on close() is not
> recoverable -- what are you going to do, close it again?)
> ...
> The point you raise is really more about the `try`
> statement than checked exceptions themselves

Thanks for helping translate my thoughts. Yes, try is really the target
here. I was too focused on my specific use case to notice that at the time.

> So checked exceptions are best when they are signalling
> something that a user _wants_ to catch so they can try
> something else, and unchecked exceptions are better when
> there is no forseeable recovery other than log it, cancel
> the current unit of work, and then either exit or go back
> to the main event loop.

I appreciate you pointing this out. This is a way better mental model than
I had.

> The proposal you make, which basically allows users to
> associate invocation context with a region of code that
> is attached to any exceptions thrown from that region, is
> interesting but likely too specialized to be broadly
> useful. Attaching metadata to exceptions is a rich and
> useful vein of ideas (including attaching context
> information useful in debugging or diagnosing test
> failure), but this one seems at the narrow end of that
> vein. But, if you look at catch clauses as pattern
> matches, which currently are restricted to the type of
> the exception, there is much room to refine the
> specificity of such patterns.

WOW - the pattern matching well is bottom less.

I feel like the idea was mentioned before, but I never considered it like
this. So, we could have the same, basic exception that we always had, but
could now enhance the Exception to include metadata that we can now unbox
with pattern-matching to get a more specific cause?

If so, that's a way better idea than mine. All existing Exception
infrastructure stays as is, but underneath the surface, we can enhance the
error throwing logic to include better detail. The example I gave above for
FileAlreadyExistsException could include the offending path. Then, rather
than having an Exception for clashing with a file and another for clashing
with a directory, I can just have a clash exception that has a field to
represent what I am clashing with, extract it via Pattern Matching, and
maybe there is even a nested pattern on that object that tells me whether
it is a file or directory.

It would mean we are leaning harder on the contracts of methods, but that
actually sounds like a good thing. For example, in the past we would just
say "if this failure happens, it will throw ExceptionA". Now, we might want
to specify what metadata will be included in ExceptionA, so that users know
what to extract, in case it isn't obvious.

In that case, I'll put my current idea to rest, since I see that Pattern
Matching pretty much eclipses it in almost every single way. Hope to see
this vein of pattern matching see the light of day soon!

Thank you for your time and help!
David Alayachew

On Sun, Dec 3, 2023 at 7:52 PM Brian Goetz <brian.goetz at oracle.com> wrote:

>
>
> I actually like Checked Exceptions. I think that, when used correctly,
> they enable an easy to read style of programming that separates the mess
> from the happy path.
>
>
> This is an important point; for all the folks out there who love to thump
> the table with "Checked exceptions were a failed experiment", there are
> plenty of people who see value in them quietly getting work don.
>
> I think Checked Exceptions are at their best when only one method of a try
> block can throw a specific exception. Meaning, there is no overlap between
> the Checked Exceptions of methodA and methodB. This is great because, then,
> you can wrap all "Throwable" methods in a single try block, and then each
> catch has a 1-to-1 mapping with the code that can throw it.
>
>
> I know what you mean, but I think there are several moving parts here.
> There is the checked-vs-unchecked dimension (which is a declaration-site
> property), which ideally is about whether the exception has a reasonably
> forseeable recovery.  (FileNotFoundException is recoverable -- you can
> prompt the user for another file name, whereas getting an IOException on
> close() is not recoverable -- what are you going to do, close it again?)
> So checked exceptions are best when they are signalling something that a
> user _wants_ to catch so they can try something else, and unchecked
> exceptions are better when there is no forseeable recovery other than log
> it, cancel the current unit of work, and then either exit or go back to the
> main event loop.
>
> The point you raise is really more about the `try` statement than checked
> exceptions themselves; the main body of a `try` is a block statement.  The
> block might do IO in a dozen places, but most of the time, we want to treat
> them all as "some IO operation in this block failed"; it is rare that we
> want to separate failure on a write from failure on a close.  Of course,
> there are "exceptions" to every rule.  Catch was also later extended to let
> you handle multiple exceptions with the same handler (catch IOE|SQLE),
> which further fits into the "aggregation" aspect of try-catch.
>
> The proposal you make, which basically allows users to associate
> invocation context with a region of code that is attached to any exceptions
> thrown from that region, is interesting but likely too specialized to be
> broadly useful.  Attaching metadata to exceptions is a rich and useful vein
> of ideas (including attaching context information useful in debugging or
> diagnosing test failure), but this one seems at the narrow end of that
> vein.  But, if you look at catch clauses as pattern matches, whcih
> currently are restricted to the type of the exception, there is much room
> to refine the specificity of such patterns.
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/amber-dev/attachments/20231203/2f428d43/attachment-0001.htm>


More information about the amber-dev mailing list