August 15, 2012
On Monday, 13 August 2012 at 15:32:45 UTC, Dmitry Olshansky wrote:
> Back to Java: what is I find strange is the lack of sensible tools to do transactional or exception safe code within the language. No RAII objects or just at least any kludge to reliably register cleanup/rollback, only "good" old try/finally.

Since Java 7, you have the same tools Haskell, Scheme, Lisp, C# and Python already offer for such cases.

For example:


try (BufferedReader br =
                   new BufferedReader(new FileReader(path))) {
        return br.readLine();
}

--
Paulo
August 15, 2012
On Tuesday, 14 August 2012 at 23:21:32 UTC, Mehrdad wrote:
> Or even better:
>
> auto joiner(RoR, Separator)(RoR r, Separator sep)
> 	throws(auto);
>
>
> That way it's easy enough for the programmer to make the compiler shut up (it's certainly easier than swallowing the exception), while allowing him to write functions that are perfectly transparent toward exceptions, and which would be allowed to throw/catch as they would in any other exception-unchecked language.
>
>
> IMO it would work well in practice.


Caveat perhaps worth mentioning:
Indirect calls (function pointers, delegates, virtual methods) would be inferred as throw-all, and would preferably give an informational warning to the user that they may need tighter exception specifications.
August 15, 2012
On Sunday, 12 August 2012 at 04:36:22 UTC, Jonathan M Davis wrote:
> On Saturday, August 11, 2012 21:27:43 Walter Bright wrote:
>> Anyhow, that article is why D does not have exception specifications. Also,
>> please note that C++ dropped exception specifications.
>
> Though it should be noted that exception specifications are _far_ worse than
> checked exceptions, because they're checked at runtime instead of compile
> time, and they kill your program if they fail. So, instead of all of the
> problems that you get with checked exceptions, you get your program killed at
> runtime when you don't get your code quite right.
>
> I think that you're going to have a hard time finding _anyone_ who actually
> understands what C++'s exception specifications do and still thinks that
> they're a good idea, whereas you _will_ find people who fully understand
> checked exceptions and still think that they're a good idea.
>
> - Jonathan M Davis

Yup, I'm among them, and I believe the only problem with checked exceptions is that most people don't understand how to use them. The main problem people have with checked exceptions is that they are forced to handle error/exceptional cases, and therefore to think about them. To my knowledge, there are no absolute rules or truths in error handling, and therefore it seems it throws people in all sorts of perplexity, because when it's not specified, programmers have no idea who is supposed to handle an exception, and how. So the worst offenders wipe them under the rug, which is borderline criminal, because it can make it nearly impossible to find the root cause of some runtime errors. Exceptions are integral part of an interface, not an afterthought, i.e they are part of an API design. But most average programmers never think about error handling until the program explodes in their face (or that of the customer). When one thinks about error handling upfront, checked exceptions aren't a problem, they are a very useful tool, and I use them all the time.

August 15, 2012
On Sunday, 12 August 2012 at 06:22:37 UTC, Marco Leise wrote:
> I read both articles and while Bruce Eckel's text read a bit like repeated "swallow exception" to "avoid reams of code" I found the interview insightful. Both aren't entirely negative on checked exceptions and Hejlsberg actually wants them:
>
>   [Anders Hejlsberg]: "And so, when you take all of these issues, to me it just seems more thinking is needed before we put some kind of checked exceptions mechanism in place for C#. But that said, there's certainly tremendous value in knowing what exceptions can get thrown, and having some sort of tool that checks."
>
> The arguments against the Java model were:
>
> 1) The programmer, annoyed by the compiler, swallows exceptions with empty catch clauses and forgets about them.
>
> I think _if_ the intention is to get back to it later, you can always write "// TODO: handle the missing icon, by loading a stock icon from the OS". On the other hand, if you just don't want to declare the thrown exception, then this is wrong thinking in my opinion. Usually when I am in this situation in Java it makes me think about the error handling: Can this error be handled gracefully? If so, right here or should it bubble up? Where is the right level to handle it? At the end of this process I have the positive feeling that I got the error handling right.
>
> 2) Versioning; a change in a function may add a thrown exception, breaking client code. Often those clients want to ignore any exceptions (and pass them on).
>
> Ok, accepted. The client code would have to change its "throws" list for no perceivable benefit.
>
> 3) Declaring the thrown exception doesn't scale well when you call into multiple subsystems that each throw different exceptions, where you would end up declaring dozens of thrown exceptions.
>
> I frankly have to say that I never worked on that big projects, that I had to declare 40 thrown exceptions. And the question may be asked if you should just wrap the exception into another at that point, because you obviously reached a granularity at which the finer details of the sub system failures have become secondary.
>
>
> So does it all boil down to the potentially long and cascading list of "throws"?
> This is not a first grade language issue, I realize that. It's just when you come across it and find yourself documenting the thrown exceptions in DDoc where they aren't checked or anything, it cries for a solution. The solution current languages take seems to be "let the exceptions slip through, more often than not you don't handle them anyway".
> How can we reap all the benefits, but avoid the manual listing of all thrown exceptions?

