D - Praise, Contract Programming, and Exceptions
- Eric Gerlach (59/59) Aug 25 2001 Hello all,
- Eric Gerlach (34/34) Aug 25 2001 In anticipation of those that disagree with a semi-mandatory 'throws'
- Bradeeoh (22/55) Aug 25 2001 I've been doing an INCREDIBLY large amount of Java programming lately, a...
- Dan Hursh (13/89) Aug 26 2001 Well, I don't want to say anything nice about java but I would like to
- Eric Gerlach (31/42) Aug 26 2001 I don't usually advocate Java either... I'm only half-pleased with their...
- Sean L. Palmer (1/3) Nov 03 2001 Yes.
- Walter (8/8) Aug 26 2001 Here's my problem with a throws clause:
- Eric Gerlach (53/64) Aug 26 2001 If you think about it, either way it breaks code reuse. In fact,
- Russell Bornschlegel (12/27) Aug 26 2001 Eric, thanks for your excellent example here. I'd been leaning
- Walter (8/15) Aug 27 2001 Since, in C++, you can throw any type, but in D, you can only throw clas...
- Sean L. Palmer (7/12) Nov 03 2001 Perhaps if the compiler detects exceptions that aren't handled, it might
- Eric Gerlach (26/37) Aug 27 2001 The thing is, the language uses exceptions as its method of
- Dan Hursh (32/37) Aug 27 2001 That's scary. Do you mean it would make sure they are meaningful? If
- Chris Friesen (7/12) Aug 27 2001 So then the compiler has to construct some kind of lookup table as to wh...
- Eric Gerlach (10/14) Aug 27 2001 I'm not sure that's true. As I'm going over the parse tree, when in a
- Dan Hursh (17/35) Aug 27 2001 Actually, when in a function with a throws clause, you have to check
- Eric Gerlach (25/39) Aug 28 2001 Well, if *all* the functions had mandatory throws clauses that wouldn't
- Walter (11/18) Aug 28 2001 One thing I haven't mentioned in the docs, but is a design goal, is to n...
- Eric Gerlach (39/59) Aug 28 2001 I thought that might be the case due to how you deal with what used to
- Walter (3/14) Aug 28 2001 Every compiler switch is a bug.
- Eric Gerlach (16/31) Aug 29 2001 eep!
- Walter (9/25) Sep 01 2001 Yes, of course. I was referring to the idea that compiling a program sho...
- Dan Hursh (4/5) Aug 29 2001 Especially that '-o' one. If it ain't called a.out, I ain't runnin'
- Walter (4/9) Sep 01 2001 -o is a bug. After all, the compiler should be smart enough to figure ou...
- Angus Graham (6/9) Sep 02 2001 So make sure not to call any files win.c! :-)
- John Carney (2/5) Aug 29 2001 Type safety? Encapsulation? The list goes on...
- Dan Hursh (19/31) Aug 26 2001 You are right, but I consider it a side affect of the interface of D
- John Carney (18/35) Aug 28 2001 I'd much rather require that a method without an exception contract stat...
- Dan Hursh (37/62) Aug 28 2001 But this seems to defeat the lazy programer's purpose. He's LAZY. He
- John Carney (25/73) Aug 29 2001 state it
- Dan Hursh (43/83) Aug 29 2001 In that case, let me make Walter's case stronger for him. What good
- kaffiene (9/24) Aug 30 2001 him
- Dan Hursh (19/48) Aug 30 2001 I think you are mistaking what I am saying. Exceptions are still
- kaffiene (17/57) Aug 30 2001 He
- Russ Lewis (8/24) Aug 31 2001 The compiler can analyze each function individually. If you throw an ex...
- kaffiene (9/18) Aug 30 2001 I've been programming Java/C++/C interchangibly over the past three year...
- Jim Farrand (13/22) Aug 29 2001 But C, B and A *should* be updated. If D now throws another type of
Hello all, (Author's note: This started out as a much shorter post that was meant to go in another thread... but it kept growing and growing, like Jack's beanstalk.) First of all, Walter, I'd like to applaud you and your wonderful creation. D is a language that shows some real promise as an industry standard. I'm very, very excited about being able to try it eventually. I think that above and beyond all the other improvements of the language, D's strongest feature is how it encourages robust programming. Adding contracts (in/out/invariant) as a language construct is a great idea. All too often a function that someone else writes doesn't do exactly what you thought it would for a boundary case, and having an easy way to know that it's their function and not your code screwing up would be wonderful. I also love the idea of unit testing built into the classes. In my experience, it won't get done well otherwise :) However, I don't think D takes contracts far enough. I think that all of a function's behaviour should be able to be described in the contract. Specifically, not having a 'throws' clause in a language that *encourages* throwing exceptions is suicide for the robustness that D appears to give. I'm not going to reiterate all of the reasons to have 'throws' here, because I think they have been well enough stated in the threads: "throws?" and "Exception specification?" But I am going to say that it is essential to providing the full and complete contract to a function. When programming by contract, there are always 2 parties to the contract, the user and the implementor. The implementor sets out a set of requirements and says "If these requirements are fulfilled, then I will do this!" and presents a set of results. Breaking a contract goes two ways. If the user does not meet the requirements, the contract is broken, and the implementor is under no obligation to fulfill it. However, if the implementor fails to finish the results, they have broken the contract, and the user will not be happy. Now, let's take a rather funny hypothetical situation: Implementors and users (the coders, not the code) will be fined $100 every time they break a contract. Therefore, both implementors and users will want to keep their contracts all the time to avoid being fined. But the implementors are in a bind. Let's say that the 'connect()' function's contract says: "Call me, and I will connect to the server!" What if the network is down? It's not the connect() function's fault, but that coder will be fined because he broke the contract with the user. Exceptions are the way out. They allow an implementor to say: "Call me, and I will connect to the server EXCEPT if the network is down, or it's Tuesday!" Now the implementor isn't held liable if the network is down. Rejoice! He doesn't get fined! But without a 'throws' clause in a function declaration, the implementor isn't able to do this. The 'connect()' function isn't able to give a complete contract to the world on how to use it. The bottom line is that the 'throws' clause is necessary to provide complete contract programming. If it isn't going to be in the language, you might as well get rid of all the contract programming constructs (in, out, invariant), as they lose much of their meaning, and only provide weak contracts. Now, a disclaimer: This is my only major plea about D. I love the rest of the language. If D catches on, it will be a Very Good Thing. Cheers, Eric P.S. I'm going to make another post in a minute about some more ideas for exceptions P.P.S. After that I'll make a post about a few more small things
Aug 25 2001
In anticipation of those that disagree with a semi-mandatory 'throws' clause, I'm going to take some arguments from a "better than C++" exception implementation, Java. One of the concerns people have with making exceptions mandatory is the need to then either catch every possible exception, or specify it in your throws declaration. Now while this is true, it's not such a bad thing. Java deals with it nicely in two ways. To understand the first method, read section 11.2 (including 11.2.1 and 11.2.2) in the Java Language Speccification to be found at: (I strongly encourage reading the entire section 11, it's not that long) Java allows RuntimeExceptions and Errors not to be declared in the throws, because those ones either are unidentifiable at compile time, or are serious and rare enough to bypass the decalaration rule. All others must be, and I'd argue should be, based on my previous post. The second method is documented in Java's documentation on Throwable: http://java.sun.com/j2se/1.4/docs/api/java/lang/Throwable.html There's a bit in the middle that talks about 'chaining' of exceptions, which allows an exception to know what exception caused it to be thrown. Essentially what it allows is this (from the page): try { lowLevelOp(); } catch LowLevelException(le) { throw new HighLevelException(le); // Chaining-aware constructor } Then the code catching the HighLevelException(he) can call he.getCause() to get the LowLevelException. That way, all sorts of low level network exceptions could be abstracted to NetworkException at a higher level with a chain down to the lower-level exception. Anyways, seek out that part and read it. Good stuff. I hope this addresses some of the concers that people have had with this clause in previous posts. Cheers, Eric
Aug 25 2001
I've been doing an INCREDIBLY large amount of Java programming lately, and I just want to say that I knew this, and because of my experience with it, know how invaluabl it is. I want to second absolutely every thing you said in your first post and the follow up and say that, indeed, the throws clause is completely neccesary for real, complete contracted programming (or some substitution thereof) and is even fairly critical outside of contracts (ie, Java) Of the many reasons programming in Java can go so much quicker and smoother, I think the throws concept requiring Exceptions to be caught is one of them, because the compiler KNOWS there may be an exception, and it doesn't let you code without catching the exception and findout later after 2 days of debugging it was that damned Exception all along when, if you were forced to catch it, you would've figured it out in 3 seconds after trying to compile your code without it. <phew> Anyway, long story short - throws = important and required, please include. :) -Brady "Eric Gerlach" <egerlach canada.com> wrote in message news:3B883583.1020802 canada.com...In anticipation of those that disagree with a semi-mandatory 'throws' clause, I'm going to take some arguments from a "better than C++" exception implementation, Java. One of the concerns people have with making exceptions mandatory is the need to then either catch every possible exception, or specify it in your throws declaration. Now while this is true, it's not such a bad thing. Java deals with it nicely in two ways. To understand the first method, read section 11.2 (including 11.2.1 and 11.2.2) in the Java Language Speccification to be found at:4121(I strongly encourage reading the entire section 11, it's not that long) Java allows RuntimeExceptions and Errors not to be declared in the throws, because those ones either are unidentifiable at compile time, or are serious and rare enough to bypass the decalaration rule. All others must be, and I'd argue should be, based on my previous post. The second method is documented in Java's documentation on Throwable: http://java.sun.com/j2se/1.4/docs/api/java/lang/Throwable.html There's a bit in the middle that talks about 'chaining' of exceptions, which allows an exception to know what exception caused it to be thrown. Essentially what it allows is this (from the page): try { lowLevelOp(); } catch LowLevelException(le) { throw new HighLevelException(le); // Chaining-aware constructor } Then the code catching the HighLevelException(he) can call he.getCause() to get the LowLevelException. That way, all sorts of low level network exceptions could be abstracted to NetworkException at a higher level with a chain down to the lower-level exception. Anyways, seek out that part and read it. Good stuff. I hope this addresses some of the concers that people have had with this clause in previous posts. Cheers, Eric
Aug 25 2001
Well, I don't want to say anything nice about java but I would like to re-second this. I would like to be able to look at a function and have a reasonable idea of the error I need to be ready to handle. I wouldn't against having the default behavior (when there is no throws clause) be that it can throw anything, so only the masochists need declare what they are doing. I do believe that any library that wants to be taken seriously should, by convention, declare throws clauses for every method. This way folks who like to try to recover or clean up can have some idea what can go wrong. Otherwise I don't see how you could do anything more that say "I died because " + exception.msg(); Dan Bradeeoh wrote:I've been doing an INCREDIBLY large amount of Java programming lately, and I just want to say that I knew this, and because of my experience with it, know how invaluabl it is. I want to second absolutely every thing you said in your first post and the follow up and say that, indeed, the throws clause is completely neccesary for real, complete contracted programming (or some substitution thereof) and is even fairly critical outside of contracts (ie, Java) Of the many reasons programming in Java can go so much quicker and smoother, I think the throws concept requiring Exceptions to be caught is one of them, because the compiler KNOWS there may be an exception, and it doesn't let you code without catching the exception and findout later after 2 days of debugging it was that damned Exception all along when, if you were forced to catch it, you would've figured it out in 3 seconds after trying to compile your code without it. <phew> Anyway, long story short - throws = important and required, please include. :) -Brady "Eric Gerlach" <egerlach canada.com> wrote in message news:3B883583.1020802 canada.com...In anticipation of those that disagree with a semi-mandatory 'throws' clause, I'm going to take some arguments from a "better than C++" exception implementation, Java. One of the concerns people have with making exceptions mandatory is the need to then either catch every possible exception, or specify it in your throws declaration. Now while this is true, it's not such a bad thing. Java deals with it nicely in two ways. To understand the first method, read section 11.2 (including 11.2.1 and 11.2.2) in the Java Language Speccification to be found at:4121(I strongly encourage reading the entire section 11, it's not that long) Java allows RuntimeExceptions and Errors not to be declared in the throws, because those ones either are unidentifiable at compile time, or are serious and rare enough to bypass the decalaration rule. All others must be, and I'd argue should be, based on my previous post. The second method is documented in Java's documentation on Throwable: http://java.sun.com/j2se/1.4/docs/api/java/lang/Throwable.html There's a bit in the middle that talks about 'chaining' of exceptions, which allows an exception to know what exception caused it to be thrown. Essentially what it allows is this (from the page): try { lowLevelOp(); } catch LowLevelException(le) { throw new HighLevelException(le); // Chaining-aware constructor } Then the code catching the HighLevelException(he) can call he.getCause() to get the LowLevelException. That way, all sorts of low level network exceptions could be abstracted to NetworkException at a higher level with a chain down to the lower-level exception. Anyways, seek out that part and read it. Good stuff. I hope this addresses some of the concers that people have had with this clause in previous posts. Cheers, Eric
Aug 26 2001
Well, I don't want to say anything nice about java but I would like to re-second this. I would like to be able to look at a function and have a reasonable idea of the error I need to be ready to handle.I don't usually advocate Java either... I'm only half-pleased with their VM way of doing things, and am still not sure about the class library, it's complete, but as someonw mentioned, if you use one bit, you have to use all the bits. However, IMHO exception handling is one thing they got right.I wouldn't against having the default behavior (when there is no throws clause) be that it can throw anything, so only the masochists need declare what they are doing. I do believe that any library that wants to be taken seriously should, by convention, declare throws clauses for every method. This way folks who like to try to recover or clean up can have some idea what can go wrong. Otherwise I don't see how you could do anything more that say "I died because " + exception.msg();Six months ago I would have been okay with it too, but working on the most recent project I've been working on, I can't say I'm okay with it anymore. The project was built in C++ through a series of grafts, and eventually emerged as a complete system. One of the annoying problems we've been having is that occasionally someone forgets to document an exception in a header file. The exceptional case occurs, and it throws. That exception propagates half-way up the call stack, and is caught in a really wierd place. Our exceptions don't know where they came from in code (another problem), and so you spend a while trying to figure out what part of your code threw that exception, and it ends up being annoying. There are three ways to handle a mandatory throws clause: 1) Don't throw exceptions :) 2) Document every specific exception that could be thrown (the Good Way) or 3) 'throws (Exception)' (the 'I'm Lazy') way. So, there is a way to get around a mandatory throws clause if you don't want to document every exception. At least that way people who call your function know you might throw *something*, but it won't be very meaningful. But, the whole point of meaningful exceptions is so that you can recover gracefully from them. Otherwise, you're right, all you get is: "I died because " + exception.msg(); Ow. I don't want my app doing that. Eric P.S. Idea: Exceptions should know what file and line they were thrown from by default.**
Aug 26 2001
P.S. Idea: Exceptions should know what file and line they were thrown from by default.**Yes.
Nov 03 2001
Here's my problem with a throws clause: A calls B B calls C C calls D D is in some third party library. Now, D is updated to throw another exception. Now, the code in C, B, and A all needs to be updated. To me, this breaks code reuse. -Walter
Aug 26 2001
Walter wrote:Here's my problem with a throws clause: A calls B B calls C C calls D D is in some third party library. Now, D is updated to throw another exception. Now, the code in C, B, and A all needs to be updated. To me, this breaks code reuse. -WalterIf you think about it, either way it breaks code reuse. In fact, changing *any* part of a contract breaks code reuse! If D changes his pre- or post-conditions, C is going to run into problems, because the 'assert(i<=5)' just became 'assert(i<5)', and he's counting on passing 5s! That isn't any reason to not include them in the language (as the language D so aptly demonstrates). Back to exceptions: If D adds a new exception, C, B, and A are broken anyways, because they don't know it's coming! I think having the clause breaks code reuse *less*, not more. Consider a stack of fixed size which used to perform a no-op if you tried to push beyond the limits of the stack. Well, the author decided that it wasn't good behaviour for the stack, and so now the push() method throws an exception. The stack is D. The author of C downloads the new version of D to run his unit tests (yay for unit tests) to make sure his still works. Now, one of several things happen based on whether there is a mandatory throws clause or not. Mandatory throws clause: C's code doesn't compile. "Damn," he says, and adds the five or so lines of code to catch and chain the exception. If he's not sure how to handle it, he has to think about it. No throws clause: Turns out C's unit tests weren't quite thorough, and he missed the boundary case where the exception would be thrown (C isn't a simple system). I'm the author of A. If there is a mandatory throws clause, I probably don't even notice that a new exception is there. A good programmer at the C or B level will catch and *handle* the exception as it should be handled. So with a throws clause I'm less likely to be affected at all. If I am affected, it will be that my code doesn't compile. No problem. I add a few lines and go merrily on my way. That is certainly preferable to the alternative, which occurs without a throws clause. I find out four months after deployment of my new software that the stupid author of D added an exception to his code which bubbled up to my code. Now I have to issue a patch and change all my code... But wait! I can't even catch the specific exception, because it's not in my scope! In fact, even if I catch a generic Exception, I can't handle it properly, because I have no idea what the innards of B, C, or D are! Even worse, I don't even know that it is D that is causing me problems!!! There is no way to fix this problem, except to contact the author of B, who after hours of searching finds the obscure case and contacts the author of C, who does the same and eventually the author of D is contacted who tells us all: "Oh yeah, I added an exception." What pisses me off more? Having to add three lines to catch a new exception from B because my code won't compile? (Which likely wouldn't happen) OR the horrible scenario I described in the last paragraph? I'd say I'd rather recompile than face that crap. My code is less *critially* broken if the throws clause is there, and mandatory. Now I can understand your reluctance to add it to the language if there is a good *compiler* reason to leave it out. But I think from a language architecture standpoint it's a good idea. Cheers, Eric
Aug 26 2001
Eric Gerlach wrote:Walter wrote:Eric, thanks for your excellent example here. I'd been leaning against throws-contracting out of laziness, and your argument is persuasive. (Hey, what are the interactions between C++ exceptions and D exceptions? Does propagation always stop at the language barrier?) I'd personally like to write code for quick-n-dirty tools without being concerned with exceptions at all. Can we define some solution wherein the default behavior is to not care what exceptions might be thrown? -RBHere's my problem with a throws clause: A calls B B calls C C calls D D is in some third party library. Now, D is updated to throw another exception. Now, the code in C, B, and A all needs to be updated. To me, this breaks code reuse. -WalterIf you think about it, either way it breaks code reuse [...snippy...]
Aug 26 2001
Russell Bornschlegel wrote in message <3B89ECDD.1282D39D estarcion.com>...(Hey, what are the interactions between C++ exceptions and D exceptions? Does propagation always stop at the language barrier?)Since, in C++, you can throw any type, but in D, you can only throw class instances of a type that doesn't exist in C++, there's an obvious compatibility problem. One solution is to fake a wrapper around any incoming C++ exception, but I feel a better solution is to ignore the problem and assert that exceptions should not propagate across DLL or language boundaries.I'd personally like to write code for quick-n-dirty tools without being concerned with exceptions at all. Can we define some solution wherein the default behavior is to not care what exceptions might be thrown?That might be best.
Aug 27 2001
Perhaps if the compiler detects exceptions that aren't handled, it might issue a warning... if you're just doing something quick and dirty, you could feel free to ignore this warning. I'm all in favor of forcing code to be more robust and reliable. So I guess I'm in favor of explicit throws() clauses, unless the compiler can detect this for me. SeanI'd personally like to write code for quick-n-dirty tools without being concerned with exceptions at all. Can we define some solution wherein the default behavior is to not care what exceptions might be thrown?That might be best.
Nov 03 2001
Eric, thanks for your excellent example here. I'd been leaning against throws-contracting out of laziness, and your argument is persuasive.I try. :)I'd personally like to write code for quick-n-dirty tools without being concerned with exceptions at all.The thing is, the language uses exceptions as its method of communicating errors. So no matter what you do, you're going to have exceptions to think about. If there were a mandatory 'throws' clause you could just have every function 'throws (Exception)' and you're fine. That is a bit ugly though. :(Can we define some solution wherein the default behavior is to not care what exceptions might be thrown?I'm not sure exactly what you mean by this. If you're referring to Dan Hursh's idea:void f() throws(); // I throw nothing void g() throws(X, Y, Z) // I throw X, Y & Z type exceptions void h(); // I'm making no promisesThen that's what I'd call the minimum. What I glean from this is that if a function declaration has a 'throws' clause, then the compiler will check the body of that function to make sure that no other exceptions other than those declared could possibly be thrown. If there is no throws clause, there is no contract there. To be honest, that's not a bad solution when compared to the other contract mechanisms. Just as you are encouraged to use in, out, invariant and test blocks for your code, you'd be encouraged to use throws clauses too. One suggestion though: I think compiler warnings should be issued if there is the threat of exceptions being thrown in a function that doesn't have a throws clause. So the enforcement comes when you have warnings-as-errors and -Wall on, as many good applications do. Now, here's a challenge: design a language that *ennforces* the proper use of pre- and post- conditions, as well as class invariants. Damn that'd be neat. Eric
Aug 27 2001
Eric Gerlach wrote:Now, here's a challenge: design a language that *ennforces* the proper use of pre- and post- conditions, as well as class invariants. Damn that'd be neat. EricThat's scary. Do you mean it would make sure they are meaningful? If the compiler could do that, it wouldn't be to far away from writing your code for you. It reminds me of a feeble attempt a group at the university I went to tried. They wanted to design a language that would allow the programmer to define, in mathematics notion, what a piece of code was supposed to do using pre & post conditions, requires & returns clauses, assume & invariant statements and the like for each routine, function, module and loop. The compiler has to understand graph theory and turning theory. It amounted to the programmer writing the code once as an interface description and again as real code. The idea being that you could swap implementation as long as the compiler agreed that it still fit the mathematic interface description. They tried to graft this monstrosity onto C++ (it was the only way they would switch from teaching Modula-2) and taught it to a few years of students who thought they were being taught straight C++. I was pretty decent a C++ at the time, but I could not read the code at all. They made up dozens of new keywords that just didn't fit. The library was made so the students had to have 10-20 MB of quota to compile the most trivial of programs. The compiler required all of those contract declarations but I don't think they ever amounted to being anything more that required comments. The compiler logic was too complicated to actually use them for validity checking. I've heard rumors that they were going to try grafting this thing on scheme and java. I believe the C++ implementation was considered a loss. Getting back to you suggestion, it's not that the idea isn't neat and the intentions I'm sure are good, but it gives me flashbacks. A Prof.'s research should never be taught as a standard before it has been proven (or falls on it's face). Dan
Aug 27 2001
Eric Gerlach wrote:Then that's what I'd call the minimum. What I glean from this is that if a function declaration has a 'throws' clause, then the compiler will check the body of that function to make sure that no other exceptions other than those declared could possibly be thrown. If there is no throws clause, there is no contract there.So then the compiler has to construct some kind of lookup table as to what exceptions each function with a 'throws' clause in the entire system (including all the libraries that you use) can throw. In a large system I could imagine this taking a LOT of memory to keep track of. I'm all for it, but it's going to cost us. Chris
Aug 27 2001
So then the compiler has to construct some kind of lookup table as to what exceptions each function with a 'throws' clause in the entire system (including all the libraries that you use) can throw. In a large system I could imagine this taking a LOT of memory to keep track of.I'm not sure that's true. As I'm going over the parse tree, when in a function that has a throws clause I check to see if it has any function calls inside which have throws clauses themselves. If I find one, and it isn't caught or declared in that scope, I print out an error and die. If there's anything to keep track of, it's no bigger than parameter declarations anyways. The record of 'who throws what' shouldn't have to carry over to runtime, as it will have already been checked and verified. Of course, that is only the case if we can't speed up execution by having it. Eric
Aug 27 2001
Eric Gerlach wrote:Actually, when in a function with a throws clause, you have to check all the functions, even the once without a throws clause. You are making a promise even if the functions you call don't. Basically I would assume a function without a throws clause is implying he throws the exception base class. On a related note, how will this affect virtual method calls? Does this mean that if you override a method you can only have a throws clause containing the same types as your base class or your exceptions have to be subclasses of the exceptions you parent throws? I would assume so, but is this reasonable in practice? Do throws clauses get attached to interface signatures? Again, I think so and I do know if this is reasonable. It sounds like it would require though on the behave of interface and class designers so that they don't paint folks into a corner. BTW. I'm still in favor of having throws clauses and enforcing them. DanSo then the compiler has to construct some kind of lookup table as to what exceptions each function with a 'throws' clause in the entire system (including all the libraries that you use) can throw. In a large system I could imagine this taking a LOT of memory to keep track of.I'm not sure that's true. As I'm going over the parse tree, when in a function that has a throws clause I check to see if it has any function calls inside which have throws clauses themselves. If I find one, and it isn't caught or declared in that scope, I print out an error and die. If there's anything to keep track of, it's no bigger than parameter declarations anyways. The record of 'who throws what' shouldn't have to carry over to runtime, as it will have already been checked and verified. Of course, that is only the case if we can't speed up execution by having it. Eric
Aug 27 2001
Actually, when in a function with a throws clause, you have to check all the functions, even the once without a throws clause. You are making a promise even if the functions you call don't. Basically I would assume a function without a throws clause is implying he throws the exception base class.Well, if *all* the functions had mandatory throws clauses that wouldn't be a problem now would it? :)) I never did think of that though. OTOH, it couldn't be that big could it? I mean, all of the function's parameters have to be kept in a table somewhere... would exceptions take that much more room?On a related note, how will this affect virtual method calls? Does this mean that if you override a method you can only have a throws clause containing the same types as your base class or your exceptions have to be subclasses of the exceptions you parent throws? I would assume so, but is this reasonable in practice? Do throws clauses get attached to interface signatures? Again, I think so and I do know if this is reasonable. It sounds like it would require though on the behave of interface and class designers so that they don't paint folks into a corner.To be honest, I was thinking about this and I couldn't figure it out either. So I just went and checked what Java does: "A method that overrides or hides another method (§8.4.6), including methods that implement abstract methods defined in interfaces, may not be declared to throw more checked exceptions than the overridden or hidden method. More precisely, suppose that B is a class or interface, and A is a superclass or superinterface of B, and a method declaration n in B overrides or hides a method declaration m in A. If n has a throws clause that mentions any checked exception types, then m must have a throws clause, and for every checked exception type listed in the throws clause of n, that same exception class or one of its superclasses must occur in the throws clause of m; otherwise, a compile-time error occurs." So it would seem that your conception isn't ludicrous. I think that it makes sense, because you have to maintain the guarantee that users of the superclass expect. If the body of your function (in the subclass) could throw another exception, well, good coding practice would dictate you should be handling that internally, rather than breaking the contract set out by your parent. Eric
Aug 28 2001
Eric Gerlach wrote in message <3B8AE63F.4010400 canada.com>...One suggestion though: I think compiler warnings should be issued if there is the threat of exceptions being thrown in a function that doesn't have a throws clause. So the enforcement comes when you have warnings-as-errors and -Wall on, as many good applications do.One thing I haven't mentioned in the docs, but is a design goal, is to not have warnings. Code should compile or it should fail with a diagnostice message. I dislike getting a piece of code from somewhere, running the makefile, and getting a bunch of warnings. Was I compiling the code right? Are those warnings real bugs or not? Why did whoever wrote the code ignore the warnings? Etc. If you examine the warnings C compilers give, it is usually to make up for some weakness in the language. I've tried to address those weaknesses, and thereby getting rid of the warnings.Now, here's a challenge: design a language that *ennforces* the proper use of pre- and post- conditions, as well as class invariants. Damn that'd be neat.But I still want to be able to just bang out sloppy code for a one-shot purpose. Some programming jobs are worth doing but not worth doing well <g>.
Aug 28 2001
Eric Gerlach wrote in message <3B8AE63F.4010400 canada.com>...I thought that might be the case due to how you deal with what used to be local variable warnings. Well, if that's your reasoning for removing compiler warnings, I think the throws clause should be mandatory. Essentially, if you're making all warnings errors by default, you're trying to have the language clean up people's sloppy code. I think this is a Good Thing. However, not bothering to declare exceptions is sloppy code. People should be at least warned if their functions might throw an exception. Heck, I'd like to be. When I was doing programming competitions a few years back, we'd have a Pascal file that started with: var a, b, c, i, j, k, l, m, n, q, x, y, z : Integer; The reason was we didn't want to spend time thinking about variable definitions. It's sloppy, yes, but we just wanted to bang out some code quickly. In C, this would have caused warnings. In D, this would cause an error. D can't let people get away with being sloppy in some areas but not in others. If D is going to crack down on sloppy code from programmers, then it should be as ruthless with exceptions as it is about all other aritifacts of sloppy code. Now, the argument has been made: "Sometimes I want to bang out code quick without regard to exceptions." Well, how about without regard to local variables? Signed/unsigned comparisons? (which I assume will become an error as well... as it is typically a warning) All these things are marks of sloppy coding. If they're warnings, then you get the problems described above by Walter. If they're errors, you can't bang out quick code. Perhaps what the compiler needs is to make a category of errors known as 'non-fatal' errors. i.e. If you have one your code will still run, but it may not run well. Then, add a '-sloppy' or like switch to the compiler, which lets it behave leniantly with regard to these errors. Now you have the tight checking for production-level code, and you have the leniant mode to allow for quick, dirty work. Not to mention, you have to explicitly invoke the sloppy mode, so the majority of code will be clean. Personally, I think that solution works great. Gives flexibility of C when you need it, but is usually very strict like Java. The best of both worlds!One suggestion though: I think compiler warnings should be issued if there is the threat of exceptions being thrown in a function that doesn't have a throws clause. So the enforcement comes when you have warnings-as-errors and -Wall on, as many good applications do.One thing I haven't mentioned in the docs, but is a design goal, is to not have warnings. Code should compile or it should fail with a diagnostice message. I dislike getting a piece of code from somewhere, running the makefile, and getting a bunch of warnings. Was I compiling the code right? Are those warnings real bugs or not? Why did whoever wrote the code ignore the warnings? Etc. If you examine the warnings C compilers give, it is usually to make up for some weakness in the language. I've tried to address those weaknesses, and thereby getting rid of the warnings.Oh goodness! I didn't mean *do* it.... I just meant it would be a challenge. Any takers? :)Now, here's a challenge: design a language that *ennforces* the proper use of pre- and post- conditions, as well as class invariants. Damn that'd be neat.But I still want to be able to just bang out sloppy code for a one-shot purpose. Some programming jobs are worth doing but not worth doing well <g>.
Aug 28 2001
Eric Gerlach wrote in message <3B8C30BB.2060805 canada.com>...Now, the argument has been made: "Sometimes I want to bang out code quick without regard to exceptions." Well, how about without regard to local variables? Signed/unsigned comparisons? (which I assume will become an error as well... as it is typically a warning) All these things are marks of sloppy coding. If they're warnings, then you get the problems described above by Walter. If they're errors, you can't bang out quick code.Oh, so you want me to be consistent? <g> <harrumph>Perhaps what the compiler needs is to make a category of errors known as 'non-fatal' errors. i.e. If you have one your code will still run, but it may not run well. Then, add a '-sloppy' or like switch to the compiler, which lets it behave leniantly with regard to these errors.Every compiler switch is a bug.
Aug 28 2001
Eric Gerlach wrote in message <3B8C30BB.2060805 canada.com>...eep! OfcourseI'mnotpresumingtoimposeonyouinanymannerwhatsoeverIsimplybelievethattheconceptsa emutuallyexclusive. Pleasedon'tkillmeohgreatlanguagedesignersir. :)Now, the argument has been made: "Sometimes I want to bang out code quick without regard to exceptions." Well, how about without regard to local variables? Signed/unsigned comparisons? (which I assume will become an error as well... as it is typically a warning) All these things are marks of sloppy coding. If they're warnings, then you get the problems described above by Walter. If they're errors, you can't bang out quick code.Oh, so you want me to be consistent? <g> <harrumph>I think that's over-generalisation. For example, you've described several compiler switches. Are they bugs? There are some decisions that have to be made at the compiler level, and not at the code level. One such example is whether to generated debug symbols or not, another is code optimisation. You have to have compiler switches for those. I think that relaxing the errors that are only there for code-style enforcement should be another one. There are obviously two ways of writing code: the strict way, and the loose way. I think that D tends towards the strict way, so make it go all the way by default, and allow programmers to loosen it up if they want. Really, it doesn't matter how, I just thought a compiler switch was appropriate. EricPerhaps what the compiler needs is to make a category of errors known as 'non-fatal' errors. i.e. If you have one your code will still run, but it may not run well. Then, add a '-sloppy' or like switch to the compiler, which lets it behave leniantly with regard to these errors.Every compiler switch is a bug.
Aug 29 2001
Eric Gerlach wrote in message <3B8D8D13.4090609 canada.com>...Yes, of course. I was referring to the idea that compiling a program should be as simple as running the compiler. You shouldn't have to consult a thick manual to figure out the plethora of switches. Look at C/C++ programming. Ever see a makefile without a looong list of switches that change the language being compiled, add layers of explicit and implicit #define's, etc.?I think that's over-generalisation. For example, you've described several compiler switches. Are they bugs? There are some decisions that have to be made at the compiler level, and not at the code level. One such example is whether to generated debug symbols or not, another is code optimisation. You have to have compiler switches for those.Perhaps what the compiler needs is to make a category of errors known as 'non-fatal' errors. i.e. If you have one your code will still run, but it may not run well. Then, add a '-sloppy' or like switch to the compiler, which lets it behave leniantly with regard to these errors.Every compiler switch is a bug.I think that relaxing the errors that are only there for code-style enforcement should be another one. There are obviously two ways of writing code: the strict way, and the loose way. I think that D tends towards the strict way, so make it go all the way by default, and allow programmers to loosen it up if they want. Really, it doesn't matter how, I just thought a compiler switch was appropriate.One issue with this idea is having multiple incompatible builds of, say, a library.
Sep 01 2001
Walter wrote:Every compiler switch is a bug.Especially that '-o' one. If it ain't called a.out, I ain't runnin' it! :-)
Aug 29 2001
Dan Hursh wrote in message <3B8DAED3.630B4D97 infonet.isl.net>...Walter wrote:-o is a bug. After all, the compiler should be smart enough to figure out that if you compile foo.c, the resulting executable should be named foo (or foo.exe for win32).Every compiler switch is a bug.Especially that '-o' one. If it ain't called a.out, I ain't runnin' it! :-)
Sep 01 2001
"Walter" <walter digitalmars.com> wrote:-o is a bug. After all, the compiler should be smart enough to figure out that if you compile foo.c, the resulting executable should be named foo(orfoo.exe for win32).So make sure not to call any files win.c! :-) "Hello tech support? When I turn on my computer it only says 'Hello World!'" Angus
Sep 02 2001
<snip>Now, the argument has been made: "Sometimes I want to bang out code quick without regard to exceptions." Well, how about without regard to local variables? Signed/unsigned comparisons? (which I assume willType safety? Encapsulation? The list goes on...
Aug 29 2001
Walter wrote:Here's my problem with a throws clause: A calls B B calls C C calls D D is in some third party library. Now, D is updated to throw another exception. Now, the code in C, B, and A all needs to be updated. To me, this breaks code reuse. -WalterYou are right, but I consider it a side affect of the interface of D changing. I be upset if the number or types of parameter to D changed and the compiler didn't flag that. Throwing a new type of exception is like changing the type of a parameter. One of my big problems with errno is that platforms can make up their own values. They can change them add them remove and I would never know and hence I cannot even attempt to handle in any way except to ignore them or throw my hands up and abort. So you right, it a pain, but it's D's fault for changing the API. Error conditions should be a part of a good API. If A want's he can be lazy and just have a throws clause of Exception or what ever the exception base class is. You could also pick up the syntax: void f() throws(); // I throw nothing void g() throws(X, Y, Z) // I throw X, Y & Z type exceptions void h(); // I'm making no promises I think libraries should document their errors with throws clauses, but I wouldn't want the language to enforce that. Dan
Aug 26 2001
<snip>You are right, but I consider it a side affect of the interface of D changing. I be upset if the number or types of parameter to D changed and the compiler didn't flag that. Throwing a new type of exception is like changing the type of a parameter. One of my big problems with errno is that platforms can make up their own values. They can change them add them remove and I would never know and hence I cannot even attempt to handle in any way except to ignore them or throw my hands up and abort. So you right, it a pain, but it's D's fault for changing the API. Error conditions should be a part of a good API. If A want's he can be lazy and just have a throws clause of Exception or what ever theAmen.exception base class is. You could also pick up the syntax: void f() throws(); // I throw nothing void g() throws(X, Y, Z) // I throw X, Y & Z type exceptions void h(); // I'm making no promisesI'd much rather require that a method without an exception contract state it explicitly: void f() ; // I throw nothing void g() throws (X, Y, Z) ; // I throw X, Y & Z void h() throws anything ; // Warning! Warning! Lazy programmer ;-)I think libraries should document their errors with throws clauses, but I wouldn't want the language to enforce that.Can I ask a question of everybody on this thread? How many of you have actually spent anytime working with a language that has rigorous exception specification syntax (eg. Java)? I spent 18 months programming almost exclusively in Java and I honestly did not find having to declare exceptions a bother. As for API drift being a problem in this regard, it happens a hell of a lot less than you might imagine - and when it does happen, you can relax in the certain knowledge that you're compiler's going to tell you about each and every point at which changes in a 3rd party library has broken your code. Regards, John Carney.
Aug 28 2001
John Carney wrote:But this seems to defeat the lazy programer's purpose. He's LAZY. He doesn't want to have to declare that he's not declaring something. That one of the things I find amusingly correct about perl's requirement that programmer who want to be forced to declare variables, have to declare that they want to have to declare variables. The lazy programmer does nothing and gets the behavior that benefits lazy programmers. It's poetic in nature.exception base class is. You could also pick up the syntax: void f() throws(); // I throw nothing void g() throws(X, Y, Z) // I throw X, Y & Z type exceptions void h(); // I'm making no promisesI'd much rather require that a method without an exception contract state it explicitly: void f() ; // I throw nothing void g() throws (X, Y, Z) ; // I throw X, Y & Z void h() throws anything ; // Warning! Warning! Lazy programmer ;-)Java is a VM. There's a difference.I think libraries should document their errors with throws clauses, but I wouldn't want the language to enforce that.Can I ask a question of everybody on this thread? How many of you have actually spent anytime working with a language that has rigorous exception specification syntax (eg. Java)? I spent 18 months programming almost exclusively in Java and I honestly did not find having to declare exceptions a bother.As for API drift being a problem in this regard, it happens a hell of a lot less than you might imagine - and when it does happen, you can relax in the certain knowledge that you're compiler's going to tell you about each and every point at which changes in a 3rd party library has broken your code.API drift may not happen much, but platform differences are another matter. That's one reason why errno can be ugly. With some many standard to choose from, which ones do you pick and how closely do you stick to each one. Vendors like to deviate from specs in order to accentuate their advantages in cases where specs try to pick least common denominators. Different implementation allow for different error conditions. With Java you have one platform, the JVM, and it is only liable to change every six months or however often Sun decides to mess with the world. When compiling to something less standard, say native operation systems, you have room for a lot more differences. This would have a bad gut feeling to anyone who has had to deal with portability a lot. You now have API drift for several different platforms, and they don't even happen at the same time. Now, I still agree that throws clauses should be in. It will be easier for API designer's to declare IN BLOOD the classes of errors that the developer should have to worry about. Provided that the API developers exercise on ounce of forethought, it should be possible to provide a setup of exception classes that covers the least common denominators, with giving platform vendors the ability to provide platform specific subclasses for better error granularity for those you want to tie themselves to a single platform or like to use conditional compilation. Provided that you give in to letting lazy tools programmer not declare any throws clause and get the lazy behavior of passing on all exceptions, they should have nothing to complain about. It will only impact implementors of compilers and libraries. I guess anyone writing a code analyzer might care too. Dan
Aug 28 2001
"Dan Hursh" <hursh infonet.isl.net> wrote in message news:3B8C760E.72C63D32 infonet.isl.net...John Carney wrote:state itexception base class is. You could also pick up the syntax: void f() throws(); // I throw nothing void g() throws(X, Y, Z) // I throw X, Y & Z type exceptions void h(); // I'm making no promisesI'd much rather require that a method without an exception contract<sigh> The problem is that lazy programming becomes the de facto standard - you might as well not bother with a throws clause in the first place. Why go to all the trouble of declaring throws in your library if your clients are not going to get any benefit from it? This is the argument that Walter clearly favours because there is no throws clause in the language. I agree with him in this respect - if you're not going to have strict exception specification, then you might as well not have any.explicitly: void f() ; // I throw nothing void g() throws (X, Y, Z) ; // I throw X, Y & Z void h() throws anything ; // Warning! Warning! Lazy programmer ;-)But this seems to defeat the lazy programer's purpose. He's LAZY. He doesn't want to have to declare that he's not declaring something. That one of the things I find amusingly correct about perl's requirement that programmer who want to be forced to declare variables, have to declare that they want to have to declare variables. The lazy programmer does nothing and gets the behavior that benefits lazy programmers. It's poetic in nature.butI think libraries should document their errors with throws clauses,exceptionI wouldn't want the language to enforce that.Can I ask a question of everybody on this thread? How many of you have actually spent anytime working with a language that has rigorousexceptionsspecification syntax (eg. Java)? I spent 18 months programming almost exclusively in Java and I honestly did not find having to declareUmmmm. And why does that make a strict throws clause any easier for the programmer?a bother.Java is a VM. There's a difference.And underneath the VM there is a whole host of different platforms each with their own error conditions which don't stop ocurring just because you've pasted a VM over the top of it all - and they all have to get reported one way or another. The fact is that most error conditions *aren't* platform specific - they may be reported in different ways, but an out of memory error is an still an out of memory error whether you're running Windows, Solaris, Irix, Linux, FreeBSD, BeOS, PalmOS, VMS, TRS-DOS or AppleSoft. Regards, John Carney.As for API drift being a problem in this regard, it happens a hell of a lot less than you might imagine - and when it does happen, you can relax in the certain knowledge that you're compiler's going to tell you about each and every point at which changes in a 3rd party library has broken your code.API drift may not happen much, but platform differences are another matter. That's one reason why errno can be ugly. With some many standard to choose from, which ones do you pick and how closely do you stick to each one. Vendors like to deviate from specs in order to accentuate their advantages in cases where specs try to pick least common denominators. Different implementation allow for different error conditions. With Java you have one platform, the JVM, and it is only liable to change every six months or however often Sun decides to mess with the world. When compiling to something less standard, say native operation systems, you have room for a lot more differences. This would have a bad gut feeling to anyone who has had to deal with portability a lot. You now have API drift for several different platforms, and they don't even happen at the same time.
Aug 29 2001
John Carney wrote:The problem is that lazy programming becomes the de facto standard - you might as well not bother with a throws clause in the first place. Why go to all the trouble of declaring throws in your library if your clients are not going to get any benefit from it? This is the argument that Walter clearly favours because there is no throws clause in the language. I agree with him in this respect - if you're not going to have strict exception specification, then you might as well not have any.In that case, let me make Walter's case stronger for him. What good are strict exceptions clauses when everyone uses "throws(exception)"? You'll have that problem either way. At let's the quick tool's writer's will like you better if the lack of the clause gives them that behavior. For what it's worth, I would probably use them in most of my code because I'm anal. Where I work we tend to use them all the time in Java except for those things that are needed quick (as in yesterday) as a patch until we can get a real fix put together. In those cases everything throws "exception". I think it is a bit hasty to say no one would use the if given the choice. It sounds like you would. I would. I would berate any API designer who puts out a library for public without throws clauses (assuming we don't talk Walter out of them).Vendors can make too many changes to the sun API. You are less of a victim of change. (At least that what sun tells us.) The sun API defines who can throw what. Period. It's not unreasonable to think that native code would be more subservient to a given platform's idiosyncrasies, including how things can fail. Every time any one of the vendors, who's platform you support, decides to make a change your code could be made uncompilable. The world gets a lot ruder. It's a legitimate concern that should be addressed. I tried to address that later on in the response.Java is a VM. There's a difference.Ummmm. And why does that make a strict throws clause any easier for the programmer?But Java got away with it because they provided the pretty picture that you would be insulted from all that. Java tries to make every thing look the same, and that is an easier task to do in a VM than on bare hardware. D is targeting bare hardware.And underneath the VM there is a whole host of different platforms each with their own error conditions which don't stop ocurring just because you've pasted a VM over the top of it all - and they all have to get reported one way or another.As for API drift being a problem in this regard, it happens a hell of a lot less than you might imagine - and when it does happen, you can relax in the certain knowledge that you're compiler's going to tell you about each and every point at which changes in a 3rd party library has broken your code.API drift may not happen much, but platform differences are another matter. That's one reason why errno can be ugly. With some many standard to choose from, which ones do you pick and how closely do you stick to each one. Vendors like to deviate from specs in order to accentuate their advantages in cases where specs try to pick least common denominators. Different implementation allow for different error conditions. With Java you have one platform, the JVM, and it is only liable to change every six months or however often Sun decides to mess with the world. When compiling to something less standard, say native operation systems, you have room for a lot more differences. This would have a bad gut feeling to anyone who has had to deal with portability a lot. You now have API drift for several different platforms, and they don't even happen at the same time.The fact is that most error conditions *aren't* platform specific - they may be reported in different ways, but an out of memory error is an still an out of memory error whether you're running Windows, Solaris, Irix, Linux, FreeBSD, BeOS, PalmOS, VMS, TRS-DOS or AppleSoft.Right, and so is a "File Not Found", or a "No More Processes" messages (those happen often in Windows, right?) or "Disk Quota Exceeded"? You are right, things can go wrong all over the place even in Java. It's just easier to anticipate the pain it will cause when you run native. At least it is for me. I've still convinced myself that exceptions must be a part of the API definition of a function. I've even convinced myself that you are less exposed to increased granularity of error reporting, but it did seem the opposite at first. In any case, I don't want to argue of whether there should be exception specifications, because we both think there should be. I would argue that since a developer can say he throws the exception base class, you might as well let him have it the easy way. If you don't it's not like there won't be editors that can be configured to do it for him. By allowing an open default, you will be helping the people need to do quick and dirty hacks every so often. Dan
Aug 29 2001
toBut this seems to defeat the lazy programer's purpose. He's LAZY. He doesn't want to have to declare that he's not declaring something. That one of the things I find amusingly correct about perl's requirement that programmer who want to be forced to declare variables, have to declare that they want to have to declare variables. The lazy programmer does nothing and gets the behavior that benefits lazy programmers. It's poetic in nature.<sigh> The problem is that lazy programming becomes the de facto standard - you might as well not bother with a throws clause in the first place. Why goall the trouble of declaring throws in your library if your clients arenotgoing to get any benefit from it? This is the argument that Walter clearly favours because there is no throws clause in the language. I agree withhimin this respect - if you're not going to have strict exception specification, then you might as well not have any....I agree. And if you're not going to have strict exception specification then you may as well not bother with design-by-contract either. Pre and post conditions exist to ensure that code is as safe and consistent as can be managed at compile time. There's no point painstakingly defining the contract for a method if an unforseen exception sidesteps it all. Peter.
Aug 30 2001
kaffiene wrote:I think you are mistaking what I am saying. Exceptions are still enforced in my microcosm. The programmer simply does not need to give a throws clause. In that case, 'throws(exception)' or what ever the exception base class is can be assumed. Face it. If the programmer is lazy or in a rush, he will probably do this anyhow. You can't prevent it without actually making the compiler analyze the enter program to make sure the programmer's throws clauses are neither missing something nor are they too general. In that case you wouldn't need a throws clause because the compiler would figure it out itself. I don't believe that is practical. Maybe my original example should have been: larry() throws(); // I will throw nothing moe() throws(X, Y, Z); // I might throw X, Y & Z shemp(); // assume I could throw execption (aka anything) curly() throws(exception);// I can throw the same things as shemp Whether or not you make shemp illegal, you still has to deal with curly. nyuk nyuk nyuk DantoBut this seems to defeat the lazy programer's purpose. He's LAZY. He doesn't want to have to declare that he's not declaring something. That one of the things I find amusingly correct about perl's requirement that programmer who want to be forced to declare variables, have to declare that they want to have to declare variables. The lazy programmer does nothing and gets the behavior that benefits lazy programmers. It's poetic in nature.<sigh> The problem is that lazy programming becomes the de facto standard - you might as well not bother with a throws clause in the first place. Why goall the trouble of declaring throws in your library if your clients arenotgoing to get any benefit from it? This is the argument that Walter clearly favours because there is no throws clause in the language. I agree withhimin this respect - if you're not going to have strict exception specification, then you might as well not have any....I agree. And if you're not going to have strict exception specification then you may as well not bother with design-by-contract either. Pre and post conditions exist to ensure that code is as safe and consistent as can be managed at compile time. There's no point painstakingly defining the contract for a method if an unforseen exception sidesteps it all. Peter.
Aug 30 2001
"Dan Hursh" <hursh infonet.isl.net> wrote in message news:3B8F175C.F0F03CFF infonet.isl.net...kaffiene wrote:HeBut this seems to defeat the lazy programer's purpose. He's LAZY.Thatdoesn't want to have to declare that he's not declaring something.thatone of the things I find amusingly correct about perl's requirementdeclareprogrammer who want to be forced to declare variables, have todoesthat they want to have to declare variables. The lazy programmeryounothing and gets the behavior that benefits lazy programmers. It's poetic in nature.<sigh> The problem is that lazy programming becomes the de facto standard -gomight as well not bother with a throws clause in the first place. Whyaretoall the trouble of declaring throws in your library if your clientsclearlynotgoing to get any benefit from it? This is the argument that Walterwithfavours because there is no throws clause in the language. I agreespecificationhimin this respect - if you're not going to have strict exception specification, then you might as well not have any....I agree. And if you're not going to have strict exceptioncanthen you may as well not bother with design-by-contract either. Pre and post conditions exist to ensure that code is as safe and consistent asBy disallowing strict exception specification you penalise carefull programmers to appease lazy programmers. That's simply a bad trade. Peter.be managed at compile time. There's no point painstakingly defining the contract for a method if an unforseen exception sidesteps it all. Peter.I think you are mistaking what I am saying. Exceptions are still enforced in my microcosm. The programmer simply does not need to give a throws clause. In that case, 'throws(exception)' or what ever the exception base class is can be assumed. Face it. If the programmer is lazy or in a rush, he will probably do this anyhow. You can't prevent it without actually making the compiler analyze the enter program to make sure the programmer's throws clauses are neither missing something nor are they too general. In that case you wouldn't need a throws clause because the compiler would figure it out itself. I don't believe that is practical.
Aug 30 2001
kaffiene wrote:Given the example I had: larry() throws(); // I will throw nothing moe() throws(X, Y, Z); // I might throw X, Y & Z shemp(); // assume I could throw exception (aka anything) curly() throws(exception);// I can throw the same things as shemp Tell me this. If we get rid of the shemp syntax, how would you deal with curly? Exceptions aside, any error reporting mechanism can be abused. Errno was grossly abused as were the various return code standards. That is a practical fact of life. Sometimes it's not even abuse. Sometimes you are writing a quick one shot tool that you need now. If there is an error you let the program bomb, you fix it on the spot and you continue. Where I work, it is called fire fighting. It is sub optimal, but we don't always have time to wait on a carefully analyzed master piece. The way I see it, you can't stop the curly example. It is a valid, strict specification. It is probably an over specification, but that is not something the compiler can reasonably detect I would assume. Anything that would detect that, I suspect, would make other over specifications illegal when they may be valid for future planning. If you can't argue on HOW to prevent the curly form of abuse, then I don't see the problem with making it explicit with the shemp syntax. Since shemp would be a synonym for curly, it is no less strict that curly. Honestly, I think it makes the lack of a careful promise more obvious. I certainly don't agree with the argument that "It's bad style so we should penalize it with the syntax". If that is our plan then let's replace goto with some that takes a few lines and lots of redundancy. Goto has been the root of far more evil than under specifying error conditions. DanI think you are mistaking what I am saying. Exceptions are still enforced in my microcosm. The programmer simply does not need to give a throws clause. In that case, 'throws(exception)' or what ever the exception base class is can be assumed. Face it. If the programmer is lazy or in a rush, he will probably do this anyhow. You can't prevent it without actually making the compiler analyze the enter program to make sure the programmer's throws clauses are neither missing something nor are they too general. In that case you wouldn't need a throws clause because the compiler would figure it out itself. I don't believe that is practical.By disallowing strict exception specification you penalise carefull programmers to appease lazy programmers. That's simply a bad trade.
Aug 30 2001
"Dan Hursh" <hursh infonet.isl.net> wrote in message news:3B8F2EC1.32A08053 infonet.isl.net...kaffiene wrote:aI think you are mistaking what I am saying. Exceptions are still enforced in my microcosm. The programmer simply does not need to giveisthrows clause. In that case, 'throws(exception)' or what ever the exception base class is can be assumed. Face it. If the programmersomethinglazy or in a rush, he will probably do this anyhow. You can't prevent it without actually making the compiler analyze the enter program to make sure the programmer's throws clauses are neither missingbelievenor are they too general. In that case you wouldn't need a throws clause because the compiler would figure it out itself. I don'tYour argument appears to be that because some people can partly side-step a language feature it shouldn't be there at all. I don't agree. I certainly don't agree that a language feature designed to produce correct code should be rejected to favour quick hacks. I think that a lot of the point of coding in a higher level language than C is that you are aiming to produce cleaner, more reliable code than you could in C. Besides, I don't see the difference between having to declare unhandled exceptions and not being able to have unused variables. If you have an unused variable, the D compiler will complain and you will duck into the code, delete the variable or comment it out (or fix the bug if it was one) then recompile. That doesn't seem too difficult a task even for someone in a hurry. If you have strict exception specfication the compiler might complain that your new method isn't handling an exception and should either catch it or declare it with a throws clause. You duck into the code and handle it or pass it on - no big deal. I also think this 'shem vs curly' issue you raise is something of a straw-man argument. If someone wants to go out of their way to abuse exception specification because they're hacking, then fine - that's their perogative. They are free to do that with expection specification. However, people who want to code clean, reliable, reusable code need to know that their modules are as good as they can get. If you allow: method() // I can throw anything to mean an method which can throw any exception, then you remove an incredibly useful tool from the careful programmer's tool chest, because the compiler can now no longer tell whether the code you are writing is wrong because you haven't handled an exception or whether you really meant it to be like that and you wanted all the exceptions to percolate through your code right out to main and bomb the program. You have two options: strict exception specification and no exception specification at all (a halfway measure helps noone as pointed out above). If you go for no exception specifications, then hackers are happy and people who want correct code get no help at all (may as well not bother with design-by-contract either if that's your point of view). If you go for strict exception specification, hackers can still hack - using throws(exception) to their heart's desire, but people aiming to write and mantain correct code are not penalised, and can get a great deal of support by the compiler to do so. I have had experience with maintaining large code bases in C++ and Java (plus having to do quick hacks - for support reasons - in both languages). I know from experience that strict exception specification is a major win. (I don't mean to presume to know anything about your programming experience, BTW) I cannot stress strongly enough how much I think ignoring strict exception specification is a *bad idea*. C++ takes the weak exception specfication route because of legacy reasons, and Barney Soupstrain rates it as one of the biggest regrets he has about C++. He's right! ;-) Peter.Given the example I had: larry() throws(); // I will throw nothing moe() throws(X, Y, Z); // I might throw X, Y & Z shemp(); // assume I could throw exception (aka anything) curly() throws(exception);// I can throw the same things as shemp Tell me this. If we get rid of the shemp syntax, how would you deal with curly? Exceptions aside, any error reporting mechanism can be abused. Errno was grossly abused as were the various return code standards. That is a practical fact of life. Sometimes it's not even abuse. Sometimes you are writing a quick one shot tool that you need now. If there is an error you let the program bomb, you fix it on the spot and you continue. Where I work, it is called fire fighting. It is sub optimal, but we don't always have time to wait on a carefully analyzed master piece. The way I see it, you can't stop the curly example. It is a valid, strict specification. It is probably an over specification, but that is not something the compiler can reasonably detect I would assume. Anything that would detect that, I suspect, would make other over specifications illegal when they may be valid for future planning. If you can't argue on HOW to prevent the curly form of abuse, then I don't see the problem with making it explicit with the shemp syntax. Since shemp would be a synonym for curly, it is no less strict that curly. Honestly, I think it makes the lack of a careful promise more obvious. I certainly don't agree with the argument that "It's bad style so we should penalize it with the syntax". If that is our plan then let's replace goto with some that takes a few lines and lots of redundancy. Goto has been the root of far more evil than under specifying error conditions.that is practical.By disallowing strict exception specification you penalise carefull programmers to appease lazy programmers. That's simply a bad trade.
Aug 31 2001
Dan Hursh wrote:I think you are mistaking what I am saying. Exceptions are still enforced in my microcosm. The programmer simply does not need to give a throws clause. In that case, 'throws(exception)' or what ever the exception base class is can be assumed. Face it. If the programmer is lazy or in a rush, he will probably do this anyhow. You can't prevent it without actually making the compiler analyze the enter program to make sure the programmer's throws clauses are neither missing something nor are they too general.The compiler can analyze each function individually. If you throw an exception in a function (or call a function that throws an exception that you don't catch) but you don't declare it, it's a syntax error. Then, when you call any function, you can guarantee that that function will be bound to only throwing the exception it declares. Am I missing something?In that case you wouldn't need a throws clause because the compiler would figure it out itself. I don't believe that is practical. Maybe my original example should have been: larry() throws(); // I will throw nothing moe() throws(X, Y, Z); // I might throw X, Y & Z shemp(); // assume I could throw execption (aka anything) curly() throws(exception);// I can throw the same things as shempIf D implements strict exception specification, then the shemp() declaration should mean an explicit declaration that it throws *nothing*.
Aug 31 2001
Can I ask a question of everybody on this thread? How many of you have actually spent anytime working with a language that has rigorous exception specification syntax (eg. Java)? I spent 18 months programming almost exclusively in Java and I honestly did not find having to declareexceptionsa bother. As for API drift being a problem in this regard, it happens ahellof a lot less than you might imagine - and when it does happen, you can relax in the certain knowledge that you're compiler's going to tell you about each and every point at which changes in a 3rd party library has broken your code.I've been programming Java/C++/C interchangibly over the past three years. I've never found exception specification to be a bother in Java, rather I've found it to be a great help. I've never shipped code wondering whether some unforeseen exception might scuttle it, and quite often I've seen the compiler complain about some unhandled exception and been pleased that it did. Peter.
Aug 30 2001
Walter wrote:Here's my problem with a throws clause: A calls B B calls C C calls D D is in some third party library. Now, D is updated to throw another exception. Now, the code in C, B, and A all needs to be updated.But C, B and A *should* be updated. If D now throws another type of exception, there is now something new that can go wrong with D. C, B and A need to take account of this - otherwise, what happens when D does throw this new exception? IMHO the exceptions thrown by a function are part of it's interface. Other interface changes in D would result in changes in code which calls D. Why not the same with exceptions? -- Jim Farrand, ML Group, mailto:farrand cs.bris.ac.uk Department of Computer Science, http://www.cs.bris.ac.uk/~farrand University of Bristol, tel: +44-(0)117-954-5254 Woodland Road, Bristol, BS8 1UB, UK
Aug 29 2001