View mode: basic / threaded / horizontal-split · Log in · Help
August 15, 2012
Re: Exception programming difficult
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
Re: Exception programming difficult
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
Re: Exception programming difficult
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
Re: Exception programming difficult
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
Re: Exception programming difficult
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
Re: Possible "throws" syntax
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
Re: Exception programming difficult
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
Re: Exception programming difficult
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
Re: Possible "throws" syntax
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
Re: Exception programming difficult
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