My experience and conclusions are very similar to yours. I would simply add that   the versioning problem simply is a change of interface. The compiler will force you to add a throws clause to your method signature if your code is likely to throw a new kind of exception (unless you handle it yourself). So you very well know you are making a breaking change, and that you risk infuriating your customers because of this. So I find it to be a fairly weak argument.
August 15, 2012
On Monday, 13 August 2012 at 08:00:33 UTC, Nathan M. Swan wrote:
> On Sunday, 12 August 2012 at 03:02:50 UTC, Marco Leise wrote:
>> I just got a bit frustrated and wanted to say that I like working with Exceptions in Java a lot more.
>
> I don't. When writing a simple command line program, when there's an error, it usually means the user messed up and I can't recover. I just print the message and terminate. I don't want to have to write "throws Exception" for everything.
>
> void main(string[] args) {
>     try {
>         realMain(args);
>         return 0;
>     } catch (Exception e) {
>         stderr.writeln(e.msg);
>     }
> }
>
> The idea sounds nice, but it's annoying in practice. The point of exceptions is to _centralize_ error handling. Being forced to either catch or declare is almost as bad as C-style errno error handling.
>

Or you could have told him HOW he messed up. By just throwing an Exception, you are not helpful at all, you are just telling that he is an ass and that he will be punished for that. Or maybe he will curse you thinking that your program doesn't work.

Let's say I write a FileParser class  which will read a table of doubles in a file. I use a number of methods defined in the JDK like say Double.parse(String) which throws a NumberFormatException("on line" + lineNumber), and catching that exception, I am able to tell the user that one of the numbers on line lineNumber is badly formatted, instead of just telling him that reading the file with 200,000 lines crashed the program. If I catch an IOException as well, I can inform him that the file is unreadable instead (but that the formatting was not yet in cause). But if I catch a FileNotFoundException first (which derives from IOException), I can be more helpful by informing him/her that the filename passed to the program is wrong.
These are entirely different classes of errors, so they need to be distinguished if they are to be handled differently, which is not possible with Exception.

> Perhaps an annotation might be nice, as long as it doesn't force catching:
>
> void buggyFunction(string file, int exception) @throws(StdioException);

It's like saying adding typing to the language is nice as long as it's not enforced by the compiler.
August 15, 2012
On 12-Aug-12 07:28, Marco Leise wrote:
> Am Sun, 12 Aug 2012 05:02:25 +0200
> schrieb Marco Leise <Marco.Leise@gmx.de>:
>
>> ---D->>
>>
>> /**
>>   * Receives a response from the server.
>>   *
>>   * Some explanation of what
>>   * the function does in detail.
>>   *
>>   * Params:
>>   *    response = receives the whole response
>>   * Throws:
>>   *    UnexpectedResponseException if the server sent us garbage
>>   *
>>   *    UnauthenticatedException we need retry after we have logged in
>>   *
>>   *    SecurityException we have to switch to a secure connection for this
>>   *
>>   *    DisconnectException the connection was unexpectedly terminated
>>   * Returns: the associated response code
>>   */
>> int foo(out string response)
>> {...}
>>
>> <<-D---
>
> could become:
>
> ---D->>
>
> /**
>   * Receives a response from the server.
>   *
>   * Some explanation of what
>   * the function does in detail.
>   *
>   * Params:
>   *    response = receives the whole response
>   * Returns: the associated response code
>   */
> int foo(out string response) throws
>      UnexpectedResponseException, /// if the server sent us garbage
>      UnauthenticatedException, /// we need retry after we have logged in
>      SecurityException, /// we have to switch to a secure connection for this
>      DisconnectException /// the connection was unexpectedly terminated
> {...}
>
> <<-D--
>

