February 19, 2012
On 18/02/2012 21:07, Andrej Mitrovic wrote:
> On 2/18/12, Nathan M. Swan<nathanmswan@gmail.com>  wrote:
>> It would be nice if there was a mixin template that creates an
>> exception class that acts like this; making similar exception
>> classes is annoying.
>
> It would be even nicer if we didn't need a mixin for classes that
> simply forward the ctor call to the base class ctor:
>
> class FileException : Exception { }   // no-go, have to write a ctor
> that forwards to super
>
> AIUI this has something to do with ctors not being virtual. I think
> someone mentioned this could be improved one day.

I guess this is a bit off topic, but what you probably want is syntactic sugar that says "declare constructors matching all super constructors and calling through to them" and can be used in ANY class hierarchy (not necessarily exceptions). For example:

class Subtype : Supertype {
    super all;
}

If you want to expose just specific constructors, then there could also be a shorthand for "declare a constructor matching a specific super constructor and calling through to it" - so you don't have to repeat all the arguments. For example:

class Subtype : Supertype {
    super();
    super(string,int);
}

That would then make it an entirely separate issue and completely not Exception-specific.
February 19, 2012
On Saturday, February 18, 2012 19:01:31 Robert Jacques wrote:
> That an argument of an internationalization module as part of the standard library, not for or against a particular exception module. I don't know what a good/robust module would look like, but many open source projects simply use a global string[string] and it seems to work okay for them.

It's an argument against making it so that the only way to get the error information from an exception is toString.

Exception handling is far more flexible when the exception's type and member variables gives you the information you need to actually handle the exception - or in the case of internationalization, generate your own error message. But ideally, users wouldn't see the result of an exception's toString regardless (especially since that includes stuff like the stack trace). Not even the msg field is really acceptable for that IMHO. It's great for debugging and maybe log messages, but not dealing with the user. To deal with the user appropriately, you need to know _what_ went wrong in a way that your program can process it and react appropriately, which strings just don't do.

- Jonathan M Davis
February 19, 2012
On Sat, Feb 18, 2012 at 04:28:25PM -0800, Jonathan M Davis wrote: [...]
> C++ is a horrible example of how exceptions should be done, so if you're basing what you want off of that, then that makes me think that you should be better familiar with how other, more recent languages use them (though maybe you're quite familiar with how C# and/or Java use Exceptions, I don't know).  From using Java, I think that how it handles exceptions in general is _far_ superior to how they're frequently dealt with in C++ (though that does tend to depend on who's doing the developing, since you _can_ have a decent exception hierarchy in C++).
[...]

The basic problem with C++ exceptions is that it allows you to throw literally *anything*. Which is nice and generous, but not having a common root to all exceptions cripples the system, because there is no functionality that can be depended upon, like toString when what you want is an error message.

Furthermore, not having a properly designed skeletal hierarchy to inherit from also adds to the problem. With no existing standard hierarchy to serve as a reference point, library writers just invent their own systems, most of which don't interoperate properly with each other. And thus the mess that is the C++ exception hierarchy.

I certainly hope D can do better than that.


T

-- 
If Java had true garbage collection, most programs would delete themselves upon execution. -- Robert Sewell
February 19, 2012
On Sun, Feb 19, 2012 at 01:10:10AM +0000, Ben Davis wrote: [...]
> I guess this is a bit off topic, but what you probably want is syntactic sugar that says "declare constructors matching all super constructors and calling through to them" and can be used in ANY class hierarchy (not necessarily exceptions). For example:
> 
> class Subtype : Supertype {
>     super all;
> }
> 
> If you want to expose just specific constructors, then there could also be a shorthand for "declare a constructor matching a specific super constructor and calling through to it" - so you don't have to repeat all the arguments. For example:
> 
> class Subtype : Supertype {
>     super();
>     super(string,int);
> }
> 
> That would then make it an entirely separate issue and completely not Exception-specific.

+1.

This is definitely something not specific to Exception. Quite often, you want to create a derived class overriding just one or two members of the base class, but end up having to copy-n-paste most of the many ctors in the base class along with their elaborate arguments just so you can pass through the arguments to them.

