February 05, 2005 Re: [Sorta OT] License Restrictions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dave | In article <cu3iia$2r7v$1@digitaldaemon.com>, Dave says... >I'm with what you and Charlie posted earlier, some kind of -contracts=[on,off] flag or some such that could be used to override what -debug and -release both enforce now. > >I'm currently thinking that the defaults should perhaps act the same as-is ('-debug' implies '-contracts=on'; '-release' implies '-contracts=off') because that is what current D users have come to expect and also because PwC is generally considered to be "debug" related (in other words, I think those defaults would be more intuitive for the majority of people familiar with PwC, but of course I could be wrong). > >- Dave Aye - add my voice to that call. |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | I don't think I made myself very clear. I would like to see a compiler that would insert run-time code that would crash an application in those instances where it detected a probable mistake made by the coder, *and* inform the coder about what the compiler has done about it. The coder can then take one of three choices for each of these instances, (1) Do nothing. The coder lives with the compiler informing them and accepts the compiler inserted code. (2) The coder modifies their code so that the situation detected by the compiler no longer exists. If the coder adds irresponsible code then they have just continued their stupid (or uneducated) behaviour, as this is just as poor as leaving it unattended. The issue here is, who's responsibility is it to code well? The coder or the compiler? I maintain it is the coder and one role that the compiler brings to is similar to that of a mentor or coach, rather than a moral enforcement officer. (3) The coder adds into their code, a statement that informs the compiler that the coder acknowledges the situation and that the compiler no longer needs to inform the coder of it. The compiler still inserts the run-time code but no longer informs the coder. With the current DMD behaviour, if the coder is the type or person who continually writes irresponsible code, then it is more likely that the first person to find this out would be the user of the application rather than the coder. I believe it is politer for the compiler to mention the poor code to the coder before the end user is disturbed by it. If the coder does not mend their ways, then they probably deserve their consumer backlash. However, if the compiler's inserted code is what the user sees, then the whole programming community is tarnished, not just the original coder. On Sat, 5 Feb 2005 02:19:15 -0800, Walter wrote: > "Derek" <derek@psych.ward> wrote in message news:1uqf5a6fc42ei$.8hb72yklj5d2.dlg@40tude.net... >> You seem to be concerned that a code will always insert 'dead code' just > so >> the compiler will stop nagging them. > > Always? No. But it happens much more often than one would think. It usually happens when one is in a hurry, or thinking about something else at the time. One promises oneself that one will go back and fix it later. But that never happens. I work in the software production industry. It pays my wages. I also have a load of hands-on experience from many projects - large and small. The behaviour you just describe is not universal. In our development regime, peer inspection, bloody-minded testers, and management supported quality control processes virtually ensure that irresponsible coding practices are detected, corrected, and perpetrators retrained. >> I'm 50 years old and I've been coding for 28 years. You will often find in my code such things as ... >> >> Abort("Logic Error #nnn. If you see this, a mistake was made by the >> programmer. This should never be seen. Inform your supplier about this >> message."); >> >> You might regard this is superfluous 'dead code', > > No, I do not. I think such practice as yours is fine. My concern is with the temptation to just insert a return statement without any abort call. I've seen it happen, a lot, by professional programmers. This is where the good intentions of the compiler error message have gone awry and caused things to be worse. Define 'professional'? My definition includes the concept of responsibility. >> however a 'nice' message >> from the coder to the user is better than a compiler generated 'jargon' >> message that the user must decode. > > This is good, and is also achievable by putting a catch in at the top level to catch any wayward uncaught exceptions and print out any message desired. Yes, and that is just one of many mechanisms to achieve this effect. >> Thus my switch constructs always have a >> default clause, > > That's my normal practice with C/C++ code, years ago I had a paper > advocating such called "Defensive Programming". Many of those ideas have > been automated in D, as D will insert a default clause for you if none is > specified, and that inserted default clause will throw an exception. It > takes the place of all the > default: assert(0); break; > I write in C/C++. I think we are much more in agreement on these issues than > not. Having D insert this code is not a problem. But having DMD be silent about it is. I would regard is as good manners to inform the coder about what you have done to their code. >> and any 'if' statement in which an unhandled false would >> cause problems, I have an 'else' phrase. I always have a return statement >> at the end of my function text, even if its will never be executed (if all >> goes well). Call it overkill if you like, but in the long run, it keeps > the >> users better informed and *more* importantly, keeps future maintainers aware of the previous coder's intentions and reasons for doing things. > > No, I don't regard it as overkill. But I would regard an inserted return statement (that is not preceded by one of the abort messages you showed above) that is not intended to ever be executed as masking a potential bug. > > I also believe that dead code, unless it is marked with an Abort() like your example, is a problem for future maintainers. He'll see that return, and wonder what it's for and why it doesn't seem to be possible to execute it. (As an aside, it's interesting how much dead code tends to accumulate in an app. You can find such by running a coverage analyzer. Dead code accumulates like all the useless DNA we carry around <g>. I've been thinking of writing such a tool for D, it would be a good complement to the profiler.) Sounds okay. Off you go then... ;-) >> Currently, D is way too dogmatic and unreasonably unhelpful to the coder. > > But I think that a compiler requiring dead code to be inserted is being dogmatic! <g> Guess it's all in one's perspective. See my choices above. The compiler is not required to force the coder to add dead code. The coder should be able to tell the compiler that "Hey! I know what I'm doing, ok!?" >> It is mostly still better than C/C++ though. > > I surely hope so! But it is still not as good as you can make it, Walter. You can make it even better still. The journey is not over with v1.0. -- Derek Melbourne, Australia |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Unknown W. Brackets | "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:cu25p2$1jbc$1@digitaldaemon.com... > Walter says: if it's compile time, programmers will patch it without thinking. That's bad. So let's use runtime. That's essentially right. I'll add one more example to the ones you presented: int foo(Collection c, int y) { foreach (Value v; c) { if (v.x == y) return v.z; } } By the nature of the program I'm writing, "y" is guaranteed to be within c. Therefore, there is only one return from the function, and that is the one shown. But the compiler cannot verify this. You recommend that the compiler complain about it. I, the programmer, knows this can never happen, and I'm in a hurry with my mind on other things and I want to get it to compile and move on, so I write: int foo(CollectionClass c, int y) { foreach (Value v; c) { if (v.x == y) return v.z; } return 0; } I'm not saying you would advocate "fixing" the code this way. I don't either. Nobody would. I am saying that this is often how real programmers will fix it. I know this because I see it done, time and again, in response to compilers that emit such error messages. This kind of code is a disaster waiting to happen. No compiler will detect it. It's hard to pick up on a code review. Testing isn't going to pick it up. It's an insidious, nasty kind of bug. It's root cause is not bad programmers, but a compiler error message that encourages writing bad code. Instead, having the compiler insert essentially an assert(0); where the missing return is means that if it isn't a bug, nothing happens, and everyone is happy. If it is a bug, the assert gets tripped, and the programmer *knows* it's a real bug that needs a real fix, and he won't be tempted to insert a return of an arbitrary value "because it'll never be executed anyway". This is the point I have consistently failed to make clear. |
February 06, 2005 Re: [Sorta OT] License Restrictions | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dave | "Dave" <Dave_member@pathlink.com> wrote in message news:cu3iia$2r7v$1@digitaldaemon.com... > > "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:cu3a23$2iuq$1@digitaldaemon.com... >> >> "Dave" <Dave_member@pathlink.com> wrote in message news:cu2uq3$288a$1@digitaldaemon.com... >>> >>> "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:cu1q0r$1609$1@digitaldaemon.com... >>>> >>>> "Vathix" <vathix@dprogramming.com> wrote in message news:opslo861ihkcck4r@esi... >>>>>>> Guys, if we persist with the mechanism of no compile-time >>>>>>> detection of >>>>>>> return paths >>>>>> >>>>>> "and switch cases" >>>>>> >>>>>>> , and rely on the runtime exceptions, do we really think NASA >>>>>>> would use >>>>>>> D? Come on! >>>>>> >>>>> >>>>> Would you fly to mars in debug mode? >>>> >>>> Well, to seriously answer your question: I think production code, at least for 'important commercial', should be shipped with contract programming enforcement on. >>>> >>> >>> How about some middle ground? >>> >>> class Foo >>> { >>> ... >>> invariant(X) // runs with debug=X >>> { >>> ... >>> } >>> int foo(int i) >>> in(Y) {} // runs with debug=Y >>> out(Y) {} >>> body(Z) {} // "error: missing body { ... } after in or out" if >>> debug=Y but not debug=Z >>> } >>> >>> Then you could do this: >>> >>> dmd -O -inline -release -debug=X -debug=Y foo.d (-release and -debug are mutually exclusive, but not -release and -debug=ident) >> >> If you mean that we should be able to individually select on/off the components of CP, i.e. preconditions, postconditions and invariants. >> >> At first blush, I'd say yes. But I think this should take some thinking about, as there may be good reasons against that don't immediately spring to mind. >> >> I'd say probably not. In this last large project, I did consider having a more granular approach, but the components run with ample speed > > I think you're right. What I mentioned above would tie PwC too closely to debug(...) and also potentially complicate large projects greatly, by allowing too much granularity. > > I'm with what you and Charlie posted earlier, some kind of -contracts=[on,off] flag or some such that could be used to override what -debug and -release both enforce now. > > I'm currently thinking that the defaults should perhaps act the same as-is ('-debug' implies '-contracts=on'; '-release' implies '-contracts=off') because that is what current D users have come to expect and also because PwC is generally considered to be "debug" related (in other words, I think those defaults would be more intuitive for the majority of people familiar with PwC, but of course I could be wrong). I would agree, for reasons of legacy breaking, were it not that D is pre-1.0. Since I'm coming to believe more and more that PwC should _not_ be considered a debug only thing, I think it should be the default. Naturally, I'm looking at this from the perspective of large commercial systems. For simple utilities, I'd be adding -contracts=off to my makefiles, and be content with that decision. Walter, may we have it on by default? (and divorce from debug?) Please. I'll be polite. Honest, ...., mate! :-) |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek | What you're advocating sounds very much like how compile time warnings work in typical C/C++ compilers. Is this what you mean? "Derek" <derek@psych.ward> wrote in message news:w9f4rolhiyrh.t9depibclhn6$.dlg@40tude.net... > I don't think I made myself very clear. > > I would like to see a compiler that would insert run-time code that would crash an application in those instances where it detected a probable mistake made by the coder, *and* inform the coder about what the compiler has done about it. The coder can then take one of three choices for each of > these instances, > > (1) Do nothing. The coder lives with the compiler informing them and accepts the compiler inserted code. > > (2) The coder modifies their code so that the situation detected by the compiler no longer exists. If the coder adds irresponsible code then they have just continued their stupid (or uneducated) behaviour, as this is just > as poor as leaving it unattended. The issue here is, who's responsibility is it to code well? The coder or the compiler? I maintain it is the coder and one role that the compiler brings to is similar to that of a mentor or coach, rather than a moral enforcement officer. > > (3) The coder adds into their code, a statement that informs the compiler that the coder acknowledges the situation and that the compiler no longer needs to inform the coder of it. The compiler still inserts the run-time code but no longer informs the coder. > > > With the current DMD behaviour, if the coder is the type or person who continually writes irresponsible code, then it is more likely that the first person to find this out would be the user of the application rather than the coder. I believe it is politer for the compiler to mention the poor code to the coder before the end user is disturbed by it. If the coder > does not mend their ways, then they probably deserve their consumer backlash. However, if the compiler's inserted code is what the user sees, then the whole programming community is tarnished, not just the original coder. |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <newshound@digitalmars.com> wrote in message news:cu3rt4$ra$1@digitaldaemon.com... > > "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:cu25p2$1jbc$1@digitaldaemon.com... >> Walter says: if it's compile time, programmers will patch it without thinking. That's bad. So let's use runtime. > > That's essentially right. > > I'll add one more example to the ones you presented: > > int foo(Collection c, int y) > { > foreach (Value v; c) > { > if (v.x == y) > return v.z; > } > } > > By the nature of the program I'm writing, "y" is guaranteed to be > within c. > Therefore, there is only one return from the function, and that is the > one > shown. But the compiler cannot verify this. You recommend that the > compiler > complain about it. I, the programmer, knows this can never happen, and > I'm > in a hurry with my mind on other things and I want to get it to > compile and > move on, so I write: > > int foo(CollectionClass c, int y) > { > foreach (Value v; c) > { > if (v.x == y) > return v.z; > } > return 0; > } This is total rubbish. A maintenance engineer is stymied by *both* forms, and confused contrarily: the first looks like a bug but may not be, the second is a bug but doesn't look like it. The only form that stands up to maintenance is something along the lines of what Derek's talking about: int foo(CollectionClass c, int y) { foreach (Value v; c) { if (v.x == y) return v.z; } throw logic_error("This function has encountered a situation which contradicts its design and/or the design of the software within which it resides"); return 0; } This is what I also do in such cases, and I believe (and have witnessed) it being a widely practiced technique. Walter, you're just digging yourself in deeper. It's embarassing. It strongly gives the impression that you only work with yourself. You're keen to mould D with a view to catering for, or at least mitigating the actions of, the lowest common denominators of the programming gene pool. Yet you seem decidely uninterested in addressing the concerns of large scale and/or commercial and/or large-teams and/or long-lasting codebases. How can this attitude help D to prosper? One of the reviewers of Imperfect C++ made the sage comment that I was spending too much time "protecting from Machiavelli". He said that that was a quest without end, and he's spot on. Your measure adds an indeterminately timed exception fire, in the case that a programmer doesn't add a return 0. That's great, so far as it goes. But here's the fly in your soup: what's to stop them adding the return 0? The code's still wrong, but now it doesn't even have your backup plan active. Here's a thought. When people cotton on to this implicit behaviour in D, maybe there'll be a large-scale propagation of "Make sure you get all your returns in!" warnings. Do you have empirical evidence that there won't be a concommitant swell of crappy / neophyte programmers who will add a return X; at the end of every function by rote, to avoid the dreaded swipe of the indeterminate exception? Maybe you're going to actually exacerbate the problem you think you're countering! > Instead, having the compiler insert essentially an assert(0); where > the > missing return is means that if it isn't a bug, nothing happens, and > everyone is happy. If it is a bug, the assert gets tripped, and the > programmer *knows* it's a real bug that needs a real fix, and he won't > be > tempted to insert a return of an arbitrary value "because it'll never > be > executed anyway". > > This is the point I have consistently failed to make clear. Man, this is *so* frustrating. You obviously (now admittedly!) think that we're all just not getting your point. I get it. WE GET IT! I/we just think you're wrong. There's a problem with two opposing automatic ways of doing things. So the answer is to not have things automatic. I feel like Cassandra. Gah! I give up. |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Derek | >I don't think I made myself very clear. > > I would like to see a compiler that would insert run-time code that > would > crash an application in those instances where it detected a probable > mistake made by the coder, *and* inform the coder about what the > compiler > has done about it. The coder can then take one of three choices for > each of > these instances, > > (1) Do nothing. The coder lives with the compiler informing them and accepts the compiler inserted code. > > (2) The coder modifies their code so that the situation detected by > the > compiler no longer exists. If the coder adds irresponsible code then > they > have just continued their stupid (or uneducated) behaviour, as this is > just > as poor as leaving it unattended. The issue here is, who's > responsibility > is it to code well? The coder or the compiler? I maintain it is the > coder > and one role that the compiler brings to is similar to that of a > mentor or > coach, rather than a moral enforcement officer. > > (3) The coder adds into their code, a statement that informs the > compiler > that the coder acknowledges the situation and that the compiler no > longer > needs to inform the coder of it. The compiler still inserts the > run-time > code but no longer informs the coder. This is eminently sensible. I give it 0.01% chance of getting traction. Sarcasm aside, it's a warning by any other name, and we're not allowed warnings in D. :-( > With the current DMD behaviour, if the coder is the type or person who > continually writes irresponsible code, then it is more likely that the > first person to find this out would be the user of the application > rather > than the coder. I believe it is politer for the compiler to mention > the > poor code to the coder before the end user is disturbed by it. Brilliantly put. I'm going to email myself a copy of this and quote you next chance I get. <g> > If the coder > does not mend their ways, then they probably deserve their consumer > backlash. However, if the compiler's inserted code is what the user > sees, > then the whole programming community is tarnished, not just the > original > coder. In Chapter 1 of IC++, I expressed it more verbosely, as: " 1.1 Eggs And Ham I'm no doubt teaching all you gentle readers about egg-sucking here, but it's an important thing to state nevertheless. Permit me to wax awhile: · It's better to catch a bug at design time than at coding/compile time[1]. · It's better to catch a bug at coding/compile time than during unit testing[2]. · It's better to catch a bug during unit testing than during debug system testing. · It's better to catch a bug during debug system than in pre-release/beta system testing. · It's better to catch a bug during pre-release/beta system testing than have your customer catch one. · It's better to have your customer catch a bug (in a reasonably sophisticated/graceful manner), than to have no customers. This is all pretty obvious stuff, although customers would probably disagree with the last one; best keep that one to ourselves. There are two ways in which such enforcements can take effect: at compile-time and at run-time, and these form the substance of this chapter. [1] I'm not a waterfaller, so coding time and compiling time are the same time for me. But even though I like unit-tests and have had some blisteringly fast pair-programming partnerships, I don't think I'm an XP-er [Beck2000] either. [2] This assumes you do unit testing. If you don't, then you need to start doing so, sharpish! " Walter was one of the reviewers of IC++, and never expressed reservations on this section. Was I wrong? Matthew P.S. Sorry for having the bad manners to be quoting myself. But worry not, most of the gnomes I profer originate from others, so oftentimes I'm actually quoting someone worth listening to. <CG> |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | "Walter" <newshound@digitalmars.com> wrote in message news:cu3rt4$ra$1@digitaldaemon.com... > > "Unknown W. Brackets" <unknown@simplemachines.org> wrote in message news:cu25p2$1jbc$1@digitaldaemon.com... >> Walter says: if it's compile time, programmers will patch it without thinking. That's bad. So let's use runtime. > > That's essentially right. [snip] I don't know where to jump into this thread so I'll jump here. Walter, would it be possible to get a "lint" program that flags dubious constructs? I'd like to working something like that into the D emacs mode so that typical errors can be flagged as the source code is written instead - but at the user's request. At work we use a tool like this called mlint - obviously based on the old lint program and it does wonders for cleaning up code and suggesting more efficient constructs etc. We have it integrated into all of our MATLAB editor tools so that you just hit a button and it highlights all the lines with recommendations and what the recommendations are. I hope that given D's lack of preprocessor and simpler syntax a dlint program would be able to generate some very useful recommendations. -Ben |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Walter | On Sat, 5 Feb 2005 17:46:37 -0800, Walter wrote: > What you're advocating sounds very much like how compile time warnings work in typical C/C++ compilers. Is this what you mean? Firstly, be they 'warning', 'information', 'error', 'FOOBAR', 'coaching', whatever... messages, I don't care. I don't care what you call the messages. I am asking for better (useful, helpful, detailed) information to be passed from the compiler to the coder. As I know you have some deep seated hang-up with the concept of 'warning message', what say we call them Transitory Information/Problem Status messages (TIPS for short). Secondly, we are only talking about two or three distinct situations, not all the hundreds of possible constructs out there. Currently DMD *already* takes special action in these situations, so its not a big difference. DMD already has all the information at its fingertips, so to speak, all it needs to do is pass this information on to the coder. If the coder decides to ignore them, or add stupid code, or tells DMD to shut up, then there is nothing more you can do. Its not your fault! Its okay, really. You did your best to help. In the long run, one cannot protect oneself, or others, from idiots. A fool-proof system just causes the universe to come up with a better class of fool. -- Derek Melbourne, Australia |
February 06, 2005 Re: Compiler support for writing bug free code | ||||
---|---|---|---|---|
| ||||
Posted in reply to Matthew | "Matthew" <admin@stlsoft.dot.dot.dot.dot.org> wrote in message news:cu3v58$3c3$1@digitaldaemon.com... > A maintenance engineer is stymied by *both* > forms, and confused contrarily: the first looks like a bug but may not > be, the second is a bug but doesn't look like it. The only form that > stands up to maintenance is something along the lines of what Derek's > talking about: > > int foo(CollectionClass c, int y) > { > foreach (Value v; c) > { > if (v.x == y) > return v.z; > } > > throw logic_error("This function has encountered a situation > which contradicts its design and/or the design of the software within > which it resides"); > > return 0; > } From a C/C++ perspective, you're right, this is the only correct solution. From a D perspective, however, I submit that the first example is not confusing. There is no falling off the end in D functions, as an exception would be thrown. The only returns that can happen are explicitly there with return statements. The maintenance engineer will know this as surely as he knows that after an assert(p) that p is not null. I agree this is a different way of thinking about the code, that coming from a solid C/C++ background it might be a bit off-putting. > This is what I also do in such cases, and I believe (and have witnessed) it being a widely practiced technique. Yes, and I've written magazine articles and done lectures pushing exactly that. It's what one has to do with C/C++. >You're > keen to mould D with a view to catering for, or at least mitigating the actions of, the lowest common denominators of the programming gene pool. I've seen this kind of error written by experts, not just the lowest common denominator. If D cannot prevent an error, it should try to mitigate the damage. >Yet you seem decidely uninterested in addressing the concerns of > large scale and/or commercial and/or large-teams and/or long-lasting codebases. How can this attitude help D to prosper? I have to disagree with this. Many features of D are the result of many long conversations with program development managers. They need positive mechanisms in the language to prevent or at least mitigate the effects of common, very human, programming mistakes. C and C++ are seriously deficient in this area. That you disagree with the efficacy of one the solutions does not at all mean I am uninterested. A very large part of D is providing support for writing robust code. > Your measure adds an indeterminately timed exception fire, in the case that a programmer doesn't add a return 0. That's great, so far as it goes. But here's the fly in your soup: what's to stop them adding the return 0? Absolutely nothing. But as I wrote before, if he's looking at fixing the code after the exception fired, he knows he's dealing with a bug that needs fixing. In the case of the compiler error message, there is not necessarilly a bug there, so the easy temptation is to throw in a return of some arbitrary value. Is that bad programming technique? Absolutely. Does it happen anyway? Yes, it does. I've been in code review meetings and listened to the excuses for it. Those kinds of things are hard to pick up in a code review, so removing the cause of it and trying to mitigate the damage is of net benefit. Let's put it this way, here are the choices (numbers pulled out of dimension X): 1) A bug catching feature that 90% of the time will cause the programmer to write correct code, but 10% of the time will result in code that has an insidious, nasty, hard to reproduce & find bug. 2) A bug catching feature that 70% of the time will cause the programmer to write correct code, but the 30% that get it wrong results in code that when it fails, fails cleanly, in an easy to reproduce, find and therefore fixable manner. It's a judgement call, not dogma. I'd rather have (2), and I believe that (2) is better for the long term success of a code base. I do not like (1), b ecause the penalties of such bugs, even though they are less frequent, are so severe they overshadows everything else. |
Copyright © 1999-2021 by the D Language Foundation