When I see code like this I have one single thought - error codes!

Indeed that's what is used in this example, with Exceptions only being convenient (and separate) transport for error codes. So the net progress is creating 1:1 type for each error condition (start counting the lines of code) and then...

If I got it right somewhere later foo is supposed to be used like this:
try{
...some_code
foo();
...other code
}
catch(UnexpectedResponseException)
{
	print error and disconnect this server or retry?
}
catch(UnauthenticatedException)
{
	print error 2
}
catch(SecurityException)
{
	sslFoo(resp); // this one is just awesome ;)
}
catch(DisconnectException )
{
	print error 3 & (ask to) reconnect?
}

Or used a catch all and do type switch Java-style to see if Exception is one of interesting to you types.  Needless to say awful again.

First SecurityError is gross fiction as you either know to authenticate (need credentials in the interface) or do auto detection (like try HTTPS, then fallback to HTTP).

Moreover encoding _cause_ of error in type is useless, end user needs a hint on the proper way to handle error. It's like pointing out a guy who made the mistake and how stupid it is instead of proposing the ways to fix the situation.

what I'd expect the code to be is (been discussed before):
class NetworkException
{
	@property bool transient; // packet lost or whatever, can re-try with the same parameters
	@property bool lost; // need reconnect to restore, server down or disconnected or unexpected input
	@property string msg();
}

This reduces all the handling to:
catch(NetworkException ne)
{
	if(ne.lost)
		//ya kill me, but you got the idea ;)
		goto ReconnectAndRetry;
	if(ne.transient){
		warning("..."); //log failure
		goto RetryAndCheckTryCount;
	}
	error(ne.msg);
}

Including but not limited to the time when foo's author adds more types to his "throws list". Unlike checked exceptions it won't break build just for the fuck of it *and* it will still work correctly.

In fact if we manage to come up with proper reasonable standard exceptions like Network/IO/etc. that everybody derives from error handling would become damn easy with *any* library.

-- 
Olshansky Dmitry
August 16, 2012
On Wednesday, 15 August 2012 at 17:44:14 UTC, SomeDude wrote:
> Or you could have told him HOW he messed up. By just throwing an Exception, you are not helpful at all, you are just telling that he is an ass and that he will be punished for that. Or maybe he will curse you thinking that your program doesn't work.
>
> Let's say I write a FileParser class  which will read a table of doubles in a file. I use a number of methods defined in the JDK like say Double.parse(String) which throws a NumberFormatException("on line" + lineNumber), and catching that exception, I am able to tell the user that one of the numbers on line lineNumber is badly formatted, instead of just telling him that reading the file with 200,000 lines crashed the program.

How checked exceptions would help you decide whether line number should be included in the error message?

> If I catch an IOException as well, I can inform him that the file is unreadable instead (but that the formatting was not yet in cause). But if I catch a FileNotFoundException first (which derives from IOException), I can be more helpful by informing him/her that the filename passed to the program is wrong.

How checked exceptions would help you design exception hierarchy? What's your point?
August 16, 2012
I had times when I missed the Java-style Exception handling.

First time I just the D sockets exceptions was thrown during runtime. The Library Reference didn't tell my anything about exceptions neither did the compiler.
This could've been avoided with documentation stating which exceptions can be thrown or if the compiler had warned me about it.
I see checked exception handling as mean to remind programmers to handle certain errors. This is not done in D.