Having a way of simply saying "the ctors in this class default to the base class ctors" will solve this problem in a very nice and logical way. (I.e., you're sortof "inheriting the base class ctors", although not exactly, of course.)


T

-- 
Today's society is one of specialization: as you grow, you learn more and more about less and less. Eventually, you know everything about nothing.
February 19, 2012
On Saturday, February 18, 2012 22:54:37 Jose Armando Garcia wrote:
> You basically agree that we need error codes inside the exception to handle database errors correctly. What about POSIX error codes? Basically in some cases you are solving the problem using inheritance in other cases you are solving the problem by switching on a variable.

There is a world of difference between having a specific exception type have an error code from an external source (e.g. a database or POSIX) and making _all_ exceptions function via error codes.

And personally, I'd argue that in many cases, the correct thing to do would be to have a base class exception type which has the error code in it (e.g. FileException) and then have derived exceptions where the one you use depends on what the error code actually was. Then additional information pertaining to that specific error code could be put in the derived exception, and you can catch the exceptions by type rather than having to resort to switching on the error type in the exception.

That way, you can actually take advantage of the exception hierarchy for controlling how you handle the exception, and you have additional information pertaining to what went wrong. And if you want access to the original error code, you have it. You can even just catch the base exception type and use a switch if you want to. But you don't have to.

- Jonathan M Davis
February 19, 2012
On Saturday, February 18, 2012 17:20:41 H. S. Teoh wrote:
> On Sun, Feb 19, 2012 at 01:10:10AM +0000, Ben Davis wrote: [...]
> 
> > I guess this is a bit off topic, but what you probably want is syntactic sugar that says "declare constructors matching all super constructors and calling through to them" and can be used in ANY class hierarchy (not necessarily exceptions). For example:
> > 
> > class Subtype : Supertype {
> > 
> >     super all;
> > 
> > }
> > 
> > If you want to expose just specific constructors, then there could also be a shorthand for "declare a constructor matching a specific super constructor and calling through to it" - so you don't have to repeat all the arguments. For example:
> > 
> > class Subtype : Supertype {
> > 
> >     super();
> >     super(string,int);
> > 
> > }
> > 
> > That would then make it an entirely separate issue and completely not Exception-specific.
> 
> +1.
> 
> This is definitely something not specific to Exception. Quite often, you want to create a derived class overriding just one or two members of the base class, but end up having to copy-n-paste most of the many ctors in the base class along with their elaborate arguments just so you can pass through the arguments to them.
> 
> Having a way of simply saying "the ctors in this class default to the base class ctors" will solve this problem in a very nice and logical way. (I.e., you're sortof "inheriting the base class ctors", although not exactly, of course.)

Feel free to open a pull request. It would certainly be a useful feature for reducing boilerplate code in some class hierarchies (though in many, the constructors in the derived class must be different, in which case it wouldn't work).

One potential issue though is that not all base classes necessarily share the same constructors. Which ones would be grabbed? The ones from the immediate base class? All of them? Only the ones common to all?

- Jonathan M Davis
February 19, 2012
On Sat, Feb 18, 2012 at 11:19 PM, Jonathan M Davis <jmdavisProg@gmx.com> wrote:
> On Saturday, February 18, 2012 22:54:37 Jose Armando Garcia wrote:
>> You basically agree that we need error codes inside the exception to handle database errors correctly. What about POSIX error codes? Basically in some cases you are solving the problem using inheritance in other cases you are solving the problem by switching on a variable.
>
> There is a world of difference between having a specific exception type have an error code from an external source (e.g. a database or POSIX) and making _all_ exceptions function via error codes.
>
> And personally, I'd argue that in many cases, the correct thing to do would be to have a base class exception type which has the error code in it (e.g. FileException) and then have derived exceptions where the one you use depends on what the error code actually was. Then additional information pertaining to that specific error code could be put in the derived exception, and you can catch the exceptions by type rather than having to resort to switching on the error type in the exception.
>
> That way, you can actually take advantage of the exception hierarchy for controlling how you handle the exception, and you have additional information pertaining to what went wrong. And if you want access to the original error code, you have it. You can even just catch the base exception type and use a switch if you want to. But you don't have to.
>

I think that is a good compromise. The one thing we need to solve is that for example Oracle's error code may collide with POSIX error code. This is why I suggested using namespace but there may be other solutions.

Thanks,
-Jose

> - Jonathan M Davis
February 19, 2012
"Andrei Alexandrescu" <SeeWebsiteForEmail@erdani.org> wrote in message news:jhos0l$102t$1@digitalmars.com...
> There's a discussion that started in a pull request:
>
> https://github.com/alexrp/phobos/commit/4b87dcf39efeb4ddafe8fe99a0ef9a529c0dcaca
>

What the hell...? It says "5 notes on commit", but only 2 are shown (both by alexrp). (And yes, that's with a modern browser with JS on.)

> From experience I humbly submit that catching by type is most of the time useless.
>

Another one for the file of "Crazy shit Andrei says" ;)

From experience, I (and clearly many others here) find a sparse, flat exception hierarchy to be problematic and limiting. But even with a rich detailed exception hierarchy, those (ie, Andrei) who want to limit themselves to catching course-grained exceptions can do so, thanks to the nature of subtyping. So why are we even discussing this?


February 19, 2012
On Saturday, February 18, 2012 23:26:35 Jose Armando Garcia wrote:
> I think that is a good compromise. The one thing we need to solve is that for example Oracle's error code may collide with POSIX error code. This is why I suggested using namespace but there may be other solutions.

What relation would POSIX and Oracle codes have though? I'd expect them to be on completely different exception types. POSIX error codes would make sense on something like FileException, whereas Oracle codes would make sense on something like DatabaseException or OracleException. The problem you run into is when you also have PostgresException and SQLLiteException which derive from DatabaseException. You could have an error code in it, but it wouldn't necessarily mean much if it weren't tied to the specific database exception type. The hierarchy that can be ignored is when OracleException or PostgresException have derived types based on the error code (which then hopefully provide additional information beyond just the error code).

But you still end up with a minimal exception hierarchy that everyone has to use if they want to stick to error codes. People can use FileException and its error code rather than FileNotFoundException and NotFileException, but they'd still have to use FileException rather than Exception to get the error code.

- Jonathan M Davis
February 19, 2012
On 19/02/2012 00:48, Jonathan M Davis wrote:
> On Saturday, February 18, 2012 16:46:43 H. S. Teoh wrote:
>> I can't believe something this simple has to be explained so
>> elaborately. I thought all of us here knew how to use OO??
>
> I think that the problem stems from people frequently using exceptions
> incorrectly, and many of the C++ programmers probably haven't _ever_ seen them
> used correctly, since I don't think that it's very common for C++ programs to
> define exception hierarchies - especially not advanced ones like Java has. And
> when you see a lot of bad exception code, that tends to turn you off to them,
> and it definitely doesn't show you how to use them correctly.
>
> - Jonathan M Davis

I can assure you they get misused in Java too. Most people write this:

try {
   lots and lots and lots of stuff here
}
catch (Exception e) {}

All they wanted to do was get round the compile error because they called Thread.sleep() which throws InterruptedException which you're required to catch, and they know they're never going to call Thread.interrupt().

What they end up doing is catching NullPointerException, ArrayIndexOutOfBoundsException and all the other things that really matter, and nasty bugs can go undiagnosed.

Eclipse's auto-fix impoves things a little - it can generate this for you:

try {
	...
}
catch (InterruptedException e) {	//For example
	//TODO: auto-generated catch block
	e.printStackTrace();
}

But no one does their TODOs, and no one takes care to keep the console output short enough to be useful.

You CAN write "throw new RuntimeException(e)", and you won't be required to catch that one. And then exceptions are incredibly useful, and I've even found rare cases where creating my own checked exception makes an API much safer. (I was processing code, and I had something like an 'uninline' operation that occasionally couldn't work, so the caller had to always have a backup plan in case the exception was thrown.)

So it could be a good system, but no one has any idea what they're doing with it.

If I had to improve the Java one, I suppose I would:

- distinguish between 'bug' exceptions (e.g. null) and 'you're more likely to want to catch this' exceptions (e.g. IO). Maybe the bug ones should have been Errors, since people *usually* don't catch those (and are certainly never required to). As it stands, Errors are reserved for corrupt class files and other VM panic scenarios.

- make sure the 'lazy' approach is a good one: the less you type, the fewer exceptions you catch, and the less likely you are to silence those exceptions at runtime. Probably the main problem with the exception hierarchy is that the short names tend to be the more general ones that are more dangerous to catch indiscriminately.