I've also cursed the Java-style many times. For example:
interface MyInterface {
 public void method throws IOException();
}

class MyClass implements MyInterface {
 public void method throws IOException() {
  //Doesn't need throw IOException!!!!
 }
}

I liked the idea when the compiler is able to warn me about unhandled exceptions.

August 17, 2012
Am Wed, 15 Aug 2012 23:29:43 +0400
schrieb Dmitry Olshansky <dmitry.olsh@gmail.com>:

> When I see code like this I have one single thought - error codes!
> 
> Indeed that's what is used in this example, with Exceptions only being convenient (and separate) transport for error codes. So the net progress is creating 1:1 type for each error condition (start counting the lines of code) and then...
> 
> If I got it right somewhere later foo is supposed to be used like this:
> try{
> ...some_code
> foo();
> ...other code
> }
> catch(UnexpectedResponseException)
> {
> 	print error and disconnect this server or retry?
> }
> catch(UnauthenticatedException)
> {
> 	print error 2
> }
> catch(SecurityException)
> {
> 	sslFoo(resp); // this one is just awesome ;)
> }
> catch(DisconnectException )
> {
> 	print error 3 & (ask to) reconnect?
> }
> 
> Or used a catch all and do type switch Java-style to see if Exception is one of interesting to you types.  Needless to say awful again.
> 
> First SecurityError is gross fiction as you either know to authenticate (need credentials in the interface) or do auto detection (like try HTTPS, then fallback to HTTP).
> 
> Moreover encoding _cause_ of error in type is useless, end user needs a hint on the proper way to handle error. It's like pointing out a guy who made the mistake and how stupid it is instead of proposing the ways to fix the situation.
> 
> what I'd expect the code to be is (been discussed before):
> class NetworkException
> {
> 	@property bool transient; // packet lost or whatever, can re-try with
> the same parameters
> 	@property bool lost; // need reconnect to restore, server down or
> disconnected or unexpected input
> 	@property string msg();
> }
> 
> This reduces all the handling to:
> catch(NetworkException ne)
> {
> 	if(ne.lost)
> 		//ya kill me, but you got the idea ;)
> 		goto ReconnectAndRetry;
> 	if(ne.transient){
> 		warning("..."); //log failure
> 		goto RetryAndCheckTryCount;
> 	}
> 	error(ne.msg);
> }
> 
> Including but not limited to the time when foo's author adds more types to his "throws list". Unlike checked exceptions it won't break build just for the fuck of it *and* it will still work correctly.
> 
> In fact if we manage to come up with proper reasonable standard exceptions like Network/IO/etc. that everybody derives from error handling would become damn easy with *any* library.

Just for the fuck of it, huh :) ? Interesting read, do you know an example, probably a standard library of some other language, that offers standard exceptions like this? If I understand you correctly, the idea is to not use distinct error ids (be they codes or exception classes), but a mix of flags. So you'd have pretty much one "catch" with a few "if"s, but with the flags you can decide on the granularity.

-- 
Marco

August 17, 2012
Am Wed, 15 Aug 2012 19:44:13 +0200
schrieb "SomeDude" <lovelydear@mailmetrash.com>:

> On Monday, 13 August 2012 at 08:00:33 UTC, Nathan M. Swan wrote:
> > Perhaps an annotation might be nice, as long as it doesn't force catching:
> >
> > void buggyFunction(string file, int exception) @throws(StdioException);
> 
> It's like saying adding typing to the language is nice as long as it's not enforced by the compiler.

I am on the same boat, but the number of people who are annoyed by the excrescences is high. That's why I came to the conclusion that both of you should have their way. You can annotate (which means the buggyFunction can only throw StdioException), but you don't need to catch it on the caller side. (Unless you also add an @throws or nothrow there.)
Also, I want to repeat that @throws can be put into DDoc automatically, avoiding the manual documentation and resulting in more modern convenience.

-- 
Marco

1 2 3 4 5
Top | Discussion index | About this forum | D home