* Re: Software landmines (loops) @ 1998-09-07 0:00 Robert Martin 1998-09-08 0:00 ` Mike Spille 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-07 0:00 UTC (permalink / raw) Mike Spille wrote in message <35F0484A.2108A9F@tisny.com>... >Robert Martin wrote: >> >> >> int f(char* name) // returns status value >> { >> int status = 0; >> if (File* f = fopen(name, "r")) >> { >> if (char* buffer = malloc(80)) >> { >> DoSomethingUseful(f,buffer); >> free(buffer); >> } >> else // malloc failure >> { >> Log("malloc failure"); >> status = -2; >> } >> fclose(f); >> } >> else // fopen failure >> { >> Log("Failure to fopen"); >> status = -1; >> } >> return status; >> } >> >> Perhaps you think this is cumbersome. I don't. Cumbersome is a rather >> subjective term. >> > >I find it quite cumbersome, and error prone to boot. I'd do it as: > >int f(char* name) // returns status value >{ > char buf[80]; > FILE* f = fopen(name, "r"); > if (f == NULL) { > Log("Failure to fopen"); > return (-1); > } > > DoSomethingUseful(f,buf, sizeof(buf)); > fclose (f); >} > >That is, use a stack-based buffer and pass in the size of the char array to >do something useful so it doesn't walk off the end of the buffer by mistake >(assuming that DoSomethingUseful is smart enough to include a size argument). Come one Mike, I was using the program as an example. It's not a real program. If you like I'll add the requirement that the buffer *must* come from the heap because stack and heap memory run at different speeds, and the 'DoSomethingUseful' function needs the heap speed memory. (Sounds crazy but one of my clients has a platform with just such a constraint). As for passing in the size, you have a point -- but its completely irrelevant to the topic at hand. In short, you are clutching at straws. >My point? I focused on what the routine was supposed to do, not on a >methodology, And apparently not on what we were discussing. We were not discussing whether buffers should be stack or heap based. We were not discussing whether size variables should be passed along with buffers. We were discussing whether or not se/se makes a function cumbersome. I used an example to make a point, and you side stepped the point. >(And I think it's more readable :-) Which makes my point about subjectivity for me. -- Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 Software landmines (loops) Robert Martin @ 1998-09-08 0:00 ` Mike Spille 0 siblings, 0 replies; 510+ messages in thread From: Mike Spille @ 1998-09-08 0:00 UTC (permalink / raw) Robert Martin wrote: > > Mike Spille wrote in message <35F0484A.2108A9F@tisny.com>... > >Robert Martin wrote: > >> > >> > >> int f(char* name) // returns status value > >> { > >> int status = 0; > >> if (File* f = fopen(name, "r")) > >> { > >> if (char* buffer = malloc(80)) > >> { > >> DoSomethingUseful(f,buffer); > >> free(buffer); > >> } > >> else // malloc failure > >> { > >> Log("malloc failure"); > >> status = -2; > >> } > >> fclose(f); > >> } > >> else // fopen failure > >> { > >> Log("Failure to fopen"); > >> status = -1; > >> } > >> return status; > >> } > >> > >> Perhaps you think this is cumbersome. I don't. Cumbersome is a rather > >> subjective term. > >> > > > >I find it quite cumbersome, and error prone to boot. I'd do it as: > > > >int f(char* name) // returns status value > >{ > > char buf[80]; > > FILE* f = fopen(name, "r"); > > if (f == NULL) { > > Log("Failure to fopen"); > > return (-1); > > } > > > > DoSomethingUseful(f,buf, sizeof(buf)); > > fclose (f); > >} > > > >That is, use a stack-based buffer and pass in the size of the char array to > >do something useful so it doesn't walk off the end of the buffer by mistake > >(assuming that DoSomethingUseful is smart enough to include a size > argument). > > Come one Mike, I was using the program as an example. It's not a real > program. If you like I'll add the requirement that the buffer *must* come > from the heap because stack and heap memory run at different speeds, and the > 'DoSomethingUseful' function needs the heap speed memory. (Sounds crazy but > one of my clients has a platform with just such a constraint). As for > passing in the size, you have a point -- but its completely irrelevant to > the topic at hand. In short, you are clutching at straws. > No, I was pointing out that you lost for the forest for the trees. While pointing out the possible advantages of single entry/return, you meanwhile ignored common C/C++ coding practices: keep functions as small as possible, don't malloc() unnecessarily, always pass array sizes around with arrays. By concentrating on the advantages of your particular style, you managed to write a rather poor function. > >My point? I focused on what the routine was supposed to do, not on a > >methodology, > > And apparently not on what we were discussing. We were not discussing > whether buffers should be stack or heap based. We were not discussing > whether size variables should be passed along with buffers. We were > discussing whether or not se/se makes a function cumbersome. I used an > example to make a point, and you side stepped the point. > Once upon a time a buddy of mine was writing a C coding guidelines manual for a company we both worked for. He asked me to proof read it for him. I did so, and while I had some mild objections here and there I found his guidelines reasonable - with one exception. At the end of the guide he provided an example that demonstrated some of the major style-points he had touched upon. His example did indeed avoid all the downfalls he had warned against in his writing, and followed the style he'd outlined perfectly. Unfortunately, the algorithm he had coded was horrendously inefficient, and buggy to boot. In his zeal to promote his guidelines, he'd forgotten to focus on what the algorithm was supposed to do. I would say that you did the same - you focused so much on the style of the code that you ignored the algorithm. The end-goal of writing a function is primarily that it does what you want it to do, and does it well. If you focus more on following a given set of rules than you do on what you're trying to accomplish, your results are going to reflect your priorities. > >(And I think it's more readable :-) > > Which makes my point about subjectivity for me. > > -- > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful
@ 1998-08-06 0:00 Robert Dewar
1998-08-07 0:00 ` harald.mueller
0 siblings, 1 reply; 510+ messages in thread
From: Robert Dewar @ 1998-08-06 0:00 UTC (permalink / raw)
Lars says
<<Are you saying tht GC would introduce a larger risk for incorrect
programs than exceptions? If so, why?
>>
Most certainly! GC introduces a huge risk for incorrect programs. Garbage
collectors assume that the pointer structure of a program is correct. If
it is corruptede, garbage collectors can cause horrible havoc. Indeed this
havoc often only shows up after several mark-and-sweep type cycles of the
GC, and it can be almost impossible to track them down
(said from horrible experiences in implementing general GC!)
^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-06 0:00 Why C++ is successful Robert Dewar @ 1998-08-07 0:00 ` harald.mueller 1998-08-07 0:00 ` Brian Rogoff 0 siblings, 1 reply; 510+ messages in thread From: harald.mueller @ 1998-08-07 0:00 UTC (permalink / raw) In article <dewar.902415458@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > > Lars says > > <<Are you saying tht GC would introduce a larger risk for incorrect > programs than exceptions? If so, why? > >> > > Most certainly! GC introduces a huge risk for incorrect programs. Garbage > collectors assume that the pointer structure of a program is correct. If > it is corruptede, garbage collectors can cause horrible havoc. Indeed this > havoc often only shows up after several mark-and-sweep type cycles of the > GC, and it can be almost impossible to track them down > > (said from horrible experiences in implementing general GC!) > Now that's interesting. I did never write a GC, but I wrote a heap management system, which had bugs in it for the first few weeks, and you wouldn't believe it: A correct GC would have been MUCH BETTER than my wrong heap management. So? Actually, the problem with new/delete schemes is that the *user*(!!) can corrupt the heap, e.g. by deleting stack variables: f(C* p) { C defaultC; C* c; if (p == null) c = &defaultC; else c = p; ... ... ... delete c; } Similar with static class variables etc. You wouldn't believe how many heaps silently and very late crash after such errors (which are mostly introduced innocently during maintenance - "we dont have to create a new C all the time - just let's have a single static one"). HMMueller -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-07 0:00 ` harald.mueller @ 1998-08-07 0:00 ` Brian Rogoff 1998-08-07 0:00 ` Timothy Welch 0 siblings, 1 reply; 510+ messages in thread From: Brian Rogoff @ 1998-08-07 0:00 UTC (permalink / raw) On Fri, 7 Aug 1998 harald.mueller@siemenscom.com wrote: > dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > > Most certainly! GC introduces a huge risk for incorrect programs. Garbage > > collectors assume that the pointer structure of a program is correct. If > > it is corruptede, garbage collectors can cause horrible havoc. Indeed this > > havoc often only shows up after several mark-and-sweep type cycles of the > > GC, and it can be almost impossible to track them down > > > > (said from horrible experiences in implementing general GC!) > > Now that's interesting. I did never write a GC, but I wrote a heap management > system, which had bugs in it for the first few weeks, and you wouldn't > believe it: A correct GC would have been MUCH BETTER than my wrong heap > management. So? I have nothing against GC, in fact I like it in general and wish its use was more widespread, but a very large part of your problem is that the language you are working in (1) Doesn't distinguish between pointers to local variables and pointers to heap allocated memory. (2) Allows you to get a pointer to any local variable, rather than forcing you to be explicit about which local variables can be pointed to, or "aliased". (3) Makes it easy to do all kinds of other arbitrary weird things with pointers. In an otherwise very similar language, Ada, none of these are a problem. Sure, the user could always declare every local variable as aliased, and make every pointer "access all" to point to heap and local variables, and insist on using Unchecked_Access ("&" in C/C++) and Unchecked_Conversion (casting) to turn off all the checks, but the presence of "Unchecked_" anything tells you where the problem might be. Modula-3 has the requirement that any module which uses unsafe features of the language be labelled as UNSAFE, which is an idea I like too, though it also has GC so you proabbly wouldn't write allocators in M3. I tend to think of Ada as being semantically similar to C++ (especially wrt to the fact that Ada allows low level programming), except that while C++ allows you to be safe, the defaults are unsafe, and while Ada allows you to be unsafe, the defaults are safe. Since I'm sort of a slapdash programmer, I prefer help from the compiler to avoid the sort of mishaps Harald describes. Doubtless the C++ experts out there who are writing reliable code are a lot smarter than me and don't need this kind of help, or they get it by using tools like Lint and Purify; probably both. I don't have the same problems in Ada that I do in C or C++, even though I'm *far* more familiar with C than Ada (I use C every day). -- Brian ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-07 0:00 ` Brian Rogoff @ 1998-08-07 0:00 ` Timothy Welch 1998-08-08 0:00 ` Robert Dewar 0 siblings, 1 reply; 510+ messages in thread From: Timothy Welch @ 1998-08-07 0:00 UTC (permalink / raw) On Fri, 7 Aug 1998 13:21:17 -0700, Brian Rogoff <bpr@shell5.ba.best.com> wrote: >I have nothing against GC, in fact I like it in general and wish its use >was more widespread, but a very large part of your problem is that the >language you are working in > >(1) Doesn't distinguish between pointers to local variables and pointers > to heap allocated memory. > >(2) Allows you to get a pointer to any local variable, rather than forcing > you to be explicit about which local variables can be pointed to, or > "aliased". > >(3) Makes it easy to do all kinds of other arbitrary weird things with > pointers. > Out of curiousity why are (1) and (2) problems? Can't the GC just check to see if the pointer is pointing to memory on the stack? Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-07 0:00 ` Timothy Welch @ 1998-08-08 0:00 ` Robert Dewar 1998-08-08 0:00 ` Jeffrey C. Dege 0 siblings, 1 reply; 510+ messages in thread From: Robert Dewar @ 1998-08-08 0:00 UTC (permalink / raw) Timothy Welch says <<>(1) Doesn't distinguish between pointers to local variables and pointers > to heap allocated memory. > >(2) Allows you to get a pointer to any local variable, rather than forcing > you to be explicit about which local variables can be pointed to, or > "aliased". > >(3) Makes it easy to do all kinds of other arbitrary weird things with > pointers. > Out of curiousity why are (1) and (2) problems? Can't the GC just check to see if the pointer is pointing to memory on the stack? >> Undoubtedly at least *part* of the problem in using C is that people are not sufficiently aware of what can go wrong. Microsoft has a rather amazing book that pretends to be a book about software techniques, but in fact is little more than a set of perfectly standard coding procedures to avoid pitfalls in C. When I read it, I was surprised that professional C programmers would find such a book useful, but the questions above are a reminder that you often people are not aware of the dangers. I must say I worry about CS curriculums in which people are only getting exposed to C and C++ and hence simply don't register important language design principles (after all the idea that it is obviously a bad idea to allow pointers to local variables is a very old one, dating back at least to Pascal, which means coming up to 30 years. Timothy, to answer your questions. (1) is a serious problem, since it can allow dangling pointers. That is, when you leave a scope with such a pointer, then you have a pointer to inactive stack. Using this pointer later on can cause serious damage, e.g. clobbering a return point stored on the stack. These dangling pointers are created even though you never use free. There is no practical implementation mechanism for efficiently detecting such a dangling pointer. (2) is of course related, but is at a more conceptual level. Aliasing is always dangerous because it can cause code to be very difficult to read, understand, and maintain (as well as leading to accidental bugs in the first place). Consider in C: (everything is an int or a *int) a = b; c = 3 + q; *d = 4; That assignment to *d *may* modify the values of a and c. This means you cannot just read ahead in the code at this stage, you have to ensure that it is not possible for d to be pointing to a or c, or worse discover that it is possible, and that one of the first two assignments is dead. A (good) compiler will make an attempt to determine the answer (it is not always possible to do this reliably). A compiler that does not make this effort risks generating horrible code for the above, since it has to forget the values of a and c in registers. A compiler that tries hard still often finds that it has to be conservative and assume the worst. A (good) programmer will make an attempt to determine the answer (it is not always possible to do this reliably). A programmer that does not make this effort risks seriously misunderstanding the above, since they will have to forget the assigned values of a and c. A programmer that tries hard still often finds that they have to be conservative and assume the worst. Note the parallel language here is quite deliberate. Whey you set obstacles for a compiler, you set them for a programmer as well. A clever compiler can compensate, and that's OK, since machine time is cheap, so what if the compilation takes longer (but as noted, even a clever compiler can be fooled). A clever programmer can compensate, and that is NOT OK, since programmer time is not cheap, and maintenance mistakes are very costly. In Pascal and Ada 83, a decision was made to completely disallow pointers to local variables, and this is undoubtedly the best decision from a language point of view. However, especially when interfacing to other languages, this proves an annoying restriction. For example, if you are interfacing to a language like C that typically requires pointers to parameters to be passed, then it is annoying not to be able to pass pointers to local variables. Ada 83 programmers would often resort to nasty low level junk (i.e. use of the 'Address attribute) for this purpose, leading to code that has all the disadvantages discussed above, and more. Why more? Becuase (a) address gives untyped pointers, like void*, and (b) the semantics of whether the aliasing attempt "works" correctly is not clear from the standard. Ada 95 compromises by allowing you to declare a variable as aliased, which means that it is allowable to take its "address", using the strongly typed 'Access attribute. An Ada 95 program that declared every local variable to be aliased would be equivalent to the C semantics (it would also be a travesty!) Generally you should alias local variables ONLY in connection with interfacing to foreign code. Yes, as with all rules, including this one, there are exceptions to this rule that are legitimate, but if you find you are using aliased extensively, something may be wrong with your approach. Robert Dewar P.S. with respect to the GC part of your question, sure, you can determine that a pointer points to the stack, but the dangling pointer case can cause unimaginable chaos in a garbage collector. Indeed the combination of garbage collection with semantics that allow dangling pointers is a dangerous one, dangerous enough to make a language design quite dubious from a practical point of view. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-08 0:00 ` Robert Dewar @ 1998-08-08 0:00 ` Jeffrey C. Dege 1998-08-10 0:00 ` Laurent GUERBY ` (11 more replies) 0 siblings, 12 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-08-08 0:00 UTC (permalink / raw) On 8 Aug 1998 08:27:02 -0400, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: > >Undoubtedly at least *part* of the problem in using C is that people are not >sufficiently aware of what can go wrong. Microsoft has a rather amazing >book that pretends to be a book about software techniques, but in fact is >little more than a set of perfectly standard coding procedures to avoid >pitfalls in C. When I read it, I was surprised that professional C >programmers would find such a book useful, but the questions above are >a reminder that you often people are not aware of the dangers. If you're talking about Steve McGuire's books, (Code Complete, Writing Solid Code), I'm a professional C programmer, and I didn't find anything in them that I hadn't been aware of for many years. >I must >say I worry about CS curriculums in which people are only getting exposed >to C and C++ and hence simply don't register important language design >principles (after all the idea that it is obviously a bad idea to allow >pointers to local variables is a very old one, dating back at least to >Pascal, which means coming up to 30 years. I have to agree with the above. A CS curriculumn should have some breadth to it. Exposure to a variety of languages is a part of this, as is instruction in the theory underlying compilers. -- The most exciting phrase to hear in science, the one that heralds new discoveries, is not "Eureka!" ("I found it!") but rather "hmm....that's funny..." -- Isaac Asimov ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-08 0:00 ` Jeffrey C. Dege @ 1998-08-10 0:00 ` Laurent GUERBY 1998-08-12 0:00 ` Andy Ward [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <m31zpxqutn.fsf@mheaney.ni.net> ` (10 subsequent siblings) 11 siblings, 1 reply; 510+ messages in thread From: Laurent GUERBY @ 1998-08-10 0:00 UTC (permalink / raw) jdege@jdege.visi.com (Jeffrey C. Dege) writes: > On 8 Aug 1998 08:27:02 -0400, Robert Dewar <dewar@merv.cs.nyu.edu> wrote: > > > >Undoubtedly at least *part* of the problem in using C is that people are not > >sufficiently aware of what can go wrong. Microsoft has a rather amazing > >book that pretends to be a book about software techniques, but in fact is > >little more than a set of perfectly standard coding procedures to avoid > >pitfalls in C. When I read it, I was surprised that professional C > >programmers would find such a book useful, but the questions above are > >a reminder that you often people are not aware of the dangers. > > If you're talking about Steve McGuire's books, (Code Complete, Writing > Solid Code), I'm a professional C programmer, and I didn't find anything > in them that I hadn't been aware of for many years. > [...] "Code Complete" author is Steve McConnell, not Steve McGuire. I think Robert talks about the latter. The former, "Code Complete", is a very nice book IMHO, and amongst the languages covered there is Ada (together with C/C++/Pascal/VB). It makes a nice advocacy package for strongly typed language BTW (you can shoot yourself into the foot easily with language X whereas you get an error message with language Y ;-). A little quote for c.l.a. readers, from the "goto" pro and cons section (reminds me of some threads ;-): "Finally, the goto was incorporated into the Ada language, the most carefully engineered programming language in history. Ada was developped long after the arguments on both sides of the goto debate had been fully developped, and after considering all sides of the issue, Ada engineers decided to include the goto" -- Laurent Guerby <guerby@bnp-eng.remcomp.com>, Team Ada, Linux/GNU addict "Use the Source, Luke. The Source will be with you, always (GPL)." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-10 0:00 ` Laurent GUERBY @ 1998-08-12 0:00 ` Andy Ward 1998-08-14 0:00 ` Robert Dewar 0 siblings, 1 reply; 510+ messages in thread From: Andy Ward @ 1998-08-12 0:00 UTC (permalink / raw) > A little quote for c.l.a. readers, from the "goto" pro and cons >section (reminds me of some threads ;-): > >"Finally, the goto was incorporated into the Ada language, the most >carefully engineered programming language in history. Ada was >developped long after the arguments on both sides of the goto debate >had been fully developped, and after considering all sides of the >issue, Ada engineers decided to include the goto" > Ahh... but have you ever found a "good" reason for using it? I have used goto in C and Pascal in certain rare cases, but I have always found clearer ways to code these cases in Ada. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Why C++ is successful 1998-08-12 0:00 ` Andy Ward @ 1998-08-14 0:00 ` Robert Dewar 1998-08-14 0:00 ` Software landmines (was: Why C++ is successful) dennison 0 siblings, 1 reply; 510+ messages in thread From: Robert Dewar @ 1998-08-14 0:00 UTC (permalink / raw) Andy said <<Ahh... but have you ever found a "good" reason for using it? I have used goto in C and Pascal in certain rare cases, but I have always found clearer ways to code these cases in Ada. >> The two obvious uses vfor gotos in Ada are 1) to get a loop "continue" mechanism 2) to write finite state machines encoding the state into the PC. Yes, some people prefer case statements for this purpose, but many people prefer the use of labels and gotos as the most obvious translation of labeled states with arrows between them. In general, the use of gotos makes sense if the resulting code is clearer and easier to maintain. THat's relatively rare, but not non-existnent, and it is quite common to run across tortured code with multiple boolean flags which can be easily simplified using a goto. For example, I find the following perfectly clear: <<sort>> for J in 1 .. N - 1 loop if D (J) > D (J + 1) then Swap (D(J), D(J + 1)); goto Sort; end if; It is a little tricky to program this without the goto and not make it less clear. Actuallky many people who try this end up with a different algorithm (hint: the above sort is cubic, it is NOT a quadratic bubble sort :-) \x1adp ^ permalink raw reply [flat|nested] 510+ messages in thread
* Software landmines (was: Why C++ is successful) 1998-08-14 0:00 ` Robert Dewar @ 1998-08-14 0:00 ` dennison 1998-08-16 0:00 ` Robert Dewar 0 siblings, 1 reply; 510+ messages in thread From: dennison @ 1998-08-14 0:00 UTC (permalink / raw) In article <dewar.903074236@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > Andy said > > <<Ahh... but have you ever found a "good" reason for using it? I have used > goto in C and Pascal in certain rare cases, but I have always found clearer > ways to code these cases in Ada. > >> > > The two obvious uses vfor gotos in Ada are > > 1) to get a loop "continue" mechanism for a simple loop, embedding the rest of the loop code in the body of the if statement is clearer. For nested loops where you want to "continue" an outer loop, I can see it. Not that I'd do such a thing. As a "goto-holic" who has been straight for 10 years, the best bet is abstinence. One day at a time. :-) > For example, I find the following perfectly clear: > > <<sort>> for J in 1 .. N - 1 loop > if D (J) > D (J + 1) then > Swap (D(J), D(J + 1)); > goto Sort; > end if; > > It is a little tricky to program this without the goto and not make it > less clear. Actuallky many people who try this end up with a different > algorithm (hint: the above sort is cubic, it is NOT a quadratic bubble sort :-) So the "average" poor maintainer schlep looks at this and thinks "is this just a continue, or a complete restarting of the loop?" Oh yeah, that's clear. %-( If anyone does something this bizzare, they'd better put copious comments around it explaining its semantics. Otherwise, its the software equivalent of a land mine. Its just sitting there waiting for someone to touch it, then ...BOOM! Very good counterexample to your own point. T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-14 0:00 ` Software landmines (was: Why C++ is successful) dennison @ 1998-08-16 0:00 ` Robert Dewar 1998-08-17 0:00 ` dennison 0 siblings, 1 reply; 510+ messages in thread From: Robert Dewar @ 1998-08-16 0:00 UTC (permalink / raw) T.E.D says For a simple loop, embedding the rest of the loop code in the body of the if statement is clearer. For nested loops where you want to "continue" an outer loop, I can see it. Not that I'd do such a thing. Even in the simple case: for J in 1 .. N loop if D (J) = NaN then goto Continue; end if; giant section of code <<Continue>> null; end loop; as opposed to for J in 1 .. N loop if D (J) /= NaN then giant section of code end if; end loop; there may be a preference for the goto. It shows the reader right up front that the loop does nothing at all to NaN's, without having to match up the if with the end if at the end of the giant section of code to know this. Also, it means that the giant section of code has one less level of indentation. But it's a toss up in this case, and for most purposes we would prefer the second case. Where it gets tricky is for J in 1 .. N loop if condition 1 then ... if condition 2 then ... if conditoin 3 then goto Continue; Now T.E.D's prescription is not so clear, and we end up having to severely contort things, or introduce a boolean flag which we keep testing as we unwind to the end. Remember that the continue here is just like a return. If you are allergic to using a loop continue or exit, you should be allergic to using a return (other than at the end of a function). Some people are, and that is at least consistent. But I see a lot of Ada programmers who will use a return without hesitation from a nested loop, but still turn green at the sight of a goto. That makes no sense to me. As a "goto-holic" who has been straight for 10 years, the best bet is abstinence. One day at a time. :-) Maybe the comparison is apt. If you really are unable to figure out how to use gotos properly, then perhaps abstinence is the "best bet", but just as we know that wine drunk in moderation can actually be a health benefit, and is most certainly not a health danger, the occasional use of a goto can be beneficial for the clarity and efficiency of your code. We can appreciate and sympathize with the poor goto-holic's who may not risk this, but it does not mean the rest of us have to abstain :-) So the "average" poor maintainer schlep looks at this and thinks "is this just a continue, or a complete restarting of the loop?" Oh yeah, that's clear. %-( The idea that code can ever be maintained by incompetent shlep's who do not understand the language they are writing in is of course a serious error. Yes, I know it happens, look at the results, need I say more? On the other hand, I see no reason to accept this rhetoric, if indeed you do have these poor maintainer shleps looking at the code, we have only T.E.D.'s unsupported allegation that they will have more trouble with my form than some other form (note that, perhaps wisely, T.E.D does not attempt to demonstrate the beautifully clear, alternative, goto-free form -- enough other competent people have tripped on that already :-) If anyone does something this bizzare, they'd better put copious comments around it explaining its semantics. Otherwise, its the software equivalent of a land mine. Its just sitting there waiting for someone to touch it, then ...BOOM! Well of course any code needs commenting, and pointing out the critical details of the algorithm in use, especially if, as in this case, it is likely to be an unfamiliar algorithm, is definitely a good idea. Very good counterexample to your own point. I don't think so! ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-16 0:00 ` Robert Dewar @ 1998-08-17 0:00 ` dennison 1998-08-19 0:00 ` ell 0 siblings, 1 reply; 510+ messages in thread From: dennison @ 1998-08-17 0:00 UTC (permalink / raw) In article <dewar.903281994@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > T.E.D says > > But it's a toss up in this case, and for most purposes we would prefer > the second case. Where it gets tricky is > > for J in 1 .. N loop > if condition 1 then > ... > if condition 2 then > ... > if conditoin 3 then > goto Continue; > > Now T.E.D's prescription is not so clear, and we end up having to > severely contort things, or introduce a boolean flag which we keep > testing as we unwind to the end. > > Remember that the continue here is just like a return. If you are allergic > to using a loop continue or exit, you should be allergic to using a return > (other than at the end of a function). Some people are, and that is at > least consistent. But I see a lot of Ada programmers who will use a return > without hesitation from a nested loop, but still turn green at the sight > of a goto. That makes no sense to me. > Good point. Typically in this case I would "cheat" it and embed the inside of the loop in a subprogram, with a return statement. You think that's no better than using a "goto". I think it IS better, because the rule for where control goes to after a return statement is much clearer than for goto. For the return, I just start reading code after the subprogram call. For goto, I have to search the entire source for the label that is being jumped to. Just as importantly, someone can completely change my structure just by moving that label. But yes, we are probably talking Bordeaux vs. Mad Dog 20-20. > So the "average" poor maintainer schlep looks at this and thinks > "is this just a continue, or a complete restarting of the loop?" > Oh yeah, that's clear. %-( > > On the other hand, I see no reason to accept this rhetoric, if indeed > you do have these poor maintainer shleps looking at the code, we have > only T.E.D.'s unsupported allegation that they will have more trouble > with my form than some other form (note that, perhaps wisely, T.E.D > does not attempt to demonstrate the beautifully clear, alternative, > goto-free form -- enough other competent people have tripped on that > already :-) Why take my word for it? The very fact that "other competent people have tripped on that" proves how obtuse it is. You'd be quite lucky to have a maintanence staff as good as the folks here on c.l.*, and *they* can't even make a simple change to your code without completely screwing it up. I couldn't hope to come up with a better example. T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-17 0:00 ` dennison @ 1998-08-19 0:00 ` ell 1998-08-19 0:00 ` adam 0 siblings, 1 reply; 510+ messages in thread From: ell @ 1998-08-19 0:00 UTC (permalink / raw) In article <6r9f8h$jtm$1@nnrp1.dejanews.com>, dennison@telepath.com wrote: > In article <dewar.903281994@merv>, > dewar@merv.cs.nyu.edu (Robert Dewar) wrote: > > T.E.D says > > > > But it's a toss up in this case, and for most purposes we would prefer > > the second case. Where it gets tricky is > > > > for J in 1 .. N loop > > if condition 1 then > > ... > > if condition 2 then > > ... > > if conditoin 3 then > > goto Continue; > > > > Now T.E.D's prescription is not so clear, and we end up having to > > severely contort things, or introduce a boolean flag which we keep > > testing as we unwind to the end. > > > > Remember that the continue here is just like a return. If you are allergic > > to using a loop continue or exit, you should be allergic to using a return > > (other than at the end of a function). Some people are, and that is at > > least consistent. But I see a lot of Ada programmers who will use a return > > without hesitation from a nested loop, but still turn green at the sight > > of a goto. That makes no sense to me. A 'return', at least in C/C++/VB, returns you to the place the current procedure was called from. 'goto' control flow can be endlessly channeled here and there and never has to return to where the initial linear control flow was originally diverted. That seems to be a huge advantage of 'return' over 'goto'. Elliott -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-19 0:00 ` ell @ 1998-08-19 0:00 ` adam 1998-08-19 0:00 ` Dan Higdon [not found] ` <l5HC1.6840$wN.18 <35F238F7.F57D3EC7@earthlink.net> 0 siblings, 2 replies; 510+ messages in thread From: adam @ 1998-08-19 0:00 UTC (permalink / raw) In article <6renh8$ga7$1@nnrp1.dejanews.com>, ell@access.digex.net wrote: > A 'return', at least in C/C++/VB, returns you to the place the current > procedure was called from. 'goto' control flow can be endlessly channeled > here and there and never has to return to where the initial linear control > flow was originally diverted. That seems to be a huge advantage of 'return' > over 'goto'. No, to me this seems to be a huge advantage of "return" over "using too many goto's in your code that go every which way so that your code ends up looking like spaghetti." No one is supporting the idea of using that many goto's, the way programmers used to. Those who think goto's are OK think they should be limited to certain specific situations, and your objection really doesn't apply when goto's are used in that sort of careful, disciplined fashion. Of course, "goto" can be dangerous in the hands of an inexperienced programmer; but so, for that matter, can every other construct of every language. In the 22 years or so since programmers have started treating "goto" as an evil, I've seen some pretty strange arguments purporting to explain *why* goto's were bad. The most bizarre one I've seen argued that if your code is structured as follows: Transformation-1; goto L; Transformation-2; L: .... where Transformation-1 and Transformation-2 are sequences of statements or something else that transform your current program state from one thing to another, then the presence of "goto" in effect means that your code contains the inverse function of Transformation-2, which cancels the effect of Transformation-2. The author offered this as an explanation why "goto" makes code harder to understand. I don't remember exactly where I read this, but it was in one of the ACM publications. Of course, this is nonsense. There are good reasons why a researcher might want to think of a "program" as a sequence of mathematical transformations on the program state, but an ordinary programmer trying to write correct code, or to read or maintain someone else's code, isn't going to think about things that way. That's why I'm skeptical about most of the arguments I see about why GOTO IS EVIL. There often seems to be an implicit assumption that mathematical purity, or an aesthetically beautiful program structure, or something similar, equals readability, but that isn't the case. So when I see statements like "'goto' control flow can be endlessly channeled here and there and never has to return to where the initial linear control flow was originally diverted", my reaction is, "So what?" This argument contains no explanation *why* this makes programs harder to work with. So, personally, I think arguments against "goto" (or against any other construction) should demonstrate things from the programmer's point of view. That is, how does this EVIL NASTY construct actually make it harder for a programmer to understand what's going on, or make it easier for a programmer to miss something and write incorrect code? If the argument doesn't address the issue from that angle, it's worthless, IMHO. Now, here are a couple arguments on the other side: (1) Say you want to avoid the EVIL NASTY "goto" by putting the code into a subroutine and using "return". Well, you have to give the subroutine a name. In place of the nested "if" causing the problem, you'll have a call to this subroutine. Now, when a programmer looks through the main line of code, she'll see a call to this subroutine, and she'll have to know what it does. Can you give the subroutine a name that will make it obvious to the maintenance programmer what's going on? Sometimes you can. But if all you're doing is extracting some code and sticking it in a subroutine, most of the time you can't give it a good descriptive name, since it reflects just a random sequence of statements and not a concept that can be easily compartmentalized. So in this case, IMHO doing this is worse than using "goto", since it makes the program less clear. Of course, you can probably figure out a way to redesign the code to make it clear, and your code will be more readable since it has smaller, more compact subroutines that perform a well-defined purpose. But this just illustrates the importance of good design in general; a programmer who simply says "RETURN is a lot better than GOTO" and moves code around just to avoid the GOTO is unlikely to end up with a more readable and maintainable program. (2) (This one is about "continue", since Charles Hixson later argued that this was also superior to "goto" for the same reasons.) If you have a loop that looks like: while (blah-blah) { some-if-statements... some-more-if-statements... xxx; yyy; zzz; } someone reading the program might assume that xxx, yyy, and zzz are always going to happen before the loop repeats. So if there's something new that needs to be done during every loop iteration, it looks like you can just add it to the end of the loop, after zzz. If there's a "continue" statement somewhere above that, this assumption is incorrect and your modification may well be wrong. If you replace the "continue" with a "goto", at least there will be a label somewhere toward the bottom of the loop, alerting you to the fact that you will have to decide whether to put the new code before or after the label, or look for the place where this label is goto'ed. In fact, this is exactly why I stopped using "continue" when I was a C programmer. (I didn't replace them with goto's, I used Boolean flags instead.) Now all of this may be a matter of how each individual programmer tends to think when they look at programs. The point is that, based on my experience, arguments about "returning to where the linear control flow was diverted" and "restricted compass" don't make a whole lot of sense in the real world. GOTO can be used in ways that enhance readability or in ways that impair it, and so can every other feature of every language. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-19 0:00 ` adam @ 1998-08-19 0:00 ` Dan Higdon 1998-08-20 0:00 ` adam [not found] ` <l5HC1.6840$wN.18 <35F238F7.F57D3EC7@earthlink.net> 1 sibling, 1 reply; 510+ messages in thread From: Dan Higdon @ 1998-08-19 0:00 UTC (permalink / raw) adam@irvine.com wrote in message <6rf59b$2ud$1@nnrp1.dejanews.com>... <snip prelude> >Now, here are a couple arguments on the other side: <snip point 1> >(2) (This one is about "continue", since Charles Hixson later argued that this >was also superior to "goto" for the same reasons.) If you have a loop that >looks like: > > while (blah-blah) { > some-if-statements... > some-more-if-statements... > > xxx; > yyy; > zzz; > } > >someone reading the program might assume that xxx, yyy, and zzz are always >going to happen before the loop repeats. So if there's something new that >needs to be done during every loop iteration, it looks like you can just add >it to the end of the loop, after zzz. If there's a "continue" statement >somewhere above that, this assumption is incorrect and your modification may >well be wrong. If you replace the "continue" with a "goto", at least there >will be a label somewhere toward the bottom of the loop, alerting you to the >fact that you will have to decide whether to put the new code before or after >the label, or look for the place where this label is goto'ed. In fact, this >is exactly why I stopped using "continue" when I was a C programmer. (I >didn't replace them with goto's, I used Boolean flags instead.) So, you've actually changed the algorithm of your code, added an unnecessary data item and added yet another compare/branch to avoid a well understood (IMHO) construct of the C language? Perhaps I'm the only one who thinks writing code that will execute efficiently is equally important as writing readable code. If I didn't care about efficiency, I sure wouldn't be using a 3rd generation procedural language (OO or not) - there are (IMHO) many more succinct and mathematically rigorous languages out there than C or Eiffel (ML and Haskell come to mind, niether of which have gotos, fwiw). I'm not trying to start a language war - I'm pointing out that gotos and the implicit goto forms (break, continue, etc) are a tool of the language. They wouldn't be there if you NEVER needed them. So if you have a case that warrants their use, you should use them, rather than trying to hamstring yourself with hokey constructs. If you *need* that boolean value later, then by all means add it. But I think that using a boolean flag to erase a GOTO is not contributing to the solution, just adding inefficiency into the generated code, and one more symbol for the programmer to have to track. ---------------------------------------- hdan@charybdis.com "Throwing fire at the sun" ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (was: Why C++ is successful) 1998-08-19 0:00 ` Dan Higdon @ 1998-08-20 0:00 ` adam 1998-08-20 0:00 ` Software landmines (loops) Nick Leaton 0 siblings, 1 reply; 510+ messages in thread From: adam @ 1998-08-20 0:00 UTC (permalink / raw) In article <l5HC1.6840$wN.1856764@news.giganews.com>, "Dan Higdon" <hdan@charybdis.com> wrote: > > adam@irvine.com wrote in message <6rf59b$2ud$1@nnrp1.dejanews.com>... > > <snip prelude> > > >Now, here are a couple arguments on the other side: > > <snip point 1> > > >(2) (This one is about "continue", since Charles Hixson later argued > >that this was also superior to "goto" for the same reasons.) If > >you have a loop that looks like: > > > > while (blah-blah) { > > some-if-statements... > > some-more-if-statements... > > > > xxx; > > yyy; > > zzz; > > } > > > >someone reading the program might assume that xxx, yyy, and zzz are > >always going to happen before the loop repeats. So if there's > >something new that needs to be done during every loop iteration, it > >looks like you can just add it to the end of the loop, after zzz. > >If there's a "continue" statement somewhere above that, this > >assumption is incorrect and your modification may well be wrong. If > >you replace the "continue" with a "goto", at least there will be a > >label somewhere toward the bottom of the loop, alerting you to the > >fact that you will have to decide whether to put the new code > >before or after the label, or look for the place where this label > >is goto'ed. In fact, this is exactly why I stopped using > >"continue" when I was a C programmer. (I didn't replace them with > >goto's, I used Boolean flags instead.) > > So, you've actually changed the algorithm of your code, added an > unnecessary data item and added yet another compare/branch to avoid > a well understood (IMHO) construct of the C language? Perhaps I'm > the only one who thinks writing code that will execute efficiently > is equally important as writing readable code. If I didn't care > about efficiency, I sure wouldn't be using a 3rd generation > procedural language (OO or not) - there are (IMHO) many more > succinct and mathematically rigorous languages out there than C or > Eiffel (ML and Haskell come to mind, niether of which have gotos, > fwiw). Well, I might have used GOTO if I had to do it over again. My early training taught me to avoid them, and this avoidance has become kind of ingrained. I still probably wouldn't use "continue", however. However: #1: Adding a flag in the manner I've described does not change the algorithm, it merely changes the way the flow of control is expressed. Unless you adopt a definition of "algorithm" that is so strict as to be useless except to an academic. #2: How important efficiency is depends on what you're writing. If you're working on time-critical code, it's very important, but if you're working on an application where most of the program's time will be spent waiting for the user to type in some input, a few hundred microseconds isn't anything to worry about. #3: A good optimizing compiler wouldn't do a compare/branch. It might set the flag, then notice that the next thing done is to test it, so it would blow off the test and just branch to wherever the "continue" statement was going to branch anyway. An even better optimizing compiler would then figure out that the flag is never actually tested, so it would just get rid of it. #4: Programmers don't always get to choose which language they use. #5: In this thread, we're arguing about readability and maintainability. If you have a situation where every nanosecond is critical, fine, but most of us are willing to give up a few nanoseconds in order to save time debugging and maintaining programs. If you've ever written a subroutine that was called at only one point in the rest of the program, instead of coding it inline so that you can avoid an unnecessary procedure call with all the stack pushes and pops, then certainly you have to admit that readability is worth sacrificing a couple machine cycles for, sometimes. > I'm not trying to start a language war - I'm pointing out that gotos > and the implicit goto forms (break, continue, etc) are a tool of the > language. They wouldn't be there if you NEVER needed them. There are lots of language constructs that aren't really "needed". And there are plenty of cases where an individual programmer, or a programming department, adopts a policy of avoiding a particular construct, which is fine as long as the prohibition isn't 100% absolute. A long time ago, I programmed in COBOL, and most of the programmers around me agreed that the ALTER statement was just a bad idea and shouldn't be used. I'll bet few would disagree with such a policy. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-20 0:00 ` adam @ 1998-08-20 0:00 ` Nick Leaton 1998-08-30 0:00 ` Matthew Heaney [not found] ` <m3ogt3qgca.fsf@mheaney.ni.n <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net> 0 siblings, 2 replies; 510+ messages in thread From: Nick Leaton @ 1998-08-20 0:00 UTC (permalink / raw) I have just done a quick check through some Eiffel code. Out of 633 loops, just 1 needed a flag for early termination of the loop. -- Nick ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-20 0:00 ` Software landmines (loops) Nick Leaton @ 1998-08-30 0:00 ` Matthew Heaney 1998-08-30 0:00 ` Robert Martin [not found] ` <m3ogt3qgca.fsf@mheaney.ni.n <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net> 1 sibling, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-08-30 0:00 UTC (permalink / raw) Nick Leaton <nickle@calfp.co.uk> writes: > I have just done a quick check through some Eiffel code. > > Out of 633 loops, just 1 needed a flag for early termination of the > loop. My own experience is quite different from yours. Although I haven't counted, I use early loop termination ALL THE TIME. For example, I routinely implement an equality test (say, for a stack) as function "=" ... return Boolean is begin ... for Index in Positive range 1 .. L.Depth loop if L.Items (Index) /= R.Items (Index) then return False; end if; end loop; return True; end "="; If my loop termination depends on a value I just read, then exit from the middle is the simplest solution: loop Get (N); exit when N = 0; <process N> end loop; For example, this is a simplest way to tokenize a lexeme. You exit the loop in the middle, after determining that the character just consumed isn't part of the current token. Exiting is how you terminate passive iteration early: procedure For_Every_Item (Stack : in Stack_Type) is Done : Boolean := False; begin for Index in reverse Positive range 1 .. Stack.Top loop Process (Stack.Items (Index), Done); exit when Done; end loop; end For_Every_Item; Searching is also implemented using early loop termination: function Get_Position (C : Character; S : String) return Natural is begin for Index in S'Range loop if S (Index) = C then return Index; end if; end loop; return 0; end Get_Position; No auxilliary variables or flags are required. Below is a portion of my response to another thread on comp.lang.ada re the goto statement. Matt (start of quote) Any theory about using (or not using) a programming construct needs to be tested against observation, by performing an empirical study that measures the defect rates of programmers using the construct. If theory says use a construct, but observation reveals that programmers who use the construct produce more errors, then the theory needs to be thrown out. For example, there's a pernicious myth that exiting (or returning) from the middle of a loop is bad, and that the only proper way to write a loop is to state the termination condition explicitly, as a predicate appearing at the top of the loop. This theory was indeed put to the test, and guess what? Programmers using a test-and-exit from the middle of the loop produced fewer errors than those programmers who tried to put the test at the top of the loop. The researchers found that the exit-from-the-middle construct had a better "cognitive fit" than the other constructs. If you want to read the gory details, the article is Cognitive Strategies and Looping Constructs: An Empirical Study Soloway, Bonar, Ehrlich CACM, Nov 83, Vol 26, No 11, p 853-860 The goodness of a language construct should not be determined by doctrinaire computer scientists or mathematicians. The only thing that matters is whether working programmers think it's easier to understand, and whether by using the construct programmers inject fewer errors into the code. I think it was Stroustrup who said, "Programming is a human activity. Forget that, and all is lost." (end of quote) ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Matthew Heaney @ 1998-08-30 0:00 ` Robert Martin 1998-08-30 0:00 ` Charles Hixson ` (7 more replies) 0 siblings, 8 replies; 510+ messages in thread From: Robert Martin @ 1998-08-30 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >If theory says use a construct, but observation reveals that programmers >who use the construct produce more errors, then the theory needs to be >thrown out. All else being equal, that would be so. But when observation shows that the construct reduces the overall cost of maintaining the program, regardless of its initial cost, then it ought not be thrown out. >For example, there's a pernicious myth that exiting (or returning) from >the middle of a loop is bad, and that the only proper way to write a >loop is to state the termination condition explicitly, as a predicate >appearing at the top of the loop. Yes. That pernicious myth is called "structured programming". >This theory was indeed put to the test, and guess what? Programmers >using a test-and-exit from the middle of the loop produced fewer errors >than those programmers who tried to put the test at the top of the loop. >Cognitive Strategies and Looping Constructs: An Empirical Study >Soloway, Bonar, Ehrlich >CACM, Nov 83, Vol 26, No 11, p 853-860 Do you know if the citing is on line? Was the experiment controlled? Did the experiment measure long term cost? Were the participants engineers who had been used to min-loop exits, and were strugging with a new concept? My own experience is counter to the results of this study. It is far easier to understand a loop if the looping criteria are present in one place; and the loop has a single, well known, exit. >The researchers found that the exit-from-the-middle construct had a >better "cognitive fit" than the other constructs. "Cognitive fit" is probably not a very good criterion for good engineering. GOTO has a very good cognitive fit. So does a flat Earth. >The goodness of a language construct should not be determined by >doctrinaire computer scientists or mathematicians. The only thing that >matters is whether working programmers think it's easier to understand, >and whether by using the construct programmers inject fewer errors into >the code. And whether or not the construct is maintainable over the long term. There are lots of constructs that make writing the initial program easy, but make maintaining it hard. The practice of using such constructs, i.e. ignoring long term effects, is sometimes called "hacking". > >I think it was Stroustrup who said, "Programming is a human activity. Forget that, and all is lost." Precisely! Programming is an activity of human creativity and human frailty. Forget either part, and all is lost. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Robert Martin @ 1998-08-30 0:00 ` Charles Hixson 1998-08-31 0:00 ` Robert I. Eachus 1998-08-31 0:00 ` dennison ` (6 subsequent siblings) 7 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-08-30 0:00 UTC (permalink / raw) In my experience it is USUALLY a bad idea to exit from the middle of a loop. It is USUALLY a bad idea not to place the loop continuation test at the start. But there are many exceptions. There are many loops that require either a very complex initial test, or multiple tests, e.g. (psuedo-code) if (str (0) != ';') { while (len (str) < 0) { select (str (0) ) { case 'A'..'Z': .... exit; case 'a'..'z': -- do something else -- chop off head of string case '0'..'8': -- do something else -- chop off head of string case '9': -- do something else -- set loop exit flag -- chop off head of string otherwise: -- reset loop exit flag } -- do some stuff when (exitFlag and lastChar != '9') exit; } } Now maybe this is what was meant by a "state-machine", as when this kind of construct comes up I do think of goto's, which WOULD make writing the code easier. I just don't think that they would make understaning it easier. On the other hand, the test that one would need to emplace to put all exit tests at the beginning of the loop is apalling, and I don't think that a calculating a compound boolean flag, together with the internal if tests to skip over code that isn't to be executed in this pass, improves things. Personally, I try to avoid this situation, but sometimes I just can't ("Parse this list of mailing labels that different people have created in different systems using different software. We can get it into csv form, and within each list the fields will usually be in the same order, and they won't interpolate new field very often. Oh, yes, sometimes people used their mailing list to attach notes to themselves about the company being mailed to. Could you save those separately.") When this comes up, the idea of NOT being able to exit a processing loop would be apalling. Sometimes I end up just throwing the entire label into comments (even after looking at it). Once in awhile I'll discard it (after looking at it). But I've GOT to be able to handle data with any type-compliant degree of variation. And sometimes that means exiting from deeply imbedded loops. Robert Martin wrote: > > Matthew Heaney wrote in message ... > > >If theory says use a construct, but observation reveals that programmers > >who use the construct produce more errors, then the theory needs to be > >thrown out ... > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Charles Hixson @ 1998-08-31 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-08-31 0:00 UTC (permalink / raw) In article <35E9C0CD.D225D1F8@earthlink.net> Charles Hixson <charleshixsn@earthlink.net> writes: > Now maybe this is what was meant by a "state-machine", as when this kind > of construct comes up I do think of goto's, which WOULD make writing the > code easier. I just don't think that they would make understaning it > easier. Yes, that is a state machine, and there are tools for making them more understandable. But if you try to implement one, even that simple, in a language which doesn't allow gotos or the equivalent, you have my sympathy. (In the example, multiple loop exits were used as a restricted form of goto. If you do use a goto, you should use the most restricted form that will do the job. Good languages have several available, including a general purpose form. In Ada the goto has a few potentially irksome restrictions (you can't use a goto from one branch of a case statement to another, or out of a subprogram), but I have never seen a situation where the limits affected a real program. (In fact, the most irksome part is probably the necessary compile-time structures and tests for legality.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Robert Martin 1998-08-30 0:00 ` Charles Hixson @ 1998-08-31 0:00 ` dennison 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Andrew Reilly [not found] ` <35f51e53.48044143@news.erols.c <m3af4mq7f4.fsf@mheaney.ni.net> ` (5 subsequent siblings) 7 siblings, 2 replies; 510+ messages in thread From: dennison @ 1998-08-31 0:00 UTC (permalink / raw) In article <6sbuod$fra$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Matthew Heaney wrote in message ... > > >This theory was indeed put to the test, and guess what? Programmers > >using a test-and-exit from the middle of the loop produced fewer errors > >than those programmers who tried to put the test at the top of the loop. ... > >The goodness of a language construct should not be determined by > >doctrinaire computer scientists or mathematicians. The only thing that > >matters is whether working programmers think it's easier to understand, > >and whether by using the construct programmers inject fewer errors into > >the code. > > And whether or not the construct is maintainable over the long term. There > are lots of constructs that make writing the initial program easy, but make > maintaining it hard. The practice of using such constructs, i.e. ignoring > long term effects, is sometimes called "hacking". I gave up mangling my code to make while loops years ago for just the reason Matthew spoke of. Occasionally when I make a middle-exited loop I will try to make a while loop out of it, but I almost always delete the code and go back to the middle-exited loop. If an algorithm really is a middle-exited loop, you just confuse things (thereby making the code harder to understand) by tring to force a different structure on it. For me, the extra code is a prime source of errors as well. Continuing with my example of a naturally middle-exited loop, there are really only two ways of "whileing" it. The first is to "unroll" one half of an iteration (up to the test). The problem with that is now you have duplicated code. In practice I find the odds of having to change that code and forgetting to change it both places is distressingly high. The other option is to create a flag of some sort, and check it every loop iteration. That's even worse because I have increased the (McCabe) complexity of the code to a rather non-obvious end. If I have to add code to the loop, even I the author have to think hard about where it goes now. Also, getting the logic on a flag reversed is one of my most common errors. I never seem to fail to do that one if given a chance. In fact I just fixed one of those yesterday. Additionally, there is the run-time issue. You are adding a check into every iteration of the loop that will go one way nearly every time. Sometimes that can get optimized out, but I wouldn't count on it. I will admit that a naturally top-exited loop written with a top-eixted loop construct is easier to understand than a naturally middle-exited loop written with a middle-exited loop construct. But that does *not* mean that the naturally middle-exited loop would have been easier to understand if twisted to use the top-exited construct too. As always, YMMV. -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` dennison @ 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Andrew Reilly 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) dennison@telepath.com wrote in message <6sebjr$b69$1@nnrp1.dejanews.com>... >In article <6sbuod$fra$1@hirame.wwa.com>, >The other option is to create a flag of some sort, and check it every loop >iteration. That's even worse because I have increased the (McCabe) complexity >of the code to a rather non-obvious end. Personally, I don't consider that to be a valid engineering criterion. The true complexity of the code has not increased; and the job of maintaining the code is simpler. >If I have to add code to the loop, >even I the author have to think hard about where it goes now. I'm not sure what you are trying to say here. Don't you always have to think hard about where your code goes? Why does the flag make it harder? Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-06 0:00 ` Charles Hixson 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >If I have to add code to the loop, > >even I the author have to think hard about where it goes now. > > I'm not sure what you are trying to say here. Don't you always have to > think hard about where your code goes? Why does the flag make it harder? The flag makes it _much_ harder, because it doubles the number of rules in the decision table. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Matthew Heaney wrote: > ... > The flag makes it _much_ harder, because it doubles the number of rules > in the decision table. Is THAT why! O. I knew that it made the code more difficult to understand, but I hadn't ever connected it with a decision table. And someone said earlier that adding an internal if-branch added an edge to the directed-graph (?), so I guess that if you use an if test on a flag to get around executing part of the code on the first/last pass, then you are adding both complexities (or are they different ways of saying the same thing? But somehow pulling chunks of code into a function and then calling that function makes things simpler, even though the flow of execution follows the same path, so something else is going on here. I tend to think that one of the major activities of programming is properly "chunking" the problem into pieces that have low-bandwidth connections with the rest of the code. This is what made the FORTRAN COMMON blocks such a bad idea, they didn't cut down the bandwidth. There is, of course, more to it than that. Anonymous blocks that occur in the middle of code may actually be isolated in just the manner that a called routine would be, but they aren't "visually isolated" and this makes it difficult to model them as isolated chunks. As a result of this analysis, I feel that Java's Anonymous inner class construct is a very bad idea. On the other hand, a named internal class would be a good idea. It could even have exactly the same meaning (including even [ugh!] read/write access to internal class variables). But if it were declared in a visually separated location (c.f., Pascal's internal functions), then it would be an means of helping the chunking. Personally, I think that if this were to be implemented, there should be, say, a "sealed internal class" that didn't have access to the internal class variables of the class that contained it. This would help improve the isolation. But almost all of the effect of this can be obtained by just not declaring the class as internal. I just feel that a tightly coupled class that doesn't really have any use outside the context of another class should be declared internal to that class (Ada can manage this by appropriate use of Private, but, to me, it's a rather tricky thing to handle this properly [I'm not sure if one can completely declare a class within the code body of an Ada file, and if you did, I think that it would have full access to the locally declared variables, thus expanding the bandwidth of the interface]). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` Matthew Heaney 0 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-06 0:00 UTC (permalink / raw) Charles Hixson <charleshixsn@earthlink.net> writes: > I just feel that a tightly coupled class that doesn't really have any > use outside the context of another class should be declared internal > to that class... Yes. > ... (Ada can manage this by appropriate use of Private, but, to me, > it's a rather tricky thing to handle this properly [I'm not sure if > one can completely declare a class within the code body of an Ada > file, and if you did, I think that it would have full access to the > locally declared variables, thus expanding the bandwidth of the > interface]). I don't understand what you think is "tricky" about declaring one type in the same module as another: package P is type T is private; ... private type U is ...; type T is record O : U; ... end record; end P; Do you object to T being able to see the representation of U? Then just make U private: private package Q is type U is private; ... private type U is ...; end Q; type T is record O : U; ... end record; end P; Do you not like that U can see the representation of T? Then make T's representation type private: private type U is ...; package Q is type T_Rep is private; ... private type T_Rep is ...; end Q; type T is new Q.T_Rep; end P; There's nothing hard or tricky going on here. Just normal scope rules. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` dennison 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Andrew Reilly 1998-09-01 0:00 ` dennison ` (2 more replies) 1 sibling, 3 replies; 510+ messages in thread From: Andrew Reilly @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sebjr$b69$1@nnrp1.dejanews.com>, dennison@telepath.com writes: > I gave up mangling my code to make while loops years ago for just the reason > Matthew spoke of. Occasionally when I make a middle-exited loop I will try to > make a while loop out of it, but I almost always delete the code and go back > to the middle-exited loop. If an algorithm really is a middle-exited loop, > you just confuse things (thereby making the code harder to understand) by > tring to force a different structure on it. For me, the extra code is a prime > source of errors as well. Just out of interest, (and loop constructs are a significant interest to me), what field of human endeavour do you find yourself supporting (coding for) that frequently requires middle-exit loops? I mostly do numerics, and find myself wanting something much simpler than the current styles, with a simple integer iteration count. A bit like the old Fortran do loops. Even having to name and declare a loop variable is overhead (semantic baggage) I'd avoid if I could. -- Andrew Reilly Reilly@zeta.org.au ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Andrew Reilly @ 1998-09-01 0:00 ` dennison 1998-09-01 0:00 ` dewarr 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: dennison @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sff74$q0s@gurney.reilly.home>, reilly@zeta.org.au wrote: > In article <6sebjr$b69$1@nnrp1.dejanews.com>, > dennison@telepath.com writes: > > to the middle-exited loop. If an algorithm really is a middle-exited loop, > > you just confuse things (thereby making the code harder to understand) by > > tring to force a different structure on it. For me, the extra code is a prime > > source of errors as well. > > Just out of interest, (and loop constructs are a significant > interest to me), what field of human endeavour do you find > yourself supporting (coding for) that frequently requires > middle-exit loops? Well, I'll go through the middle-exited loops on code I'm working on now... 4 Parsing loops 2 Sorting loops 2 Searching loops 1 Token analysis loop 1 Error handling 2 lexicagraphical comparison loops 1 lexicagraphical incrementer > I mostly do numerics, and find myself wanting something much simpler > than the current styles, with a simple integer iteration count. > A bit like the old Fortran do loops. Even having to name and > declare a loop variable is overhead (semantic baggage) I'd avoid > if I could. I suppose that would be useful if you wanted a "repeat the following code 1051 times" loop. But its very rare I need to do something like that w/o also needing to use the iteration count as an index. In fact, if its really simple, a lot of times you can write it as one array assignment operation in Ada. For instance, the insertion operation in one of my sorting loops is: Rows(1..Sortee) := Rows(1..Sorted-1) & Rows(Sortee) & Rows(Sorted..Sortee-1); -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Andrew Reilly 1998-09-01 0:00 ` dennison @ 1998-09-01 0:00 ` dewarr 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sff74$q0s@gurney.reilly.home>, reilly@zeta.org.au wrote: > In article <6sebjr$b69$1@nnrp1.dejanews.com>, > dennison@telepath.com writes: > > I gave up mangling my code to make while loops years ago for just the reason > > Matthew spoke of. Occasionally when I make a middle-exited loop I will try to > > make a while loop out of it, but I almost always delete the code and go back > > to the middle-exited loop. If an algorithm really is a middle-exited loop, > > you just confuse things (thereby making the code harder to understand) by > > tring to force a different structure on it. For me, the extra code is a prime > > source of errors as well. > > Just out of interest, (and loop constructs are a significant > interest to me), what field of human endeavour do you find > yourself supporting (coding for) that frequently requires > middle-exit loops? > > I mostly do numerics, and find myself wanting something much simpler > than the current styles, with a simple integer iteration count. > A bit like the old Fortran do loops. Even having to name and > declare a loop variable is overhead (semantic baggage) I'd avoid > if I could. > > -- > Andrew Reilly Reilly@zeta.org.au > Something like for J in 1 .. 10 loop A (J) := 0; end loop; The above is standard Ada code, it declares J as a local constant in the loop, preventing its use outside the loop, or its modification within the loop. Robert Dewar -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Andrew Reilly 1998-09-01 0:00 ` dennison 1998-09-01 0:00 ` dewarr @ 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) reilly@zeta.org.au (Andrew Reilly) writes: > I mostly do numerics, and find myself wanting something much simpler > than the current styles, with a simple integer iteration count. > A bit like the old Fortran do loops. Even having to name and > declare a loop variable is overhead (semantic baggage) I'd avoid > if I could. Then Ada's your language! Although you have to name a loop variable (in a for loop), you don't have to acually declare it via a type declaration. For example, to iterate over an array, you do this A : Integer_Array; begin ... for Index in A'Range loop ... A (Index) ... This works even for the case of an array whose length is zero. In the stack example, I showed how to iterate over a portion of the array: for Index in Positive range 1 .. L.Top loop if L.Items (Index) /= R.Items (Index) then ... There are other features of Ada95 (the Numerics annex, for example, and being able to call existing Fortran code) that would appeal to a Fortran guy. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@news.erols.c <m3af4mq7f4.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@news.erols.c <m3af4mq7f4.fsf@mheaney.ni.net> @ 1998-08-31 0:00 ` Patrick Doyle 1998-08-31 0:00 ` Gene Gajewski ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Patrick Doyle @ 1998-08-31 0:00 UTC (permalink / raw) In article <m3af4mq7f4.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > >I can almost live that. The real problem, however, is that using an >extra flag to terminate VASTLY complicates the predicate. In fact, the >flag doubles the number of states I have to think about when mentally >evaluating the predicate! That's the real source of the loop >termination errors. Doubles the number of states, compared to what? The *only* difference is that the exit-in-the-middle code has one of the exit conditions hidden inside the loop, instead of being stated explicitly at the top or bottom. Exit-in-the-middle is not inherently simpler, as you seem to suggest, or else it would be a different algorithm. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Patrick Doyle @ 1998-08-31 0:00 ` Gene Gajewski 1998-08-31 0:00 ` Richard D Riehle 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: Gene Gajewski @ 1998-08-31 0:00 UTC (permalink / raw) Patrick Doyle wrote in message ... <snip> >Doubles the number of states, compared to what? The *only* difference >is that the exit-in-the-middle code has one of the exit conditions >hidden inside the loop, instead of being stated explicitly at the >top or bottom. Each time you enter a block of code, you carry forward all the assumptions (exit conditions) of that block, and any of those it is nested in. All of these, assumptions or exit conditions must be held in mind in observance as the code is created. Reducing the number of assumptions, or predicates as some like to call them, allows a cleaner process thought process. It is not coducive to analysis by exit points. Analysis by predicates requires that you actually follow the code. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Patrick Doyle 1998-08-31 0:00 ` Gene Gajewski @ 1998-08-31 0:00 ` Richard D Riehle 1998-09-01 0:00 ` Simon Wright 1998-09-02 0:00 ` adam 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 2 replies; 510+ messages in thread From: Richard D Riehle @ 1998-08-31 0:00 UTC (permalink / raw) >In article <m3af4mq7f4.fsf@mheaney.ni.net>, >Matthew Heaney <matthew_heaney@acm.org> wrote: >> >>I can almost live that. The real problem, however, is that using an >>extra flag to terminate VASTLY complicates the predicate. In fact, the >>flag doubles the number of states I have to think about when mentally >>evaluating the predicate! That's the real source of the loop >>termination errors. I recall a bunch of IV&V people coming to review a project a few years ago. They were the typical doctrinaire, fresh-out-of-school youngsters who one expects to find assigned by the big consulting companies, trained to look for "checkbox" violations rather than to think about the software process. One enthusiastic fellow began to insist that programmers remove all the exits from their loops -- convert them into while or for loops. It seems to me that the people who make up rules for programmers are people who either no long write real programs or never have written production code. The debate about exits within loops seems silly, particularly when talking about Ada. Nobody writes exits in Ada code unless the loop has a label, and the compiler tests to see if the exit contains the label of the loop as well as checking that the named loop has an "end label." This makes maintenance very easy. An exit is not another form of sphagetti code anymore than a return from within a procedure or function. In many algorithms there are perfectly good reasons for interrupting a flow of control early. Putting on a dogamtic face to deny that will simply result in more incomprehensible code. The talk about spaghetti code is colorful but unproductive. By this analogy, perhaps we should call the modular code, "ravioli code." Now we have this little plate of raviolis, each representing a software module. Oh, and then we could thread them together with one long strand of spaghetti. Yes, I do know what that implies. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Richard D Riehle @ 1998-09-01 0:00 ` Simon Wright 1998-09-02 0:00 ` adam 1 sibling, 0 replies; 510+ messages in thread From: Simon Wright @ 1998-09-01 0:00 UTC (permalink / raw) Richard D Riehle <laoXhai@ix.netcom.com> writes: > Nobody writes exits in Ada code unless the loop has a > label, and the compiler tests to see if the exit contains the label of the > loop as well as checking that the named loop has an "end label." This makes > maintenance very easy. ::blush:: I think I'd better revisit the coding standards. -- Simon Wright Work Email: simon.j.wright@gecm.com GEC-Marconi Radar & Defence Systems Voice: +44(0)1705-701778 Command & Information Systems Division FAX: +44(0)1705-701800 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Richard D Riehle 1998-09-01 0:00 ` Simon Wright @ 1998-09-02 0:00 ` adam 1 sibling, 0 replies; 510+ messages in thread From: adam @ 1998-09-02 0:00 UTC (permalink / raw) In article <6set0b$oa@sjx-ixn3.ix.netcom.com>, Richard D Riehle <laoXhai@ix.netcom.com> wrote: > The talk about spaghetti code is colorful but unproductive. By this > analogy, perhaps we should call the modular code, "ravioli code." > Now we have this little plate of raviolis, each representing a software > module. Oh, and then we could thread them together with one long strand of > spaghetti. Yes, I do know what that implies. Actually, I like this metaphor. Ravoili has all this good stuff hidden inside the pasta where you can't see it, which fits nicely with the "black box" theory of programming, in which the parts of the program outside the module can see just the parts of the module that it needs to see, i.e. the pasta part, while it doesn't have to know anything about the inside part except that it tastes good when you bite into it. However, there aren't any holes in ravioli, which makes it hard to thread them together with spaghetti. Therefore, I'd like to suggest an alternative metaphor, mostaccioli code, which I think also fits nicely. Mostaccioli comes in nice firm parts, so that it can't wind up all around itself the way spaghetti code can. Also, mostaccioli has one entry hole and one exit hole, suggesting the desirability of writing code with a single entry point and a single exit point, as well as providing a way for a lot of mostaccioli to be strung together on a piece of spaghetti (although I have never tried to cook it this way). Macaroni also has one entry hole and one exit hole, but mostaccioli is nice and straight, suggesting straightforward code that's easy to understand, while macaroni tends to be bent, except for those little salad macaroni things, which might be a good metaphor for a very short one-line procedure. My motivation here is, of course, to make sure all the other forms of pasta don't feel left out of the discussion. I'm working on figuring out appropriate meanings for "rotelle code", "lasagne code", and "farfalle code", and will follow up when I figure out something good. But I have to quit now, because I'm hungry. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Patrick Doyle 1998-08-31 0:00 ` Gene Gajewski 1998-08-31 0:00 ` Richard D Riehle @ 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) doylep@ecf.toronto.edu (Patrick Doyle) writes: > Doubles the number of states, compared to what? The *only* difference > is that the exit-in-the-middle code has one of the exit conditions > hidden inside the loop, instead of being stated explicitly at the > top or bottom. > > Exit-in-the-middle is not inherently simpler, as you seem to suggest, > or else it would be a different algorithm. Disagree. A decision table for the original solution has only 2 rules (columns). 1 2 Iterating Y N --------------- A decision table for the "improved" solution has 4 rules: 1 2 3 4 Iterating Y Y N N Equal Y N Y N --------------------- This is why I say the number of states to consider is doubled by the addition of a flag into the predicate. The decision table has twice as many rules. So I really would say that the exit-in-the-middle solution is inherently simpler. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4.fsf@mheaney.ni.net> @ 1998-08-31 0:00 ` Andrew Hussey 1998-08-31 0:00 ` Mattias Lundstr�m ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Andrew Hussey @ 1998-08-31 0:00 UTC (permalink / raw) In <m3af4mq7f4.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes: >I can almost live that. The real problem, however, is that using an >extra flag to terminate VASTLY complicates the predicate. In fact, the >flag doubles the number of states I have to think about when mentally >evaluating the predicate! That's the real source of the loop >termination errors. >(I shouldn't have to remind anyone, but just in case: George Miller did >a famous study about human cognitive limits, and found that people can >remember about 7 things, plus or minus 2. That's why complex predicates >make a programmer's head spin, and why he often gets loop termination >wrong.) >Using an exit from the middle avoids the headaches (literally) >engendered by using an extra flag in the predicate. When you want to >exit, you just say that you want to exit, directly. No mental >gymnastics are required in order to determine whether you'll "really" >exit, as would be the case using the flag approach. That's brilliant, now your code is much easier to write! Now let's see who has an easier time *testing* their code. I think you'll find the control-flow errors you introduce in the spaghetti you produce will more than make up for any gain you have from rapid coding. A. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Andrew Hussey @ 1998-08-31 0:00 ` Mattias Lundstr�m 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Tim Ottinger 1998-08-31 0:00 ` Matthew Heaney 1998-09-01 0:00 ` dewarr 2 siblings, 2 replies; 510+ messages in thread From: Mattias Lundstr�m @ 1998-08-31 0:00 UTC (permalink / raw) Andrew Hussey wrote: > > In <m3af4mq7f4.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes: > >Using an exit from the middle avoids the headaches (literally) > >engendered by using an extra flag in the predicate. When you want to > >exit, you just say that you want to exit, directly. No mental > >gymnastics are required in order to determine whether you'll "really" > >exit, as would be the case using the flag approach. > > That's brilliant, now your code is much easier to write! > Now let's see who has an easier time *testing* their code. > I think you'll find the control-flow errors you introduce > in the spaghetti you produce will more than make up for > any gain you have from rapid coding. I just have to butt in here. Why would this code become harder to test? If we take a simple example (more or less C++) 1. Flag solution while( ... && retval == OK ) { ... if( ... ) retval = NOT_OK; } return retval; vs 2. Multiple exits while( ... ) { ... if( ... ) return NOT_OK; } return OK; the control flow is basically the same (the same number of paths functionally identical) so the number and nature of tests that are needed have not been affected. Personally I prefer the second version in many cases since I believe it is normally easier to write as well as understand. (Specifically the exceptional exits are handled in this way (with return codes) in our projects). (Ie The maintenance argument - that the second code version becomes harder to read and understand (and thus maintain) - since the return statement may well not be obvious if there is a lot of other code within the loop. I do not agree with this, but it is certainly an argument worth considering. IMHO This should be covered by good comments where applicable.) - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Mattias Lundstr�m @ 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Robert I. Eachus ` (2 more replies) 1998-09-01 0:00 ` Tim Ottinger 1 sibling, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 2353 bytes --] Mattias Lundstr�m wrote in message <35EAB5B1.1DA1986B@ehpt.com>... 1. Flag solution while( ... && retval == OK ) { ... if( ... ) retval = NOT_OK; } return retval; vs 2. Multiple exits while( ... ) { ... if( ... ) return NOT_OK; } return OK; >(Ie The maintenance argument - that the second code version >becomes harder to read and understand (and thus maintain) - >since the return statement may well not be obvious if there >is a lot of other code within the loop. I do not agree >with this, but it is certainly an argument worth considering. >IMHO This should be covered by good comments where applicable.) It's not so much a matter of being harder to read and understand. Rather it is that there is no good place to make certain kinds of changes to the code. For example, let's say that we had to make a change that forced us to open and close a file that the body of the loop needed to read. Then: 1. Flag solution File* f = fopen(...); while( ... && retval == OK ) { ... if( ... ) retval = NOT_OK; } fclose(f); return retval; vs 2. Multiple exits File* f = fopen(...); while( ... ) { ... if( ... ){ fclose(f); return NOT_OK; } } fclose(f); return OK; Clearly solution 1 is easier to deal with than solution 2. Solution 1 implies that there will be one, and only one, fclose in the function. Whereas solution 2 implies that there will be as many fcloses as there are early returns. And that new fcloses will have to be added if new returns are added. Thus the maintainer must *remember* to add an fclose every time he adds a new return; *and* he must remember to check every return if he adds something else like a fopen/fclose pair in the function (e.g. a malloc/free, a sieze/release, a lock/unlock, etc). So, to reiterate, reading and understanding are not the sole issue. Producing code that is easy to maintain is more to the point. It is quite feasible to have code that you understand perfectly well, but is very hard to maintain. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Robert I. Eachus 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Richard Jones 1998-09-01 0:00 ` Mattias Lundstr�m 2 siblings, 2 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-08-31 0:00 UTC (permalink / raw) In article <6sf1dn$n52$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: > It's not so much a matter of being harder to read and understand. Rather it > is that there is no good place to make certain kinds of changes to the code. > For example, let's say that we had to make a change that forced us to open > and close a file that the body of the loop needed to read... This is why T-shirts were printed up at one of the Ada 9X Requirements Workshops that said: "We don't know what the problem is... ...but Finalization is the solution." Finalization did end up in Ada 95, and it is the right solution to this particular problem. If you want the file to be closed when all references go away, it is easy enough to put the code in one place, and write: (elsewhere): type File_Handle is new Controlled with private... Now you can say: procedure ... is FH: File_Handle; begin ... end ...; And be sure that the file will be closed if necessary, but only when the file is open and no other reference to it exists. Of course, no one does this, because most compiler vendors "do the right thing" for the standard I/O packages. (This wasn't always the case.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert I. Eachus @ 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Robert I. Eachus wrote in message ... > > Finalization did end up in Ada 95, and it is the right solution to >this particular problem. I am not sure of the semantics of 'finalization' in ADA9X, but if it works like Java's, then it does not solve the problem created by multiple exits from loops. Again, the issue is structure. When a single-entry/single-exit model is followed, the code attains a structure that is conducive to resource management. Consider: (C++ with a finally clause (which I wish it had!)) int f() { char* p = 0; File* f = 0; try{ p = malloc(80); if (!p) return 1; f = fopen("myFile", "r"); if (!f) return 2; fread(f, p, 80); ... return 0; } finally{ if (f) fclose(f); if (p) free(p); } } The problem with this is the tests in the finally clause. Those tests are an artifact due to loss of structure. They take time, space, and are not general (i.e. there might be no reasonable test to perform!) On the other hand: int f() { int retval = 0; if (char* p = malloc(80)) { if (File* f = fopen("myFile", "r"); { fread(f, p, 80); ... fclose(f); } else // fopen failure { retval = 2; } free(p); } else // malloc failure { retval = 1; } return retval; } No tests necessary, structure preserved. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Stephen Leake 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > > Finalization did end up in Ada 95, and it is the right solution to > >this particular problem. > > I am not sure of the semantics of 'finalization' in ADA9X, but if it works > like Java's, then it does not solve the problem created by multiple exits > from loops. "Finalization" in Ada95 is equivalent to having a constructor and deconstructor for an object. If a file (or mutex) is controlled - which just means it has a deconstructor - then the file (mutex) will be automatically closed (released) when the subprogram terminates. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` Stephen Leake 1998-09-01 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Stephen Leake @ 1998-09-01 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > "Robert Martin" <rmartin@oma.com> writes: > > > > Finalization did end up in Ada 95, and it is the right solution to > > >this particular problem. > > > > I am not sure of the semantics of 'finalization' in ADA9X, but if it works > > like Java's, then it does not solve the problem created by multiple exits > > from loops. > > "Finalization" in Ada95 is equivalent to having a constructor and > deconstructor for an object. > > If a file (or mutex) is controlled - which just means it has a > deconstructor - then the file (mutex) will be automatically closed > (released) when the subprogram terminates. In addition, Ada Finalization happens immediately when the object goes out of scope; Java finalization happens when the garbage collector gets around to freeing the object's memory. This means Java finalization is NOT a solution to the resource issue (seize/release, open/close, etc), but Ada Finalization is. -- Stephe ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Stephen Leake @ 1998-09-01 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Stephen Leake wrote in message ... Java finalization happens when the garbage collector >gets around to freeing the object's memory. This means Java >finalization is NOT a solution to the resource issue (seize/release, >open/close, etc. True. But the 'finally' clause in Java *is*. That was what the example was showing. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert I. Eachus 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) eachus@spectre.mitre.org (Robert I. Eachus) writes: > Finalization did end up in Ada 95, and it is the right solution to > this particular problem. If you want the file to be closed when all > references go away, it is easy enough to put the code in one place, > and write: > > (elsewhere): > > type File_Handle is new Controlled with private... > > Now you can say: > > procedure ... is > FH: File_Handle; > begin > ... > end ...; > > And be sure that the file will be closed if necessary, but only when > the file is open and no other reference to it exists. > > Of course, no one does this, because most compiler vendors "do the > right thing" for the standard I/O packages. (This wasn't always the > case.) I made a similar suggestion wrt the use of a semaphore. I guess great minds think alike, eh, Bob? Matt ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Robert I. Eachus @ 1998-09-01 0:00 ` Richard Jones 1998-09-02 0:00 ` Mattias Lundstr�m ` (3 more replies) 1998-09-01 0:00 ` Mattias Lundstr�m 2 siblings, 4 replies; 510+ messages in thread From: Richard Jones @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin <rmartin@oma.com> wrote: > Mattias Lundstr�m wrote in message <35EAB5B1.1DA1986B@ehpt.com>... > It's not so much a matter of being harder to read and understand. Rather it > is that there is no good place to make certain kinds of changes to the code. > For example, let's say that we had to make a change that forced us to open > and close a file that the body of the loop needed to read. Then: > 1. Flag solution > File* f = fopen(...); > while( ... && retval == OK ) { > ... > if( ... ) > retval = NOT_OK; > } > fclose(f); > return retval; > vs > 2. Multiple exits > File* f = fopen(...); > while( ... ) { > ... > if( ... ){ > fclose(f); > return NOT_OK; > } > } > fclose(f); > return OK; Both of you miss the point that exceptions solve this problem neatly and naturally, i.e. in some sort of bastardized Java/C++ hybrid you might write: File f ("name", File::OpenReadOnly); while (...) { if (error_condition) throw new ErrorException; } return; Rich. -- Richard Jones rjones@orchestream.com Tel: +44 171 598 7557 Fax: 460 4461 Orchestream Ltd. 125 Old Brompton Rd. London SW7 3RP PGP: www.four11.com "boredom ... one of the most overrated emotions ... the sky is made of bubbles ..." Original message content Copyright � 1998 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Jones @ 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m ` (2 subsequent siblings) 3 siblings, 0 replies; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Richard Jones wrote: > Both of you miss the point that exceptions solve this problem > neatly and naturally, i.e. in some sort of bastardized > Java/C++ hybrid you might write: > > File f ("name", File::OpenReadOnly); > while (...) { > > if (error_condition) throw new ErrorException; > } > return; > > Rich. Not so. This is equivalent (if only function scope is considered here): File f ("name", File::OpenReadOnly); while (...) { if (error_condition) return NOT_OK; } return OK; which depends on the File object to do the cleanup in its destructor. This is one way to solve the problem, but it has nothing to do with the whole exception vs return code discussion. Note also that in the case of Java this kind of resource cleanup may not be satisfactory since we can not know when the finalization (cleanup) is actually done. - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Jones 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 3 siblings, 0 replies; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Richard Jones wrote: > Both of you miss the point that exceptions solve this problem > neatly and naturally, i.e. in some sort of bastardized > Java/C++ hybrid you might write: > > File f ("name", File::OpenReadOnly); > while (...) { > > if (error_condition) throw new ErrorException; > } > return; > > Rich. Not so. This is equivalent (if only function scope is considered here): File f ("name", File::OpenReadOnly); while (...) { if (error_condition) return NOT_OK; } return OK; which depends on the File object to do the cleanup in its destructor. This is one way to solve the problem, but it has nothing to do with the whole exception vs return code discussion. Note also that in the case of Java this kind of resource cleanup may not be satisfactory since we can not know when the finalization (cleanup) is actually done. - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Jones 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 3 siblings, 0 replies; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Richard Jones wrote: > Both of you miss the point that exceptions solve this problem > neatly and naturally, i.e. in some sort of bastardized > Java/C++ hybrid you might write: > > File f ("name", File::OpenReadOnly); > while (...) { > > if (error_condition) throw new ErrorException; > } > return; > > Rich. Not so. This is equivalent (if only function scope is considered here): File f ("name", File::OpenReadOnly); while (...) { if (error_condition) return NOT_OK; } return OK; which depends on the File object to do the cleanup in its destructor. This is one way to solve the problem, but it has nothing to do with the whole exception vs return code discussion. Note also that in the case of Java this kind of resource cleanup may not be satisfactory since we can not know when the finalization (cleanup) is actually done. - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Jones ` (2 preceding siblings ...) 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Patrick Logan 3 siblings, 1 reply; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Richard Jones wrote: > Both of you miss the point that exceptions solve this problem > neatly and naturally, i.e. in some sort of bastardized > Java/C++ hybrid you might write: > > File f ("name", File::OpenReadOnly); > while (...) { > > if (error_condition) throw new ErrorException; > } > return; > > Rich. Not so. This is equivalent (if only function scope is considered here): File f ("name", File::OpenReadOnly); while (...) { if (error_condition) return NOT_OK; } return OK; which depends on the File object to do the cleanup in its destructor. This is one way to solve the problem, but it has nothing to do with the whole exception vs return code discussion. Note also that in the case of Java this kind of resource cleanup may not be satisfactory since we can not know when the finalization (cleanup) is actually done. - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-02 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain; charset=US-ASCII, Size: 619 bytes --] In comp.object Mattias Lundstr�m <ehsmalu@ehpt.com> wrote: : Note also that in the case of Java this kind of resource : cleanup may not be satisfactory since we can not know when : the finalization (cleanup) is actually done. In Java you should always explicitly handle resource deallocation for all resources that are in any way "precious". Use... try {} finally { deallocation } to ensure that deallocation will occur no later than the exit of the "try" body. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan @ 1998-09-02 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1084 bytes --] Patrick Logan wrote in message ... >In comp.object Mattias Lundstr�m <ehsmalu@ehpt.com> wrote: > >: Note also that in the case of Java this kind of resource >: cleanup may not be satisfactory since we can not know when >: the finalization (cleanup) is actually done. > >In Java you should always explicitly handle resource deallocation for >all resources that are in any way "precious". Use... > > try {} finally { deallocation } > >to ensure that deallocation will occur no later than the exit of the >"try" body. And, in C++, because destructors are not in the scope of the try block, I prefer: try {...; cleanup();} catch(...){cleanup(); throw;} Rather than trying to use destructors as a general solution. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Robert I. Eachus 1998-09-01 0:00 ` Richard Jones @ 1998-09-01 0:00 ` Mattias Lundstr�m 1998-09-01 0:00 ` Robert Martin 2 siblings, 1 reply; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > > Mattias Lundstr�m wrote in message <35EAB5B1.1DA1986B@ehpt.com>... > >(Ie The maintenance argument - that the second code version > >becomes harder to read and understand (and thus maintain) - > >since the return statement may well not be obvious if there > >is a lot of other code within the loop. I do not agree > >with this, but it is certainly an argument worth considering. > >IMHO This should be covered by good comments where applicable.) > > It's not so much a matter of being harder to read and understand. Rather it > is that there is no good place to make certain kinds of changes to the code. Ok. I admit. I overlooked this argument... > > For example, let's say that we had to make a change that forced us to open > and close a file that the body of the loop needed to read. Then: > 2. Multiple exits > File* f = fopen(...); > while( ... ) { > ... > if( ... ){ > fclose(f); > return NOT_OK; > } > } > fclose(f); > return OK; Obviously you should NOT write code like this (for the reasons you state). If the needs for cleanup continue to grow this will become unmanageble very quickly. Especially if we have a lot of exits where we need to duplicate code. If you need cleanup before leaving the function you would need to change the original loop layout. Perhaps to: File* f = fopen(...); while( ... ) { ... if( ... ){ retval = NOT_OK; goto leave_loop; } } leave_loop: fclose(f); return retval; where I have used goto instead of break mostly to annoy ;-) I still think that a multi-exit solution like this is better then juggling flags in many cases. (Question: Is this still a multi-exit according to your defintions. It clearly is is you choose to analyse the control flow and see the goto as not a part of the loop predicate.) In this case it would be more elegant to instead use a file class that automatically closes the file when going out of scope, but this may be infeasible in some general cases. Eg A. We are using a GC language and can not know when the object will be cleaned up. B. There may be a need for error handling in the cleanup part of the code. We do NOT want to throw exceptions from the destructors. > Clearly solution 1 is easier to deal with than solution 2. Solution 1 In fact this change almost demands for the rewrite of solution 2. - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Mattias Lundstr�m @ 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Robert I. Eachus ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 3243 bytes --] Mattias Lundstr�m wrote in message <35EB9B91.3FF8583@ehpt.com>... >Robert Martin wrote: > >> 2. Multiple exits >> File* f = fopen(...); >> while( ... ) { >> ... >> if( ... ){ >> fclose(f); >> return NOT_OK; >> } >> } >> fclose(f); >> return OK; > >Obviously you should NOT write code like this (for the reasons >you state). If the needs for cleanup continue to grow this will >become unmanageble very quickly. Especially if we have a lot >of exits where we need to duplicate code. > >If you need cleanup before leaving the function you >would need to change the original loop layout. Perhaps to: > >File* f = fopen(...); >while( ... ) { > ... > if( ... ){ > retval = NOT_OK; > goto leave_loop; > } >} >leave_loop: >fclose(f); >return retval; > This is roughly equivalent to the 'finally' solution in another post. And I'll use the same argument. char* p = malloc(80); if (!p) goto error_exit; File* f = fopen(...); if (!f) goto error_exit; while (...) { if (horrible_error) goto error_exit; } fclose(f); free(p) return OK; error_exit: if (p) free(p); if (f) fclose(f); return NOT_OK; } The redundant resource cleanup, and the checks made in the error_exit section are pretty ugly. And this ugliness will only grow and become more contorted over time. Also, it is not guaranteed that all resources will have check functions, forcing the use of flags (which is all p and f are used for in error_exit) in order to determine when it is safe to release such a resource. Single-entry/single-exit (se/se) structures always have appropriate places for acuiring and freeing resources. The state of the algorithm is encoded into the structure. Multiple exits, gotos, finally clauses, destructures, etc, all *lose* state information. Once they are invoked, the previous state of the algorithm can only be recaptured by investigating the data and within the algorithm. This means flags that cover the entire scope of the algorithm must be maintained so that the error recovery code can determine what to do. Now certainly it is easier to write the functions with multiple exits. And if the functions never change, then you have won; and using a structured programming approach would be a net loss. However, functions generally don't remain the same. Most of the time they <<grow>> (remember Kahn talking about how his "pets" enter through your ear and live inside your brain? "Later", he said, " as they <<grow>>...") Functions that have not been built using structured programming can degrade pretty badly when they <<grow>>. The decision to use multiple exists (other than exceptions) is a short term decision that will probably yeild short term benefits. But in the long term the decision has the potential to cause significant pain. Personally, I have experienced enough of that sort of pain, so I am pretty careful about se/se. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Robert I. Eachus 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 2 siblings, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sh2rp$8v3$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: > Now certainly it is easier to write the functions with multiple exits. And > if the functions never change, then you have won; and using a structured > programming approach would be a net loss. However, functions generally > don't remain the same. Most of the time they <<grow>> (remember Kahn > talking about how his "pets" enter through your ear and live inside your > brain? "Later", he said, " as they <<grow>>...") Functions that have not > been built using structured programming can degrade pretty badly when they > <<grow>>. (First some flame retardant, hopefully unnecessary. What follows talks about how the difference in paradigms between Ada and other languages affect which style--multiple exit--Ada programmers prefer. That doesn't mean that Ada is better, even though it is. ;-) Ada programmers are not used to functions growing. An abstraction is written once, then used forever. If it needs to be extended, you derive from it (called subtyping or subclassing in other OO languages), or extend the type locally with locally declared subprograms. Modifying existing code is a very rare process, and it usually involves changes, not growth. Package specs often grow during development, but that is usually due to recognizing the need or potential need for some additional operation to be exported. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert I. Eachus @ 1998-09-01 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Robert I. Eachus wrote in message ... >In article <6sh2rp$8v3$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: > > > Now certainly it is easier to write the functions with multiple exits. And > > if the functions never change, then you have won; and using a structured > > programming approach would be a net loss. However, functions generally > > don't remain the same. Most of the time they <<grow>> (remember Kahn > > talking about how his "pets" enter through your ear and live inside your > > brain? "Later", he said, " as they <<grow>>...") Functions that have not > > been built using structured programming can degrade pretty badly when they > > <<grow>>. > > Ada programmers are not used to functions growing. An abstraction >is written once, then used forever. If it needs to be extended, you >derive from it (called subtyping or subclassing in other OO languages), >or extend the type locally with locally declared subprograms. >Modifying existing code is a very rare process, and it usually >involves changes, not growth. Package specs often grow during >development, but that is usually due to recognizing the need or >potential need for some additional operation to be exported. This is, in fact, a characteristic of any good OO design that conforms to the Open/Closed principle. New featuers are added by adding new code; not by changing old working code. Nevertheless, functions sometimes do change; and when they do its nice to have the structured so as to facilitate those changes. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Robert I. Eachus @ 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mattias Lundstr�m 2 siblings, 1 reply; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Aggresive cuttings below. Robert Martin wrote: > [...] > This is roughly equivalent to the 'finally' solution in another post. And > I'll use the same argument. [...] [Loop that sets return value 'retval' and does 'goto error_exit' on error] > error_exit: > if (p) free(p); > if (f) fclose(f); return retval; // The point is that this is code that is ALWAYS executed. // The only "multi-exit" issue here is the multiple exit // points from the loop. The function has only this exit. Your problem with this is (as I understand you) is the use of flags (or other method of tracking) to be able to say if( resource1 allocated ) deallocate( resource1 ); if( resource2 allocated ) deallocate( resource2 ); ... if( resourceN allocated ) deallocate( resourceN ); How do you mean that you could avoid this by a single-exit solution ? > > The redundant resource cleanup, and the checks made in the error_exit > section are pretty ugly. And this ugliness will only grow and become more Perhaps. But I do think they are unavoidable. You may break them up over multiple functions when and if they become too complex, but this has really nothing to do with the single/multi-exit issue. > contorted over time. Also, it is not guaranteed that all resources will > have check functions, forcing the use of flags (which is all p and f are > used for in error_exit) in order to determine when it is safe to release > such a resource. > > Single-entry/single-exit (se/se) structures always have appropriate places > for acuiring and freeing resources. The state of the algorithm is encoded > into the structure. Multiple exits, gotos, finally clauses, destructures, > etc, all *lose* state information. Once they are invoked, the previous > state of the algorithm can only be recaptured by investigating the data and > within the algorithm. This means flags that cover the entire scope of the > algorithm must be maintained so that the error recovery code can determine > what to do. The whole point of having resource deallocation at the end of the loop is that you do not want to distribute this into many places. Are you (I hope not) proposing something like while( loop should continue ) { ... if( error 1 ) { do some deallocation set flag(s) not to continue } ... if( error 2 ) { do some oother (possibly overlapping) deallocation set flag(s) not to continue } ... } > The decision to use multiple exists (other than exceptions) is a short term > decision that will probably yeild short term benefits. But in the long term > the decision has the potential to cause significant pain. Personally, I > have experienced enough of that sort of pain, so I am pretty careful about > se/se. As can be deduced from the above I do not agree with you ;-) Btw. Why, in your opinion, are exceptions different? - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 2379 bytes --] Mattias Lundstr�m wrote in message <35ED4937.1D01ED67@ehpt.com>... >Aggresive cuttings below. > >Robert Martin wrote: >> >[...] >> This is roughly equivalent to the 'finally' solution in another post. And >> I'll use the same argument. >[...] >[Loop that sets return value 'retval' and does 'goto error_exit' on >error] >> error_exit: >> if (p) free(p); >> if (f) fclose(f); >return retval; >// The point is that this is code that is ALWAYS executed. >// The only "multi-exit" issue here is the multiple exit >// points from the loop. The function has only this exit. > >Your problem with this is (as I understand you) is the use of flags >(or other method of tracking) to be able to say > >if( resource1 allocated ) deallocate( resource1 ); >if( resource2 allocated ) deallocate( resource2 ); >... >if( resourceN allocated ) deallocate( resourceN ); > >How do you mean that you could avoid this by a single-exit >solution ? Here is the solution I posted a few article back in this thread... int f() { int retval = 0; if (char* p = malloc(80)) { if (File* f = fopen("myFile", "r"); { fread(f, p, 80); ... fclose(f); } else // fopen failure { retval = 2; } free(p); } else // malloc failure { retval = 1; } return retval; } No tests necessary, structure preserved. >Btw. Why, in your opinion, are exceptions different? 1. They are indeterminate. When you throw an exception, you have no idea where control will wind up. It is not simply an exit from the current scope, or even from the current function. 2. As I prefer to use them, they are for extraordinary conditions. They are used when things go so wrong that there is no point in continuing, and also no point in maintaining any concern for efficiency. They are expensive. Finally, in the end, I still try to force a kind of single-exit mechanism on exceptions by using: catch(...){ cleanup(); throw; } (akin to Java's 'finally' clause). Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Robert I. Eachus 1998-09-02 0:00 ` Mattias Lundstr�m @ 1998-09-02 0:00 ` Mattias Lundstr�m 2 siblings, 0 replies; 510+ messages in thread From: Mattias Lundstr�m @ 1998-09-02 0:00 UTC (permalink / raw) Aggresive cuttings below. Robert Martin wrote: > [...] > This is roughly equivalent to the 'finally' solution in another post. And > I'll use the same argument. [...] [Loop that sets return value 'retval' and does 'goto error_exit' on error] > error_exit: > if (p) free(p); > if (f) fclose(f); return retval; // The point is that this is code that is ALWAYS executed. // The only "multi-exit" issue here is the multiple exit // points from the loop. The function has only this exit. Your problem with this is (as I understand you) is the use of flags (or other method of tracking) to be able to say if( resource1 allocated ) deallocate( resource1 ); if( resource2 allocated ) deallocate( resource2 ); ... if( resourceN allocated ) deallocate( resourceN ); How do you mean that you could avoid this by a single-exit solution ? > > The redundant resource cleanup, and the checks made in the error_exit > section are pretty ugly. And this ugliness will only grow and become more Perhaps. But I do think they are unavoidable. You may break them up over multiple functions when and if they become too complex, but this has really nothing to do with the single/multi-exit issue. > contorted over time. Also, it is not guaranteed that all resources will > have check functions, forcing the use of flags (which is all p and f are > used for in error_exit) in order to determine when it is safe to release > such a resource. > > Single-entry/single-exit (se/se) structures always have appropriate places > for acuiring and freeing resources. The state of the algorithm is encoded > into the structure. Multiple exits, gotos, finally clauses, destructures, > etc, all *lose* state information. Once they are invoked, the previous > state of the algorithm can only be recaptured by investigating the data and > within the algorithm. This means flags that cover the entire scope of the > algorithm must be maintained so that the error recovery code can determine > what to do. The whole point of having resource deallocation at the end of the loop is that you do not want to distribute this into many places. Are you (I hope not) proposing something like while( loop should continue ) { ... if( error 1 ) { do some deallocation set flag(s) not to continue } ... if( error 2 ) { do some oother (possibly overlapping) deallocation set flag(s) not to continue } ... } > The decision to use multiple exists (other than exceptions) is a short term > decision that will probably yeild short term benefits. But in the long term > the decision has the potential to cause significant pain. Personally, I > have experienced enough of that sort of pain, so I am pretty careful about > se/se. As can be deduced from the above I do not agree with you ;-) Btw. Why, in your opinion, are exceptions different? - Mattias ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Mattias Lundstr�m 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Tim Ottinger 1 sibling, 0 replies; 510+ messages in thread From: Tim Ottinger @ 1998-09-01 0:00 UTC (permalink / raw) Mattias Lundstr�m wrote: > I just have to butt in here. > Why would this code become harder to test? > > If we take a simple example (more or less C++) I added a few comments: > 1. Flag solution > while( ... && retval == OK ) { > ... > if( ... ) > retval = NOT_OK; > } > return retval; /* SET BREAKPOINT HERE */ > > vs > > 2. Multiple exits > while( ... ) { > ... > if( ... ) > return NOT_OK; /* SET BREAKPOINT HERE */ > } > return OK; /* AND ANOTHER ONE HERE */ In one case, I set a single breakpoint and can inspect the value to see what happened. In the second, I set more than one breakpoint, or the function will return quietly. That can be good or bad. The single-return gives more options than the multiple- return version. You can watchpoint the variable, or you can set the break on return and inspect the variable, or set the breaks where the return value is set. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Andrew Hussey 1998-08-31 0:00 ` Mattias Lundstr�m @ 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Tim McDermott ` (3 more replies) 1998-09-01 0:00 ` dewarr 2 siblings, 4 replies; 510+ messages in thread From: Matthew Heaney @ 1998-08-31 0:00 UTC (permalink / raw) ahussey@it.uq.edu.au (Andrew Hussey) writes: > >Using an exit from the middle avoids the headaches (literally) > >engendered by using an extra flag in the predicate. When you want to > >exit, you just say that you want to exit, directly. No mental > >gymnastics are required in order to determine whether you'll "really" > >exit, as would be the case using the flag approach. > > That's brilliant, now your code is much easier to write! > Now let's see who has an easier time *testing* their code. > I think you'll find the control-flow errors you introduce > in the spaghetti you produce will more than make up for > any gain you have from rapid coding. Here's is something I whipped up for another post recently. It's an equality operator for a bounded stack. The implementation of the function has multiple returns. Does this implementation fit your definition of spaghetti code? Would the implementation be better by not using multiple returns? function "=" (L, R : Stack_Type) return Boolean is begin if L.Top /= R.Top then return False; end if; for Index in Positive range 1 .. L.Top loop if L.Items (Index) /= R.Items (Index) then return False; end if; end loop; return True; end "="; My feeling is that trying to implement this operation using only a single return would just make it more complicated. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney @ 1998-08-31 0:00 ` Tim McDermott 1998-08-31 0:00 ` Larry Brasfield ` (2 more replies) 1998-08-31 0:00 ` Robert Martin ` (2 subsequent siblings) 3 siblings, 3 replies; 510+ messages in thread From: Tim McDermott @ 1998-08-31 0:00 UTC (permalink / raw) Matthew Heaney wrote: > Here's is something I whipped up for another post recently. It's an > equality operator for a bounded stack. > > The implementation of the function has multiple returns. > > Does this implementation fit your definition of spaghetti code? > > Would the implementation be better by not using multiple returns? > > function "=" (L, R : Stack_Type) return Boolean is > begin > > if L.Top /= R.Top then > return False; > end if; > > for Index in Positive range 1 .. L.Top loop > if L.Items (Index) /= R.Items (Index) then > return False; > end if; > end loop; > > return True; > > end "="; > > My feeling is that trying to implement this operation using only a > single return would just make it more complicated. How about this: function "=" (L, R : Stack_Type) return Boolean is begin Boolean isEqual = True; Positive Index = 1; if L.Top /= R.Top then isEqual = False; end if; while Index < L.Top && isEqual loop if L.Items (Index) /= R.Items (Index) then isEqual = False; end if; Index++; end loop; return isEqual; end "="; What Dykstra was getting at with single entance, single exit is that you can attempt to reason about the programs that are well structured. In the second version, you can make assertions about pre- and post-conditions. In fact they jump out of the loop test. That is not the case with the first version. Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Tim McDermott @ 1998-08-31 0:00 ` Larry Brasfield 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` dewar 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 1 reply; 510+ messages in thread From: Larry Brasfield @ 1998-08-31 0:00 UTC (permalink / raw) Tim McDermott wrote in message <35EB1706.22E7E52E@draper.com>... > > >Matthew Heaney wrote: > >> Here's is something I whipped up for another post recently. It's an >> equality operator for a bounded stack. >> >> The implementation of the function has multiple returns. >> >> Does this implementation fit your definition of spaghetti code? Not mine. Without significant effort, I can translate your code into "False if lengths differ, or if an element differs, else True". The concept of returning a query result when and where it becomes known cannot degrade clarity as I perceive it. >> Would the implementation be better by not using multiple returns? >> >> function "=" (L, R : Stack_Type) return Boolean is >> begin >> >> if L.Top /= R.Top then >> return False; >> end if; >> >> for Index in Positive range 1 .. L.Top loop >> if L.Items (Index) /= R.Items (Index) then >> return False; >> end if; >> end loop; >> >> return True; >> >> end "="; >> >> My feeling is that trying to implement this operation using only a >> single return would just make it more complicated. I think this is a poor example for the structure issue. A better one, IMO, is one where state must be modified and invariants discerned to be maintained "while" some appropriately understood transformation is effected. >How about this: > > function "=" (L, R : Stack_Type) return Boolean is >begin > > Boolean isEqual = True; > Positive Index = 1; > > if L.Top /= R.Top then > isEqual = False; > end if; > > while Index < L.Top && isEqual loop > if L.Items (Index) /= R.Items (Index) then > isEqual = False; > end if; > Index++; > end loop; > > return isEqual; > >end "="; > >What Dykstra was getting at with single entance, single exit is that you can >attempt to reason about the programs that are well structured. In the >second version, you can make assertions about pre- and post-conditions. In >fact they jump out of the loop test. That is not the case with the first >version. A bit overstated in this case, I think. But your point is important. There seem to be two ways that people analyze program segments: (1) What the code does; and (2) What is true because the code runs/ran. (I do not count a myriad of fuzzy and inneffective ways.) Multiple exits and other more complicated flow graphs impede (but do not necessarily defeat) a "What is true" analysis, but do not have as much effect on a "What will/can happen when this runs" analysis, unless the flow of control becomes difficult to sort out. I maintain that "What is true" analysis is ultimately more effective and reliable, especially as it is composed from smaller chunks of analysis. At higher levels than short, readily grasped partial screen code fragments, simpler flow graphs are a bigger win than is apparent from the small examples used to illustrate such ideas, especially for those who take the "What is true" approach. I think a lot of the disagreement over the merits of the less simple structure (short spaghetti?) arises from differences in how people comprehend code. I once worked with a brilliant fellow whose code drove me nuts (momentarily!) because his way of looking at it was different from mine, in the way I've suggested. (No offense intended, if you're reading this, D.) That said, I find the addition of extra flags just to remove an edge from the flow graph to be a (slight) hindrance to comprehension. --Larry Brasfield Above opinions may be mine alone. (Humans may reply at unundered larry_br@sea_net.com ) ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Larry Brasfield @ 1998-09-01 0:00 ` Matthew Heaney 0 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) "Larry Brasfield" <larry_br@sea_net.com> writes: > >> Does this implementation fit your definition of spaghetti code? > > Not mine. Without significant effort, I can translate your code > into "False if lengths differ, or if an element differs, else True". > The concept of returning a query result when and where it > becomes known cannot degrade clarity as I perceive it. Ah, the voice of reason in a chaotic world. Thanks for the dose of pragmatism. > That said, I find the addition of extra flags just to > remove an edge from the flow graph to be a > (slight) hindrance to comprehension. Me too. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Tim McDermott 1998-08-31 0:00 ` Larry Brasfield @ 1998-09-01 0:00 ` dewar 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: dewar @ 1998-09-01 0:00 UTC (permalink / raw) In article <35EB1706.22E7E52E@draper.com>, Tim McDermott <mcdermott@draper.com> wrote: > > > Matthew Heaney wrote: > > > Here's is something I whipped up for another post recently. It's an > > equality operator for a bounded stack. > > > > The implementation of the function has multiple returns. > > > > Does this implementation fit your definition of spaghetti code? > > > > Would the implementation be better by not using multiple returns? > > > > function "=" (L, R : Stack_Type) return Boolean is > > begin > > > > if L.Top /= R.Top then > > return False; > > end if; > > > > for Index in Positive range 1 .. L.Top loop > > if L.Items (Index) /= R.Items (Index) then > > return False; > > end if; > > end loop; > > > > return True; > > > > end "="; > > > > My feeling is that trying to implement this operation using only a > > single return would just make it more complicated. > > How about this: > > function "=" (L, R : Stack_Type) return Boolean is > begin > > Boolean isEqual = True; > Positive Index = 1; > > if L.Top /= R.Top then > isEqual = False; > end if; > > while Index < L.Top && isEqual loop > if L.Items (Index) /= R.Items (Index) then > isEqual = False; > end if; > Index++; > end loop; > > return isEqual; > > end "="; > > What Dykstra was getting at with single entance, single exit is that you can > attempt to reason about the programs that are well structured. In the > second version, you can make assertions about pre- and post-conditions. In > fact they jump out of the loop test. That is not the case with the first > version. > > Tim > > Yes, this is a very predictable response, but I MUCH prefer the original with multiple returns, why? Because when I read return False; I know that is the end of it, and I can immediately verify that this part of the program is correct, and that the value returned in this case is what it should be. I can then forget that case and move to the next one. If on the other hand I read: > isEqual = False; Then I have to keep this in mind, as I read on, to make sure some idiot has not added later on a statement like if some-weird-hard-to-follow-condition then isEqual = True; end if; changing the original value. and of course I have to keep looking, because someone may change the value back to False. Variables are dangerous in themselves, replacing multiple returns by introducing a variable is in this case jumping out of the frying pan into the fire! -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Tim McDermott 1998-08-31 0:00 ` Larry Brasfield 1998-09-01 0:00 ` dewar @ 1998-09-01 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) Tim McDermott <mcdermott@draper.com> writes: > How about this: > > function "=" (L, R : Stack_Type) return Boolean is > begin > > Boolean isEqual = True; > Positive Index = 1; > > if L.Top /= R.Top then > isEqual = False; > end if; > > while Index < L.Top && isEqual loop > if L.Items (Index) /= R.Items (Index) then > isEqual = False; > end if; > Index++; > end loop; > > return isEqual; > > end "="; > > What Dykstra was getting at with single entance, single exit is that you can > attempt to reason about the programs that are well structured. In the > second version, you can make assertions about pre- and post-conditions. In > fact they jump out of the loop test. That is not the case with the first > version. I find that mentally reasoning about the behavior of this program is more difficult. When the first test is finished, I have to do mental work to make sure that, if isEqual is false, no code gets executed prior to reaching my destination, which is the end of the subprogram. This is mental work I wouldn't have to do had I just returned immediately, knowing that the stack depths were different. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Tim McDermott @ 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Gene Gajewski ` (6 more replies) 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Don Harrison 3 siblings, 7 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... > >Would the implementation be better by not using multiple returns? Yes. Imagine that you had to change the function to make it thread safe; and that the way to do that was to sieze and release a mutex while the function was executing. As written you would have to add the release in three separate places. But if you had avoided the multiple returns, you would have had a single release. > > >function "=" (L, R : Stack_Type) return Boolean is >begin > > if L.Top /= R.Top then > return False; > end if; > > for Index in Positive range 1 .. L.Top loop > if L.Items (Index) /= R.Items (Index) then > return False; > end if; > end loop; > > return True; > >end "="; > > >My feeling is that trying to implement this operation using only a >single return would just make it more complicated. Well, let's see: (in C++) bool operator==(Stack& l, Stack& r) { bool equal = true; for (int index = 1; index < l.top() && equal == true; index++) { if (l[index] != r[index]) equal = false; } return equal; } If this is more complex (something that is arguable) it is not *much* more complex. On the other hand, it is easier to maintain. The thread-safety issue I talked about above would be easier to add to this function than to the one with multiple returns. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Gene Gajewski 1998-09-01 0:00 ` Matthew Heaney ` (5 subsequent siblings) 6 siblings, 0 replies; 510+ messages in thread From: Gene Gajewski @ 1998-08-31 0:00 UTC (permalink / raw) Robert Martin wrote in message <6sf87j$47n$1@hirame.wwa.com>... >Yes. Imagine that you had to change the function to make it thread safe; >and that the way to do that was to sieze and release a mutex while the >function was executing. As written you would have to add the release in >three separate places. But if you had avoided the multiple returns, you >would have had a single release. Sounds as if the mutex belongs outside of the function, not in it. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Gene Gajewski @ 1998-09-01 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Robert I. Eachus ` (4 subsequent siblings) 6 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >Would the implementation be better by not using multiple returns? > > Yes. Imagine that you had to change the function to make it thread safe; > and that the way to do that was to sieze and release a mutex while the > function was executing. As written you would have to add the release in > three separate places. But if you had avoided the multiple returns, you > would have had a single release. Well... The proper way to use a mutex is to wrap it in a controlled type, so that release is called automatically as a result of subprogram exit, no matter what the reason. (Controlled types in Ada have operations that are roughly analagous to constructors and deconstructors in C++.) Something like: function "=" (L, R : Stack_Type) return Boolean is Lock : Mutex_Lock (Mutex'Access); begin <same body as before> end "="; When the Lock object initializes (automatically), it calls the seize operation of the mutex. When the Lock object finalizes (automatically, as a result of subprogram termination - for whatever reason), it calls the release operation of the mutex. A subprogram could terminate because there was an unhandled exception, which is a form of return. In that case, release wouldn't get called. (Unless you remembered to include a catch-all handler, to release the mutex. But you probably won't remember.) So I don't buy your thread-safety argument, because the issue you raise is a problem for any algorithm that requires a mutex, not just an algorithm implemented using multiple returns. > bool operator==(Stack& l, Stack& r) > { > bool equal = true; > for (int index = 1; index < l.top() && equal == true; index++) > { > if (l[index] != r[index]) > equal = false; > } > return equal; > } > > If this is more complex (something that is arguable) it is not *much* more > complex. I find that this is indeed more complex. A decision table for the predicate has 4 rules instead of just 2. > On the other hand, it is easier to maintain. The thread-safety > issue I talked about above would be easier to add to this function than to > the one with multiple returns. I agree with you, but as I pointed out, there are problems with that implementation too. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerhard Menzl 1998-09-02 0:00 ` Tres Seaver 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: > >> >Would the implementation be better by not using multiple returns? >> >> Yes. Imagine that you had to change the function to make it thread safe; >> and that the way to do that was to sieze and release a mutex while the >> function was executing. As written you would have to add the release in >> three separate places. But if you had avoided the multiple returns, you >> would have had a single release. > >Well... The proper way to use a mutex is to wrap it in a controlled >type, so that release is called automatically as a result of subprogram >exit, no matter what the reason. (Controlled types in Ada have >operations that are roughly analagous to constructors and deconstructors >in C++.) In a language that supports such things, using controlled types is *a* way (not necessarily the "proper" way). (it happens to be the way that I choose in many cases). But this has nothing really to do with the issue at hand. Yes, it may be feasible to put some resource management code into a controlled type and avoid the issues of maintenance that I raised earlier; but that doesn't eliminate the problem of structure. In the end, if you can make the structure of the software solve a problem, that is better than using a special language feature to do it. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Gerhard Menzl 1998-09-02 0:00 ` Tres Seaver 1 sibling, 0 replies; 510+ messages in thread From: Gerhard Menzl @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > >> Yes. Imagine that you had to change the function to make it thread safe; > >> and that the way to do that was to sieze and release a mutex while the > >> function was executing. As written you would have to add the release in > >> three separate places. But if you had avoided the multiple returns, you > >> would have had a single release. > > > >Well... The proper way to use a mutex is to wrap it in a controlled > >type, so that release is called automatically as a result of subprogram > >exit, no matter what the reason. (Controlled types in Ada have > >operations that are roughly analagous to constructors and deconstructors > >in C++.) > > In a language that supports such things, using controlled types is *a* way > (not necessarily the "proper" way). (it happens to be the way that I choose > in many cases). But this has nothing really to do with the issue at hand. > Yes, it may be feasible to put some resource management code into a > controlled type and avoid the issues of maintenance that I raised earlier; > but that doesn't eliminate the problem of structure. In the end, if you can > make the structure of the software solve a problem, that is better than > using a special language feature to do it. In the presence of structured exception handling, as in C++, controlled types are the proper way; everything else will lead to code duplication and unnecessary tests. This does not lead to the conclusion that multiple returns are a good thing, but neither is resource allocation and deallocation a good argument *against* them as far as object-oriented languages are concerned. With purely procedural languages, I concede that you have a point. Gerhard Menzl ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerhard Menzl @ 1998-09-02 0:00 ` Tres Seaver 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1 sibling, 2 replies; 510+ messages in thread From: Tres Seaver @ 1998-09-02 0:00 UTC (permalink / raw) Robert Martin wrote: > > Matthew Heaney wrote in message ... > >"Robert Martin" <rmartin@oma.com> writes: > > > >> >Would the implementation be better by not using multiple returns? > >> > >> Yes. Imagine that you had to change the function to make it thread safe; > >> and that the way to do that was to sieze and release a mutex while the > >> function was executing. As written you would have to add the release in > >> three separate places. But if you had avoided the multiple returns, you > >> would have had a single release. > > > >Well... The proper way to use a mutex is to wrap it in a controlled > >type, so that release is called automatically as a result of subprogram > >exit, no matter what the reason. (Controlled types in Ada have > >operations that are roughly analagous to constructors and deconstructors > >in C++.) > > In a language that supports such things, using controlled types is *a* way > (not necessarily the "proper" way). (it happens to be the way that I choose > in many cases). But this has nothing really to do with the issue at hand. > Yes, it may be feasible to put some resource management code into a > controlled type and avoid the issues of maintenance that I raised earlier; > but that doesn't eliminate the problem of structure. In the end, if you can > make the structure of the software solve a problem, that is better than > using a special language feature to do it. I find it interesting to read all the "single entry / exit" argument in light of the prolifieration of exception-based mechanisms. Exceptions have all of the disadvantages of multiple returns, with the added problem of invisibility. Adjusting one's style to remain robust in the face of exceptions automagically makes for robustness in the presence of multiple returns, it would seem to me. -- Tres Seaver tseaver@palladion.com Palladion Software http://www.palladion.com Houston, Texas, USA Vox: (713) 523-6582 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Tres Seaver @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Patrick Logan 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Tres Seaver wrote in message <35EDB334.B65F7D81@palladion.com>... > >I find it interesting to read all the "single entry / exit" argument in light of >the prolifieration of exception-based mechanisms. Exceptions have all of the >disadvantages of multiple returns, with the added problem of invisibility. >Adjusting one's style to remain robust in the face of exceptions automagically >makes for robustness in the presence of multiple returns, it would seem to me. > Exceptions are extraordinary. By the time you throw an exception, things have gone very wrong. Yes, there is some cleanup you may need to do. But there is also quite a bit that you can probably ignore. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` sureshvv 0 siblings, 0 replies; 510+ messages in thread From: sureshvv @ 1998-09-03 0:00 UTC (permalink / raw) In article <6skp0i$8i9$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Exceptions are extraordinary. By the time you throw an exception, things > have gone very wrong. Yes, there is some cleanup you may need to do. But > there is also quite a bit that you can probably ignore. In one part of the system, Yes. The system could self-rectify and continue to function or function in a slightly degraded manner long after the exception is thrown. Of course, depending upon what you decided to cleanup and what you ignored :-) suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Tres Seaver 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Patrick Logan 1 sibling, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Tres Seaver <tseaver@palladion.com> wrote: : I find it interesting to read all the "single entry / exit" argument in light of : the prolifieration of exception-based mechanisms. Exceptions have all of the : disadvantages of multiple returns, with the added problem of invisibility. : Adjusting one's style to remain robust in the face of exceptions automagically : makes for robustness in the presence of multiple returns, it would seem to me. That's an interesting point. Should a loop exit from one point only, and *then* throw an exception? Or should the exception be thrown from within the loop? I think the latter, in most cases, but this is an example of mid-exit. I don't write that many loops the throw exceptions, but I do it. I will continue to hammer home the need for *short* methods in any case. I hate encountering someone's page-long methods. They're almost bound to be doing something incomprehensible. Otherwise if they're short their bound to be more manageable no matter how "unstructured". -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Gene Gajewski 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` Robert I. Eachus 1998-09-01 0:00 ` sureshvv ` (3 subsequent siblings) 6 siblings, 0 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sf87j$47n$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: > If this is more complex (something that is arguable) it is not *much* more > complex. On the other hand, it is easier to maintain. The thread-safety > issue I talked about above would be easier to add to this function than to > the one with multiple returns. And as far as some of us are concerned, there is no difference, because the way to implement the guarded function is to wrap the guard around the test: function "=" (L, R : Guarded_Stack_Type) return Boolean is Temp: Boolean; begin Seize(L.Guard); Seize(R.Guard); Temp := Stack_Type(L) = Stack_Type(R); Release(R.Guard); Release(L.Guard); return Temp; end "="; With the obvious type declaration for the guarded stack: type Guarded_Stack_Type is new Stack with Guard: Semaphore; This implements the guarded equality in terms of the (known good) test for the parent type. Of course, this particular implementation is subject to deadlock, so I would either use a single semaphore for all stacks, or a more complex locking strategy, probably locking the stack with the lower address first: function "=" (L, R : Guarded_Stack_Type) return Boolean is Temp: Boolean; begin if L'Address = R'Address then return True; end if; if L'Address < R'Address then Seize(L.Guard); Seize(R.Guard); else Seize(R.Guard); Seize(L.Guard); end if; Temp := Stack_Type(L) = Stack_Type(R); Release(R.Guard); Release(L.Guard); -- release order doesn't matter. return Temp; end "="; Now we have a tasking/thread safe comparison, but we didn't have to mix up the three cases here with the three cases in the original "=". So I have six cases to test, not nine. Actually, I get more benefit, because I only have three NEW cases to test. Note to Ada programmers: At first it seems right to make the entire stack type a protected object. But how would you define the "=" and any other two stack operations in that case? Once you realize that there needs to be a pair of seize and release operations, you might as well associate them with a new component of the object anyway. Also--for Ada and non-Ada programmers--the norm would be to do all this in the body of the package which defined Guarded_Stack_Type as a private extension of Stack_Type. Now the interface profile of the two types can be the same, since all the semaphore manipulations can be hidden from view. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin ` (2 preceding siblings ...) 1998-09-01 0:00 ` Robert I. Eachus @ 1998-09-01 0:00 ` sureshvv 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Richard Melvin ` (2 subsequent siblings) 6 siblings, 1 reply; 510+ messages in thread From: sureshvv @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sf87j$47n$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Matthew Heaney wrote in message ... > > > > >Would the implementation be better by not using multiple returns? > > Yes. Imagine that you had to change the function to make it thread safe; > and that the way to do that was to sieze and release a mutex while the > function was executing. As written you would have to add the release in > three separate places. But if you had avoided the multiple returns, you > would have had a single release. In C++, you could use the Resource Allocation is Initialization idiom to deal with such cases. 1. Early returns aid in limiting the amount of code that has to be processed and understood. 2. Understandability is the most important criterion for maintainability. Making the code as simple as possible in order to solve the problem at hand is more important than trying to make it easier to change against some imaginary future changes. suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` sureshvv @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` sureshvv 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) sureshvv@hotmail.com wrote in message <6sh6ic$o8p$1@nnrp1.dejanews.com>... >In article <6sf87j$47n$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: >> >1. Early returns aid in limiting the amount of code that has to be processed >and understood. I disagree. It only limits the amount of code to read for one particular iteration of the loop. But to understand the loop you have to read it all. > >2. Understandability is the most important criterion for maintainability. I disagree again. An easily modifiable structure is much more important than understandability. *Any* structure built by a human can be understood by most other humans. Once understood, the work is over. But a structure that is hard to maintain, remains hard to maintain until you redesign it. There are many structures that are easy to understand but hard to maintain. >Making the code as simple as possible in order to solve the problem at hand >is more important than trying to make it easier to change against some >imaginary future changes. I disagree one last time. Two digit dates are much easier to deal with than four digit dates. Until the century changes... The engineer who does not design for maintainability, is doing a disservice to himself, his fellow engineers, and his employer. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` sureshvv 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Robert Martin 0 siblings, 2 replies; 510+ messages in thread From: sureshvv @ 1998-09-02 0:00 UTC (permalink / raw) In article <6shhcq$lid$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > sureshvv@hotmail.com wrote in message <6sh6ic$o8p$1@nnrp1.dejanews.com>... > > >1. Early returns aid in limiting the amount of code that has to be > processed > >and understood. > > I disagree. It only limits the amount of code to read for one particular > iteration of the loop. But to understand the loop you have to read it all. > > I do not think that number of iterations a loop makes is of primary importance while examining an unfamiliar piece of code. In the example we have been discussing, the early return indicates that if the stacks are of different length the stacks are different and examining the items in the stack is unnecessary. This logic is immediately apparent with the early return than with the flags that you added in order to conform to the se/se principle. > >2. Understandability is the most important criterion for maintainability. > > I disagree again. An easily modifiable structure is much more important > than understandability. *Any* structure built by a human can be understood > by most other humans. Once understood, the work is over. But a structure > that is hard to maintain, remains hard to maintain until you redesign it. Maintenance is redesign. It is more important that your methods be small and focussed enough that they can be rewritten relatively quickly in the face of new requirements than being harder to read (with various flags to help conform to the single entry-exit principle) just so they give you space to squeeze in some new code. > There are many structures that are easy to understand but hard to maintain. But maintain against what kind of changes? Your examples were all about using some resource that needs to be finalized, and will be properly handled by using the Resource acquisition is initialization (RAI, to be Ellesque) idiom. > >Making the code as simple as possible in order to solve the problem at hand > >is more important than trying to make it easier to change against some > >imaginary future changes. > > I disagree one last time. Two digit dates are much easier to deal with than > four digit dates. Until the century changes... Y2K, the last resort of usenet arguments. INMO, 2 digit dates were an engineering tradeoff, that made sense when they were written just like 4 digit dates do now (which will break after the year 9999). > The engineer who does not > design for maintainability, is doing a disservice to himself, his fellow > engineers, and his employer. More bs. The argument is if using flags to conform to the se/se principle, makes the code more maintainable. The engineer who spends his time making his code more complex to protect against a certain kind of changes (which are better handled using techniques, such as Resource acquisition is initialization) is wasting the time of his fellow engineers and the resources of his employer. suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` sureshvv @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Charles Hixson 1998-09-04 0:00 ` Rick Smith 1998-09-02 0:00 ` Robert Martin 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) sureshvv@hotmail.com wrote in message <6sk59r$8e6$1@nnrp1.dejanews.com>... >In article <6shhcq$lid$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: >> >> sureshvv@hotmail.com wrote in message <6sh6ic$o8p$1@nnrp1.dejanews.com>... >> >Making the code as simple as possible in order to solve the problem at hand >> >is more important than trying to make it easier to change against some >> >imaginary future changes. >> >> I disagree one last time. Two digit dates are much easier to deal with than >> four digit dates. Until the century changes... > >INMO, 2 digit dates were >an engineering tradeoff, that made sense when they were written >just like 4 digit dates do now (which will break after the year 9999). If only it were so. But of course many of the Y2K problems are not being solved by expanding the field to four digits. Rather they are adding *code* not *space*. The technique is called windowing. Whenver date subtractions or comparisons are done in the code, they interpreted as follows: if date > X assume 1900 else assume 2000 If X is 50 then any date larger than 50 is assumed to be in the 20th century. Otherwise the data is assumed to be in the 21st century. This, of course, means that there will be a Y2050 crisis. Ah, but no. Because X is not universally agreed upon. Some applications use 60, some use 40. So what we really have is a smearing of the crisis over the next several decades. Of course none of those old COBOL programs will still be running then... The choice to use windowing rather than 4 digit dates is also an engineering trade off. >> The engineer who does not >> design for maintainability, is doing a disservice to himself, his fellow >> engineers, and his employer. > >More bs. The argument is if using flags to conform to the se/se principle, >makes the code more maintainable. >The engineer who spends his time making his code more complex to protect >against a certain kind of changes (which are better handled using techniques, >such as Resource acquisition is initialization) is wasting the time of his >fellow engineers and the resources of his employer. Granted. Now, what takes longer. Creating new classes and managing resources in their constructors and destructors; or maintaining single-entry/single-exit style? RAI is a very nice technique, and I am happy to use it for certain kinds of exception protection. Expecially when the classes have already been built (e.g. auto_ptr). On the other hand, there are resources that don't lend well to management from destructors. And for those, I prefer to use se/se as an aid to their management. In the final analysis, we are not talking about a huge investment. se/se functions are not horribly more complex, or terribly difficult to read. They are software, like any other. Their structure is more conducive to certain kinds of maintenance. The cost of building se/se is reasonably low. These are data points for making engineering trade offs. If you have a function that can be managed with RAI, and you are reasonably sure that this will be the case for the forseeable future, and you really need a few extra minutes, then by all means use multiple exits. On the other hand, if you think its possible that RAI will be insufficient to handle the resource needs of your functions in the forseeable future, and you can spare a few extra minutes to work out the se/se structure, you are probably better off doing so. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Charles Hixson 1998-09-04 0:00 ` Patrick Logan 1998-09-04 0:00 ` adam 1998-09-04 0:00 ` Rick Smith 1 sibling, 2 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote: ... > If only it were so. But of course many of the Y2K problems are not being > solved by expanding the field to four digits. Rather they are adding *code* > not *space*. The technique is called windowing. Whenver date subtractions > or comparisons are done in the code, they interpreted as follows: > > if date > X assume 1900 else assume 2000 > > If X is 50 then any date larger than 50 is assumed to be in the 20th > century. Otherwise the data is assumed to be in the 21st century. > > This, of course, means that there will be a Y2050 crisis. Ah, but no. > Because X is not universally agreed upon. Some applications use 60, some > use 40. So what we really have is a smearing of the crisis over the next > several decades. > > Of course none of those old COBOL programs will still be running then... > > The choice to use windowing rather than 4 digit dates is also an engineering > trade off. > ... > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan I hope that you are wrong about what they are doing. I fear that you aren't. Windowing is a good solution for recovering the data before saving it into a new format. It's a very bad permanent "solution". Usually. Sometimes one can define a window based around the current date that will work in a permanent manner (data only kept for so long, e.g.). And in such cases one would always be able to recalculate the data to the expanded format whenever needed. (This is why there should never be a 9999 crisis). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Charles Hixson @ 1998-09-04 0:00 ` Patrick Logan 1998-09-04 0:00 ` adam 1 sibling, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-04 0:00 UTC (permalink / raw) In comp.object Charles Hixson <charleshixsn@earthlink.net> wrote: : I hope that you are wrong about what they are doing. I fear that : you aren't. Windowing is a good solution for recovering the data : before saving it into a new format. It's a very bad permanent : "solution". Usually. From what I've read, the people writing about "windowing" realize it is a temporary solution (the duration of the window). What's *really* scary is the people who indicate they are going to "fix on failure"! OTOH some of these situations could turn into an opportunity for Extreme Programming and building "spike" solutions. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Charles Hixson 1998-09-04 0:00 ` Patrick Logan @ 1998-09-04 0:00 ` adam 1998-09-06 0:00 ` Gerry Quinn 1 sibling, 1 reply; 510+ messages in thread From: adam @ 1998-09-04 0:00 UTC (permalink / raw) In article <35EF7971.1CDE6B7D@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: > > I hope that you are wrong about what they are doing. I fear that you > aren't. Windowing is a good solution for recovering the data before > saving it into a new format. It's a very bad permanent "solution". > Usually. I hope no one thinks it's intended as a permanent solution. Given that there's less than a year and a half until 2000 hits, what this solution does is to buy a lot of time to come up with a "real" solution. (I'm assuming that the windowing solution requires a lot less resources than expanding the date.) I agree that this solution may not make a lot of sense for an organization that can *comfortably* go to a 4-digit date and have everything in place by the time it's needed. Of course, there's the danger that pointy-haired managers will then fail to work on the "real" solution for the next 49 years, because "it's not causing any problems right now", and "our whole computer systems will be obsolete by then anyway", and "we've never heard of George Santayana". Now I have to go dig up the very funny joke that appeared on rec.humor.funny recently, about a COBOL programmer who got so sick of Y2K problems that he had himself cryo- genically frozen to be awakened in 2003, only the cryogenic machine wasn't Y2K compliant so it didn't wake him up in time, and they finally woke him up almost 8000 years later because they were about to have a Year 10000 problem and they needed someone who knew COBOL. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` adam @ 1998-09-06 0:00 ` Gerry Quinn 0 siblings, 0 replies; 510+ messages in thread From: Gerry Quinn @ 1998-09-06 0:00 UTC (permalink / raw) In article <6spj4u$pi0$1@nnrp1.dejanews.com>, adam@irvine.com wrote: > >Of course, there's the danger that pointy-haired managers will then fail to >work on the "real" solution for the next 49 years, because "it's not causing >any problems right now", and "our whole computer systems will be obsolete by >then anyway", and "we've never heard of George Santayana". Can't they 'window' again in 2049 by bringing everything back to the present state? - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Charles Hixson @ 1998-09-04 0:00 ` Rick Smith 1998-09-04 0:00 ` Charles Hixson ` (3 more replies) 1 sibling, 4 replies; 510+ messages in thread From: Rick Smith @ 1998-09-04 0:00 UTC (permalink / raw) Robert Martin wrote in message <6ske0c$16k$1@hirame.wwa.com>... > > ... But of course many of the Y2K problems are not being >solved by expanding the field to four digits. Rather they are adding *code* >not *space*. The technique is called windowing. Whenver date subtractions >or comparisons are done in the code, they interpreted as follows: > > if date > X assume 1900 else assume 2000 > >If X is 50 then any date larger than 50 is assumed to be in the 20th >century. Otherwise the data is assumed to be in the 21st century. > >This, of course, means that there will be a Y2050 crisis. Ah, but no. >Because X is not universally agreed upon. Some applications use 60, some >use 40. So what we really have is a smearing of the crisis over the next >several decades. Portions are correct for fixed windowing only! Consider that when reading data into the system, one could apply the window to create a 4 digit date, internally. In that situation, "date subtractions or comparisons" would be done on 4 digit dates. However, flexible windowing assumes a range around the current (system) date. In these cases, there is no specific "crisis" date and, in fact, may never have a "crisis" date. Besides, most dates need to have range checks for reasonableness. For example, should the date for a current transaction be accepted, without error or warning, if the date is more than a few days from the current date? Some data has a lifetime that makes 4 digit years unnecessary. If the requirements for an existing system state that a "back order" must be resolved within 30 days of the order date and that completed orders will not be held for more than 5 years, what is the benefit of changing the system to store 4 digit years with the order? The benefits of windowing should be clear. 1. No user should be required to enter more data than is necessary. If the correct 4 digit year can be determined by the last two digits, do not ask for more than these 2 digits. 2. Given the choice between windowing and reformating persistent data, choose windowing. Reformating existing data could break other parts of the system. Finally, for new systems or when reformating persistent data choose to store the data with 4 digit years or replace a calendar date format with a standard date format. >Of course none of those old COBOL programs will still be running then... Of course they will! :-) ------------------------------- Rick Smith e-mail: < ricksmith@aiservices.com > ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Rick Smith @ 1998-09-04 0:00 ` Charles Hixson 1998-09-04 0:00 ` Robert Martin ` (2 subsequent siblings) 3 siblings, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-04 0:00 UTC (permalink / raw) Rick Smith wrote: ... > Some data has a lifetime that makes 4 digit years unnecessary. If the > requirements for an existing system state that a "back order" must be > resolved within 30 days of the order date and that completed orders will > not be held for more than 5 years, what is the benefit of changing the > system to store 4 digit years with the order? > > The benefits of windowing should be clear. > > 1. No user should be required to enter more data than is necessary. If the > correct 4 digit year can be determined by the last two digits, do not ask > for more than these 2 digits. > ... > ------------------------------- > Rick Smith > e-mail: < ricksmith@aiservices.com > The problem comes when the validity of assumptions changes. In 1990 to say that if someone was born after xx/xx/90, then they were actually born before 1900 is reasonable. In 2000, what do you say about someone who was born in xx/xx/00? A 2-digit date was a perfectly valid entry value, it won't be for about 5 years (10 years?), and then it will be again. But this is an easy problem to overlook (most test data sets won't have any people more than 100 years old, and in most years a 2-digit entry field is good enough for everyone [no one living in my service area and entered in my database is currently verified to have lived to more than 105]). Also, it probably wouldn't cause any trouble in my application anyway (it doesn't matter much if a transit pass is denied to someone who is over 100 years old, they wouldn't have used it anyway -- given today's medicine). But there are a lot of guards in those sentences. Things external to my program that could change to cause my currently working program to stop working. And I don't have control over any of them. If the bus service starts a public relations campaign to provide free chauffered rides to seniors (or super-seniors), it will SUDDENLY be important that I handle the exceptional cases that I had been previously ignoring. ETC! On the other hand, the basic thrust of your argument is certainly correct. But one needs to be careful to build in overrides! E.g., have the century field exist on the form, but be automatically filled in with the most common default assumption, and then do an automatic tab over the field, so that one must manually select the century to be able to enter it. The century could also be a choice list, that includes all currently reasonable values. If the list of values is stored in a preferences file, then it would be no problem to add values once a century (even after the vendor stops supporting the environment). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Rick Smith 1998-09-04 0:00 ` Charles Hixson @ 1998-09-04 0:00 ` Robert Martin 1998-09-08 0:00 ` adam [not found] ` <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com> 3 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-04 0:00 UTC (permalink / raw) Rick Smith wrote in message ... > >However, flexible windowing assumes a range around the current (system) >date. In these cases, there is no specific "crisis" date and, in fact, may >never >have a "crisis" date. Of course the more applications that use a window around the current system date, the better. But in my travels, I have talked to a few Y2K managers, and they give me the impression that they are using fixed windowing alot. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Rick Smith 1998-09-04 0:00 ` Charles Hixson 1998-09-04 0:00 ` Robert Martin @ 1998-09-08 0:00 ` adam 1998-09-08 0:00 ` Rick Smith [not found] ` <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com> 3 siblings, 1 reply; 510+ messages in thread From: adam @ 1998-09-08 0:00 UTC (permalink / raw) In article <VxRH1.379$I%.1143059@news1.atlantic.net>, "Rick Smith" <ricksmith@aiservices.com> wrote: > 1. No user should be required to enter more data than is necessary. If the > correct 4 digit year can be determined by the last two digits, do not ask > for more than these 2 digits. Well, just to be nitpicky: Does this mean that if the window of reasonable dates is small enough, the user should only be asked for 1 digit, because the correct 4-digit year could be determined from just the last digit and because "we should never ask the user for more data than is necessary"? I don't think the "minimum amount of data necessary" philosophy makes any sense here. Rather, I think the legitimate reason here is that if users have been entering 2-digit years all along, it might make sense to keep the user interface the way it is. (I'm assuming we're talking about data entry people or other users who have been using the application for a while and have gotten accustomed to it.) However, if, in the same application, there are some places where 2 digits are sufficient and other places where it isn't (and thus 4 digits are "necessary"---unless you want to say that only the last 3 digits should be sufficient! :)) I'd personally prefer all the years to be 4 digits. As a user, I would much rather have consistency than an overzealous attempt at "allowing me to enter just the minimum amount of data I have to". The latter would actually make things less efficient, since I'd have to look at the screen and think about whether I need to type in 2 or 4 digits, instead of just automatically entering a 4-digit year every time. Of course, non-touch typists (and I mean those of you who have to hunt for the 9 key *twice* when entering the year 1998) may see things differently. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` adam @ 1998-09-08 0:00 ` Rick Smith 0 siblings, 0 replies; 510+ messages in thread From: Rick Smith @ 1998-09-08 0:00 UTC (permalink / raw) adam@irvine.com wrote in message <6t3use$5la$1@nnrp1.dejanews.com>... >In article <VxRH1.379$I%.1143059@news1.atlantic.net>, > "Rick Smith" <ricksmith@aiservices.com> wrote: > >> 1. No user should be required to enter more data than is necessary. If the >> correct 4 digit year can be determined by the last two digits, do not ask >> for more than these 2 digits. > >Well, just to be nitpicky: Does this mean that if the window of reasonable >dates is small enough, the user should only be asked for 1 digit, because the >correct 4-digit year could be determined from just the last digit and because >"we should never ask the user for more data than is necessary"? > The second sentence should have been "..., do not require more ..." This change causes the second sentence to match the meaning of the first sentence. In that sense, the user should be permitted to enter one digit or two digits or four digits, if that is the choice of the user. IMO, it is better that RSI not be the fault of the developer for requiring the entry of too much data. >I don't think the "minimum amount of data necessary" philosophy makes any >sense here. Rather, I think the legitimate reason here is that if users have >been entering 2-digit years all along, it might make sense to keep the user >interface the way it is. (I'm assuming we're talking about data entry people >or other users who have been using the application for a while and have >gotten accustomed to it.) However, if, in the same application, there are >some places where 2 digits are sufficient and other places where it isn't >(and thus 4 digits are "necessary"---unless you want to say that only the >last 3 digits should be sufficient! :)) I'd personally prefer all the years >to be 4 digits. As a user, I would much rather have consistency than an >overzealous attempt at "allowing me to enter just the minimum amount of data >I have to". The latter would actually make things less efficient, since I'd >have to look at the screen and think about whether I need to type in 2 or 4 >digits, instead of just automatically entering a 4-digit year every time. Of >course, non-touch typists (and I mean those of you who have to hunt for the 9 >key *twice* when entering the year 1998) may see things differently. > One reason that users have been entering two digit years, "all along," is that developers have required them to do so. Allowing one digit years, provides the opportunity for users to become accustomed to entering less data. A recent discussion in news:comp.lang.cobol concerned the longevity of four digit years. The concenus was that by 03 (or 2003) most of the systems that had been modified to accept four digit years, for data entry, will have been modified to reduce the requirement to two digits. I do not remember there being any disagreement that it would happen; it was just a question of when. ------------------------------- Rick Smith e-mail: < ricksmith@aiservices.com > ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com> @ 1998-09-08 0:00 ` Rick Smith 1998-09-08 0:00 ` Mark A Biggar 1 sibling, 0 replies; 510+ messages in thread From: Rick Smith @ 1998-09-08 0:00 UTC (permalink / raw) Giovanni 8 wrote in message ... >> Rick Smith wrote: >> The benefits of windowing should be clear. >> >> 1. No user should be required to enter more data than is >> necessary. If the correct 4 digit year can be determined >> by the last two digits, do not ask for more than these >> 2 digits. > >Yes, but how big is that "if"? A computer is a tool that should make jobs easier for users. Yet, I have seen too many cases where the developer uses fixed, inflexible formatting to ease *their* job of validating and processing the data; rather than making reasonable assumptions about data content to make it easier for the user to enter data. Fixed, inflexible formatting would require the entry of a year, for date of hire, even if the turn over for the organization is 90 per cent. This means that, with respect to date of hire, at least, 90 per cent of the time, the year is not required. If it has any semblence to a date, I will try to process it as such; but it is still your responsibility to determine if I have properly recognized the date you intended. >> 2. Given the choice between windowing and reformating >> persistent data, choose windowing. Reformating existing >> data could break other parts of the system. > >I disagree. The other parts of the system are already broken; >you've just been skating on thin ice. Repair them. Repair >your date formats. It doesn't really take all that long one >once you bite the bullet, and go on with life secure in knowing >that that problem will never ever catch up with you again. Disagree. There are, at least, three classes of programs, with respect to how they use the date. 1. Processes the date and must be corrected. 2. Passes the date without significant processing (e.g., printing the date in reports). 3. Uses a structure which contains a date but does not use the date, itself (e..g, uses employee master which has hire date). Changing the format of the date means that programs of types 2 and 3 must be changed even though they are not broken. >> Finally, for new systems or when reformating persistent data >> choose to store the data with 4 digit years or replace a >> calendar date format with a standard date format. > >Hmmm. Which "standard"? M$'s standard? The one that only >recently has been changed to handle dates after 1999-12-31? >There's an ISO standard (1685?) that at least allows a >reaonable format. Depends upon language, platform, etc. Just make certain that a standard exists. ISO appears fine in most cases; including the transport of data among systems. The COBOL standard integer date could be used within COBOL. However, C's time_t should never be stored in persistent data nor passed to other systems (from a discussion in < news:comp.std.c >). ------------------------------- Rick Smith e-mail: < ricksmith@aiservices.com > ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com> 1998-09-08 0:00 ` Rick Smith @ 1998-09-08 0:00 ` Mark A Biggar 1 sibling, 0 replies; 510+ messages in thread From: Mark A Biggar @ 1998-09-08 0:00 UTC (permalink / raw) Giovanni 8 wrote: > Good point. I've run into things like health care data. Looking > at the data in the data base, one must ask: Was that person born > in 1985 or was it 1885? Since a growing number of people are > living more than 100 years, it's a significant problem. This is exactly the situation my sister ran into. She works in the perscription claims processing group of a large health insurance company and they just went through a whole Y2K evaluation of their databases. What they discovered was that even though the database used 2 digit years all over the place, they actually had almost no Y2K problems. This was because the only dates where 2 vs 4 digits really mattered in the DB was for birthdates, which had always been stored in theire DB with 4 digits because when the DB first came on line in the mid 80's they had to correctly handle 90+ year old people born before 1900. All other dates in the DB where effectively some form of expiration date, none of which are before 1980. So there were only a few places where they had to tweek the code to think that years 00-79 corresponded to 2000-2079 (most of the code already made this assumption) and didn't have to change the DB at all. So, I guess they lucked out! -- Mark Biggar mark.a.biggar@lmco.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` sureshvv 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Robert Martin 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) sureshvv@hotmail.com wrote in message <6sk59r$8e6$1@nnrp1.dejanews.com>... > >Y2K, the last resort of usenet arguments. No -- Hitler is the last resort of usenet arguments. (oops, thread over, I lose.) Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin ` (3 preceding siblings ...) 1998-09-01 0:00 ` sureshvv @ 1998-09-01 0:00 ` Richard Melvin 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Jim Cochrane 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Chris Brand 6 siblings, 2 replies; 510+ messages in thread From: Richard Melvin @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sf87j$47n$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> writes >bool operator==(Stack& l, Stack& r) >{ > bool equal = true; > for (int index = 1; index < l.top() && equal == true; index++) > { > if (l[index] != r[index]) > equal = false; > } > return equal; >} Now, following convoluted conditionals[1] like the above always makes my head spin, but it looks to me like the above code would always return true when comparing against an empty stack. Given that this is a trivial piece of code, written by an expert, read by half of usenet, and nobody seems to have spotted the problem, I think this has to count as a significant data point on the side of the multiple returns camp. Richard [1] It's not particularly complicated, but it does combine into one expression two tests with completely different purposes, which I think is always a source of confusion. Of course, the 1-based indexing doesn't help, with 0-based being more usual in C++ - this is probably a second bug, but I'd have to see the specification of top and operator[] to find out. -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Melvin @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Jim Cochrane 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Richard Melvin wrote in message ... >In article <6sf87j$47n$1@hirame.wwa.com>, Robert Martin ><rmartin@oma.com> writes >>bool operator==(Stack& l, Stack& r) >>{ >> bool equal = true; >> for (int index = 1; index < l.top() && equal == true; index++) >> { >> if (l[index] != r[index]) >> equal = false; >> } >> return equal; >>} > >Now, following convoluted conditionals[1] like the above always makes my >head spin, but it looks to me like the above code would always return >true when comparing against an empty stack. > >Given that this is a trivial piece of code, written by an expert, read >by half of usenet, and nobody seems to have spotted the problem, I think >this has to count as a significant data point on the side of the >multiple returns camp. Sorry, I copied the algorithm that someone else wrote, and dropped the two lines that compared the size of the stack. It was *definitely* the use of structured programming that forced me to omit those two lines! The evidence is right here folks, structured programming damages your brain. You will omit lines of code if you use it. You are better off using lots of gotos, mid function returns, breaks, and continues so that you don't ever accidentally omit a couple of lines of code again! I've certainly learned my lesson. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Richard Melvin 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Jim Cochrane 1998-09-02 0:00 ` Richard Melvin 1 sibling, 1 reply; 510+ messages in thread From: Jim Cochrane @ 1998-09-02 0:00 UTC (permalink / raw) In article <LpVjTBAegG71EwXH@radm.demon.co.uk>, Richard Melvin <rmelvin@radm.demon.co.uk> wrote: >In article <6sf87j$47n$1@hirame.wwa.com>, Robert Martin ><rmartin@oma.com> writes >>bool operator==(Stack& l, Stack& r) >>{ >> bool equal = true; >> for (int index = 1; index < l.top() && equal == true; index++) >> { >> if (l[index] != r[index]) >> equal = false; >> } >> return equal; >>} > >Now, following convoluted conditionals[1] like the above always makes my >head spin, but it looks to me like the above code would always return >true when comparing against an empty stack. It appears that this routine has an implied pre-condition: l.size() == r.size() In this case, if l is empty, r is also empty. I think you can easily define equality as including the case where both stacks are empty. I suppose you could say that the problem is an undocumented pre-condition. > >Given that this is a trivial piece of code, written by an expert, read >by half of usenet, and nobody seems to have spotted the problem, I think >this has to count as a significant data point on the side of the >multiple returns camp. I think, more appropriately, it argues for the "Document routine pre/post-conditions (as well as use assertions as documentation of program state, where appropriate)" camp. > >Richard > >[1] It's not particularly complicated, but it does combine into one >expression two tests with completely different purposes, which I think >is always a source of confusion. Of course, the 1-based indexing doesn't >help, with 0-based being more usual in C++ - this is probably a second >bug, but I'd have to see the specification of top and operator[] to find >out. > >-- >Richard Melvin -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Jim Cochrane @ 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Jim Cochrane 0 siblings, 1 reply; 510+ messages in thread From: Richard Melvin @ 1998-09-02 0:00 UTC (permalink / raw) In article <6silt4$gb0@flatland.dimensional.com>, Jim Cochrane <jtc@dimensional.com> writes > >It appears that this routine has an implied pre-condition: >l.size() == r.size() > snip.. > >I think, more appropriately, it argues for the "Document routine >pre/post-conditions (as well as use assertions as documentation of >program state, where appropriate)" camp. I hardly think so, given that this was a comparison operator for a stack - a stack, pretty much by definition, is variable-length (perhaps with a fixed maximum length, but that's not relevant). Just throwing in extra preconditions to cover bugs in the implementation is not my interpretation of design-by-contract. Otherwise I can revolutionise the world of fast sort algorithms: void sortInLinearTime(Vector & v) { PRE (v.length() < 2); return; } (assuming PRE is counted as an externally-documented precondition, not an assertion). -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Richard Melvin @ 1998-09-02 0:00 ` Jim Cochrane 1998-09-03 0:00 ` Matthew Heaney 0 siblings, 1 reply; 510+ messages in thread From: Jim Cochrane @ 1998-09-02 0:00 UTC (permalink / raw) In article <9qnQhDAAvZ71EwAx@radm.demon.co.uk>, Richard Melvin <rmelvin@radm.demon.co.uk> wrote: >In article <6silt4$gb0@flatland.dimensional.com>, Jim Cochrane ><jtc@dimensional.com> writes >> >>It appears that this routine has an implied pre-condition: >>l.size() == r.size() >> >snip.. >> >>I think, more appropriately, it argues for the "Document routine >>pre/post-conditions (as well as use assertions as documentation of >>program state, where appropriate)" camp. > >I hardly think so, given that this was a comparison operator for a stack >- a stack, pretty much by definition, is variable-length (perhaps with a >fixed maximum length, but that's not relevant). > >Just throwing in extra preconditions to cover bugs in the implementation >is not my interpretation of design-by-contract. You are correct. My premise was a bit off. A better one would be: Before implementing a routine, it is necessary to determine what the routine must accomplish. A very effective method of doing this is to document the specification for the routine in the form of pre- and post-conditions. Once this is done, the routine can be coded such that it meets the post-condition based on the pre-condition. In the quoted example, documenting the pre-condition would have helped to uncover the fact that containers of different sizes would need to be dealt with. It would become obvious that a pre-condition of l.size = r.size would not be appropriate and thus that the negation of this condition would need to be dealt with in the implementation. > >Otherwise I can revolutionise the world of fast sort algorithms: > >void >sortInLinearTime(Vector & v) >{ > PRE (v.length() < 2); > return; >} > >(assuming PRE is counted as an externally-documented precondition, not >an assertion). >-- >Richard Melvin -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Jim Cochrane @ 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Jim Cochrane 0 siblings, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) jtc@dimensional.com (Jim Cochrane) writes: > You are correct. My premise was a bit off. A better one would be: > Before implementing a routine, it is necessary to determine what the > routine must accomplish. A very effective method of doing this is to > document the specification for the routine in the form of pre- and > post-conditions. Once this is done, the routine can be coded such that it > meets the post-condition based on the pre-condition. There may be a misunderstanding here. In my stack equality example, there were NO precoditions. I think that the check if L.Top /= R.Top then return False; end if; was (incorrectly) interpreted as some kind of precondition check. But this interpretation is incorrect. This fragment means, if the stacks don't have the same depth, then they aren't equal. > In the quoted example, documenting the pre-condition would have helped to > uncover the fact that containers of different sizes would need to be dealt > with. In my original example, there weren't any preconditions. > It would become obvious that a pre-condition of l.size = r.size > would not be appropriate and thus that the negation of this condition would > need to be dealt with in the implementation. The stacks I was comparing in my example all had the same (max) size. The check I was making was for different depths. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Jim Cochrane 1 sibling, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-03 0:00 UTC (permalink / raw) > if L.Top /= R.Top then > return False; > end if; Jim Cochrane is right: this precondition comment was discussing the C++ fragment from Robert Martin. However, to help historians here, I didn't misinterpret your code as a precondition. I misinterpreted it as checking the first item on the stack (you know, the stuff at the `top'). Hence, given those semantics, I thought it necessary to add the precondition l.count = r.count However, addressing Richard Melvin's comment that this is an abuse of DBC, I actually don't agree. While, as Jim Cochrane says, it is better to think through the required preconditions and the desired postcondition, and determine exactly what the routine needs to do, it is still *good* practise to document *requirements of the actual routine* (even if they are less than satisfactory). That way, client programmers have a chance to decide: (i) exactly what to check before using the routine (ii) whether they want to use the routine at all. I'll give you an example: Pylon is a small, lightweight and portable data structure library written in Eiffel. It has some pretty interesting, well designed features. However, one of the features I disliked was the insertion procedure on SETs. Among other preconditions, it required: not_in_set: not has (v) --where v is the input argument Now, for a SET class, I thought that this was an unreasonable request. (Isn't it part of this container's job to handle SETness, as opposed to BAGness?) I was able to determine the exact behaviour extremely efficiently, thanks to this documentation. I was also able to determine that ISE's open source data structure library, EiffelBase, handled insertion to the SET as I would've expected. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Loryn Jenkins @ 1998-09-03 0:00 ` Jim Cochrane 1 sibling, 0 replies; 510+ messages in thread From: Jim Cochrane @ 1998-09-03 0:00 UTC (permalink / raw) In article <m3g1ea5b93.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: >jtc@dimensional.com (Jim Cochrane) writes: > >> You are correct. My premise was a bit off. A better one would be: >> Before implementing a routine, it is necessary to determine what the >> routine must accomplish. A very effective method of doing this is to >> document the specification for the routine in the form of pre- and >> post-conditions. Once this is done, the routine can be coded such that it >> meets the post-condition based on the pre-condition. > >There may be a misunderstanding here. In my stack equality example, >there were NO precoditions. > Um, yes, there is a misunderstanding :-). I was responding to someone who was resonding to a previous post of mine, which was commenting on someone else's response to an example posted by Robert Martin. That is, the code being discussed is Robert's code, in which he forgot to deal with the fact that the two containers could have different sizes (number of elements). >I think that the check > > if L.Top /= R.Top then > return False; > end if; > >was (incorrectly) interpreted as some kind of precondition check. But >this interpretation is incorrect. > >This fragment means, if the stacks don't have the same depth, then they >aren't equal. > >> In the quoted example, documenting the pre-condition would have helped to >> uncover the fact that containers of different sizes would need to be dealt >> with. > >In my original example, there weren't any preconditions. > >> It would become obvious that a pre-condition of l.size = r.size >> would not be appropriate and thus that the negation of this condition would >> need to be dealt with in the implementation. > >The stacks I was comparing in my example all had the same (max) size. >The check I was making was for different depths. At the risk of adding more confusion, by l.size ... I meant the number of elements in l, not the maximum size - and again, this was discussing a code snippet that Robert Martin had posted. Sorry for the confusion. -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin ` (4 preceding siblings ...) 1998-09-01 0:00 ` Richard Melvin @ 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Biju Thomas 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-01 0:00 ` Chris Brand 6 siblings, 2 replies; 510+ messages in thread From: Phil Goodwin @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sf87j$47n$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Matthew Heaney wrote in message ... > > > > >Would the implementation be better by not using multiple returns? > > Yes. Imagine that you had to change the function to make it thread safe; > and that the way to do that was to sieze and release a mutex while the > function was executing. As written you would have to add the release in > three separate places. But if you had avoided the multiple returns, you > would have had a single release. Or you could use the Initialization is Resource Aquisition idiom and thereby choose not to have the problem in the first place, takes care of 'returns' caused by exceptions as well. You could also choose to refactor the code at the time that you are adding the mutex. First rewrite the routine with a single return and no mutex and test it to make sure that it still works and then add the mutex and the single release. I write plenty of little routines that have loops in them that exit in the middle. It doesn't make sense to me to alter the algorithm and write extra code just so that the routine might be easier to maintain someday (if ever). On the other hand, when I DO maintain such a routine I definitely WILL make sure that there is only one exit point if that's what is needed to eliminate duplicate code. I adopted this position in part because of some of what I've read about Extreme Programming. I haven't adopted it wholesale, but I do like their no-nonsense philosophy. They use two balancing maxims that I've applied to this question: Do The Simpest Thing That Could Possibly Work; and Once And Only Once. So when I write a function I do the simplest thing that could possibly work, which sometimes means sticking a return right smack in the middle of a loop. I am especially likely to do this when the loop body is less than five lines long anyway. Then, when I have to refactor in order to add the aquisistion and release of some resource, I rearrange the routine so that I add the code once and only once. The justification for this is that I don't want to adopt a coding task because it _might_ be needed during maintenance, I would rather do it during maintenance when I KNOW that it needs to be done. Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Phil Goodwin @ 1998-09-01 0:00 ` Biju Thomas 1998-09-02 0:00 ` Phil Goodwin 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1 sibling, 1 reply; 510+ messages in thread From: Biju Thomas @ 1998-09-01 0:00 UTC (permalink / raw) Phil Goodwin wrote: > > I write plenty of little routines that have loops in them that exit in the > middle. It doesn't make sense to me to alter the algorithm and write extra > code just so that the routine might be easier to maintain someday (if ever). > On the other hand, when I DO maintain such a routine I definitely WILL make > sure that there is only one exit point if that's what is needed to eliminate > duplicate code. > > I adopted this position in part because of some of what I've read about > Extreme Programming. I haven't adopted it wholesale, but I do like their > no-nonsense philosophy. They use two balancing maxims that I've applied to > this question: Do The Simpest Thing That Could Possibly Work; and Once And > Only Once. So when I write a function I do the simplest thing that could > possibly work, which sometimes means sticking a return right smack in the > middle of a loop. I am especially likely to do this when the loop body is > less than five lines long anyway. Then, when I have to refactor in order to > add the aquisistion and release of some resource, I rearrange the routine so > that I add the code once and only once. The justification for this is that I > don't want to adopt a coding task because it _might_ be needed during > maintenance, I would rather do it during maintenance when I KNOW that it > needs to be done. The problem with such refactoring during maintenance is that it may introduce new problems, and you need to do extensive testing to make sure that you haven't broken anything. Often, this type of extensive testing may not be feasible at all during maintenance, because of budget and time constraints. This type of attitude may explain why new releases of software (which are supposed to do bug fixing too) introduce more bugs than the original version. Biju Thomas ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Biju Thomas @ 1998-09-02 0:00 ` Phil Goodwin 1998-09-02 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Phil Goodwin @ 1998-09-02 0:00 UTC (permalink / raw) In article <35EC937F.94420C51@ibm.net>, bijuthom@ibm.net wrote: > Phil Goodwin wrote: > > > > I write plenty of little routines that have loops in them that exit in the > > middle. It doesn't make sense to me to alter the algorithm and write extra > > code just so that the routine might be easier to maintain someday (if ever). > > On the other hand, when I DO maintain such a routine I definitely WILL make > > sure that there is only one exit point if that's what is needed to eliminate > > duplicate code. > > > > I adopted this position in part because of some of what I've read about > > Extreme Programming. I haven't adopted it wholesale, but I do like their > > no-nonsense philosophy. They use two balancing maxims that I've applied to > > this question: Do The Simpest Thing That Could Possibly Work; and Once And > > Only Once. So when I write a function I do the simplest thing that could > > possibly work, which sometimes means sticking a return right smack in the > > middle of a loop. I am especially likely to do this when the loop body is > > less than five lines long anyway. Then, when I have to refactor in order to > > add the aquisistion and release of some resource, I rearrange the routine so > > that I add the code once and only once. The justification for this is that I > > don't want to adopt a coding task because it _might_ be needed during > > maintenance, I would rather do it during maintenance when I KNOW that it > > needs to be done. > > The problem with such refactoring during maintenance is that it may > introduce new problems, and you need to do extensive testing to make > sure that you haven't broken anything. Often, this type of extensive > testing may not be feasible at all during maintenance, because of budget > and time constraints. This type of attitude may explain why new releases > of software (which are supposed to do bug fixing too) introduce more > bugs than the original version. I would posit that if you are changing the function at all you must do a complete regression test on it. I grant you that the more you change the routine the more likely you are to introduce bugs and that is an important consideration. However, what we are doing here is deffering the risk of creating a more complicated algorithm to the point in time where we know that the risk is worthwhile. The only other option is to assume that the risk will always turn out to be worthwhile and code the more complicated algorithm in every case. Since we know that we aren't going to reap the benefit of the complicated algorithm in every case we can surmise that we have done too much work. My position is not that strict structured programming has no benefit, it is that it has a cost and that the cost is not justified unless the benefit is recieved. The strategy I outlined is designed to defer the cost until the benefit reaches its highest value. Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Phil Goodwin @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Phil Goodwin 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Phil Goodwin wrote in message <6sk01j$1qn$1@nnrp1.dejanews.com>... > >I would posit that if you are changing the function at all you must do a >complete regression test on it. I grant you that the more you change the >routine the more likely you are to introduce bugs and that is an important >consideration. However, what we are doing here is deffering the risk of >creating a more complicated algorithm to the point in time where we know that >the risk is worthwhile. Unfortunately, by the time you know that the structure is wrong, it is often difficult to justify making it right. It is almost always easier to find a clever fix than it is to restructure so that the clever fix isn't necessary. (witness the windowing technique for fixing Y2K bugs). Now, you might suggest that once faced with the choice of clever fix or refactoring, one should always choose refactoring. But I will respond to that with two points. 1. Your premise is that you shouldn't pay for a risk you aren't sure will materialize. Since you don't know that you'll need another clever fix, your premise will lead you to simply make the current clever fix. 2. Multiple returns *were* the first clever fix. If you look at these two statements carefully you will realize that they form the essense of inductive reasoning; leading to the conclusion that true refactoring will never happen. I take slightly different view. If the cost of protecting myself from risk is low, and if the cost of the risk materializing is high, then I will pay for the risk up front. It's like buying insurance. >The only other option is to assume that the risk will >always turn out to be worthwhile and code the more complicated algorithm in >every case. Again, if cost of the more complex algorithm is low, and if the cost of the risk is high, then this may not be a bad decision. >My position is not that strict structured programming has no benefit, it is >that it has a cost and that the cost is not justified unless the benefit is >recieved. Is the cost of your medical insurance, or your auto insurance, or your life insurance justified? Of course it is! (and you should see my health insurance rates!) The reason it is justified is that the potential downside is enormous. So the justificaton of a maintainable approach must be that the downside potential is high enough to get us to gladly pay the up front costs of protection. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Phil Goodwin 1998-09-03 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Phil Goodwin @ 1998-09-03 0:00 UTC (permalink / raw) Comments interspersed... In article <6skerj$1u5$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Phil Goodwin wrote in message <6sk01j$1qn$1@nnrp1.dejanews.com>... > > > >I would posit that if you are changing the function at all you must do a > >complete regression test on it. I grant you that the more you change the > >routine the more likely you are to introduce bugs and that is an important > >consideration. However, what we are doing here is deffering the risk of > >creating a more complicated algorithm to the point in time where we know > that > >the risk is worthwhile. > > Unfortunately, by the time you know that the structure is wrong, it is often > difficult to justify making it right. It is almost always easier to find a > clever fix than it is to restructure so that the clever fix isn't necessary. > (witness the windowing technique for fixing Y2K bugs). Then you must either arrange things so that you never have to restructure or you must have some way to know when to restructure rather than make a 'clever fix'. > Now, you might > suggest that once faced with the choice of clever fix or refactoring, one > should always choose refactoring. But I will respond to that with two > points. I might suggest that, but, as it happens I will not... > 1. Your premise is that you shouldn't pay for a risk you aren't sure will > materialize. Since you don't know that you'll need another clever fix, your > premise will lead you to simply make the current clever fix. > > 2. Multiple returns *were* the first clever fix. > > If you look at these two statements carefully you will realize that they > form the essense of inductive reasoning; leading to the conclusion that true > refactoring will never happen. Right, the premise that you should Do The Simplest Thing That Could Possibly Work isn't powerful enough to enable decisions in all cases. There is another useful premise that the Extreme Programming guys call "Once And Only Once" that is used to trigger refactoring. In short, in prohibits 'clever tricks' that lead to code duplication. The Once And Only Once rule will save us from making the mistakes that you have presented in your examples. It may turn out to be insufficient to overcome all the shortcomings of Do The Simplest Thing That Could Possibly Work, but I'm not aware of any examples where it doesn't. > I take slightly different view. If the cost of protecting myself from risk > is low, and if the cost of the risk materializing is high, then I will pay > for the risk up front. It's like buying insurance. > > >The only other option is to assume that the risk will > >always turn out to be worthwhile and code the more complicated algorithm in > >every case. > > Again, if cost of the more complex algorithm is low, and if the cost of the > risk is high, then this may not be a bad decision. > > >My position is not that strict structured programming has no benefit, it is > >that it has a cost and that the cost is not justified unless the benefit is > >recieved. > > Is the cost of your medical insurance, or your auto insurance, or your life > insurance justified? > Of course it is! (and you should see my health insurance rates!) The > reason it is justified is that the potential downside is enormous. > > So the justificaton of a maintainable approach must be that the downside > potential is high enough to get us to gladly pay the up front costs of > protection. So, you are saying that, in the cases where the risk DOES turn out to be worthwhile the value is so great that it outweighs the cost in all the other cases where the precaution turned out to be unnecessary? I think that this is sound reasoning, but it hinges on the premise that the realized value is very great. So you insure your home but not your plastic lawn furniture. I advocate for using SE/SE on large complicated functions, but not always on small simple ones. The message that I'm interested in conveying is not that the rule is bad and should be thrown out, but rather that it shouldn't be rigidly applied in every circumstance. Knowing why the rule exists at all and what benefit following it confers is IMHO far more important than always following it to the letter because it's a Good Thing. Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Phil Goodwin @ 1998-09-03 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Phil Goodwin wrote in message <6smrvi$86c$1@nnrp1.dejanews.com>... > >The message that I'm interested in conveying is not that the rule is bad and >should be thrown out, but rather that it shouldn't be rigidly applied in every >circumstance. Knowing why the rule exists at all and what benefit following it >confers is IMHO far more important than always following it to the letter >because it's a Good Thing. Then we are in agreement. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Biju Thomas @ 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1 sibling, 0 replies; 510+ messages in thread From: Ole-Hjalmar Kristensen @ 1998-09-03 0:00 UTC (permalink / raw) Phil Goodwin<pgoodwin@my-dejanews.com> writes: > In article <6sf87j$47n$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: > > > > Matthew Heaney wrote in message ... > > > > > > > >Would the implementation be better by not using multiple returns? > > > > Yes. Imagine that you had to change the function to make it thread safe; > > and that the way to do that was to sieze and release a mutex while the > > function was executing. As written you would have to add the release in > > three separate places. But if you had avoided the multiple returns, you > > would have had a single release. > > Or you could use the Initialization is Resource Aquisition idiom and thereby > choose not to have the problem in the first place, takes care of 'returns' > caused by exceptions as well. > > You could also choose to refactor the code at the time that you are adding > the mutex. First rewrite the routine with a single return and no mutex and > test it to make sure that it still works and then add the mutex and the > single release. > > I write plenty of little routines that have loops in them that exit in the > middle. It doesn't make sense to me to alter the algorithm and write extra > code just so that the routine might be easier to maintain someday (if ever). > On the other hand, when I DO maintain such a routine I definitely WILL make > sure that there is only one exit point if that's what is needed to eliminate > duplicate code. > > I adopted this position in part because of some of what I've read about > Extreme Programming. I haven't adopted it wholesale, but I do like their > no-nonsense philosophy. They use two balancing maxims that I've applied to > this question: Do The Simpest Thing That Could Possibly Work; and Once And > Only Once. So when I write a function I do the simplest thing that could > possibly work, which sometimes means sticking a return right smack in the > middle of a loop. I am especially likely to do this when the loop body is > less than five lines long anyway. Then, when I have to refactor in order to > add the aquisistion and release of some resource, I rearrange the routine so > that I add the code once and only once. The justification for this is that I > don't want to adopt a coding task because it _might_ be needed during > maintenance, I would rather do it during maintenance when I KNOW that it > needs to be done. > > Phil > > -----== Posted via Deja News, The Leader in Internet Discussion ==----- > http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum Yes. Another useful principle is to refactor the code by adding another subroutine which does the aquisition and release, and calls the exixting routine in between. This avoids changing the semantics of the existing routine, which may be desirable. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin ` (5 preceding siblings ...) 1998-09-01 0:00 ` Phil Goodwin @ 1998-09-01 0:00 ` Chris Brand 1998-09-01 0:00 ` Robert Martin 6 siblings, 1 reply; 510+ messages in thread From: Chris Brand @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > > bool operator==(Stack& l, Stack& r) > { > bool equal = true; > for (int index = 1; index < l.top() && equal == true; index++) > { > if (l[index] != r[index]) > equal = false; > } > return equal; > } > > If this is more complex (something that is arguable) it is not *much* more > complex. On the other hand, it is easier to maintain. It is open to (maintenance) errors such as for (int index = 1; index < l.top() && equal = true; index++) which the multiple-return version isn't, so the "easier to maintain" argument is far from clear-cut. -- Chris An extra line to keep my news server happy ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Chris Brand @ 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Biju Thomas 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Chris Brand wrote in message <35EC3440.9FA81BF1@west.raytheon.com>... >Robert Martin wrote: >> >> bool operator==(Stack& l, Stack& r) >> { >> bool equal = true; >> for (int index = 1; index < l.top() && equal == true; index++) >> { >> if (l[index] != r[index]) >> equal = false; >> } >> return equal; >> } >> >> If this is more complex (something that is arguable) it is not *much* more >> complex. On the other hand, it is easier to maintain. > >It is open to (maintenance) errors such as > for (int index = 1; index < l.top() && equal = true; index++) >which the multiple-return version isn't, so the "easier to maintain" >argument is far from clear-cut. I think *all* structures are vulnerable to typos. The code above is no more vulnerable than any other code is. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Biju Thomas 1998-09-01 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Biju Thomas @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > > Chris Brand wrote in message <35EC3440.9FA81BF1@west.raytheon.com>... > >Robert Martin wrote: > >> > >> bool operator==(Stack& l, Stack& r) > >> { > >> bool equal = true; > >> for (int index = 1; index < l.top() && equal == true; index++) > >> { > >> if (l[index] != r[index]) > >> equal = false; > >> } > >> return equal; > >> } > >> > >> If this is more complex (something that is arguable) it is not *much* > more > >> complex. On the other hand, it is easier to maintain. > > > >It is open to (maintenance) errors such as > > for (int index = 1; index < l.top() && equal = true; index++) > >which the multiple-return version isn't, so the "easier to maintain" > >argument is far from clear-cut. > > I think *all* structures are vulnerable to typos. The code above is no more > vulnerable than any other code is. If it was 1) for (int index = 1; index < l.top() && equal; index++) or 2) for (int index = 1; index < l.top() && true == equal; index++) it might not have been vulnerable to this type of typos (which is frequent in C++, I think). Of course, some people say the second style is less readable. But the the first one seems to be best. Biju Thomas ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Biju Thomas @ 1998-09-01 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Biju Thomas wrote in message <35EC91EB.BEF1DB23@ibm.net>... > >If it was >1) > for (int index = 1; index < l.top() && equal; index++) > >or >2) > for (int index = 1; index < l.top() && true == equal; index++) > >it might not have been vulnerable to this type of typos (which is >frequent in C++, I think). Not very frequent. First, most compilers issue warnings when structures like "a=b" appear in a conditional context (e.g. if (a=0)) Secondly, you only need make the mistake a few times before you <<know>>. >Of course, some people say the second style is less readable. But the >the first one seems to be best. I agree. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Tim McDermott 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Don Harrison 3 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-01 0:00 UTC (permalink / raw) How is this more complicated? equal (l,r: LIST): BOOLEAN is require l.count = r.count do Result := l.first /= r.first if Result then from l.start; r.start until not Result or l.off loop Result := l.item /= r.item l.forth; r.forth end end end Sorry for the language change ... it's the one I'm familiar with. By the way, I'm not sure whether it's a problem in your Ada code, but my Eiffel code could fail if r has greater or fewer items than l. Hence the precondition. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Loryn Jenkins @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Loryn Jenkins ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> writes: > How is this more complicated? > > equal (l,r: LIST): BOOLEAN is > require > l.count = r.count > do > Result := l.first /= r.first > if Result then > from > l.start; r.start > until > not Result or l.off > loop > Result := l.item /= r.item > l.forth; r.forth > end > end > end There are a few things I don't like about this: 1) You have to test a flag every iteration of the loop. That adds (a marginal amount of) inefficiency. 2) The loop predicate has 4 possible values. The original example had only 2. 3) There's more nesting. So yes, I feel the above implementation is more complex than the original implementation that used muliple returns. > Sorry for the language change ... it's the one I'm familiar with. AOK, I understood it OK. (I also read the 1st ed of Bertrand's book.) > By the way, I'm not sure whether it's a problem in your Ada code, but my > Eiffel code could fail if r has greater or fewer items than l. Hence the > precondition. That's what the check L.Top /= R.Top means: if the number of items is different, then you know immediately that the stacks can't be equal. When you reach the loop, you know the stack depths are the same. The way I look at this problem, is that it's like searching for a specific house on an unfamiliar block. As you're driving, when you find the house, you stop immediately and declare success. You don't have to drive to the end of the block, and then say where the house was. Likewise for the example I provided. Once you determine that the stacks are unequal, you quit and go home. You don't need go all the way to the end of the subprogram to declare victory (unless of course the stacks happen to really be equal). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Charles Hixson 1998-09-01 0:00 ` dewarr 1998-09-04 0:00 ` Jean-Marc Jezequel 2 siblings, 2 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-01 0:00 UTC (permalink / raw) Matthew Heaney wrote: > > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > How is this more complicated? > > > > equal (l,r: LIST): BOOLEAN is > > require > > l.count = r.count > > do > > Result := l.first /= r.first > > if Result then > > from > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := l.item /= r.item > > l.forth; r.forth > > end > > end > > end > > There are a few things I don't like about this: > > 1) You have to test a flag every iteration of the loop. That adds (a > marginal amount of) inefficiency. Oh well. I can live with that. (Unless my profiler tells me it is in a hot spot ... which doesn't happen too often.) > 2) The loop predicate has 4 possible values. The original example had > only 2. And you had two exit points, and I have one. (Probably because I'm not familiar with your style) I actually have to work a bit harder than reading my version. > 3) There's more nesting. Sorry, I don't see that. You have one for loop and an if statement. I have one if statement and a loop. Seems the same amount of nesting to me. > So yes, I feel the above implementation is more complex than the > original implementation that used muliple returns. Oh well, we'll have to agree to disagree then. > That's what the check L.Top /= R.Top means: if the number of items is > different, then you know immediately that the stacks can't be equal. > When you reach the loop, you know the stack depths are the same. Ah! For some reason, I thought you were testing the first item on the stack. So, my amended code, to match your semantics is thus: equal (l,r: LIST): BOOLEAN is require l /= Void and r /= Void do Result := l.count /= r.count if Result then from l.start; r.start until not Result or l.off loop Result := l.item /= r.item l.forth; r.forth end end end > The way I look at this problem, is that it's like searching for a > specific house on an unfamiliar block. As you're driving, when you find > the house, you stop immediately and declare success. You don't have to > drive to the end of the block, and then say where the house was. Yeah, yeah. Same here, given the amended code. Loryn Jenkins PS: I really would agree with you if the only counter examples were Tim McDermott's and Jim Cochrane's ones. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Loryn Jenkins @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` James Weirich 1998-09-02 0:00 ` Loryn Jenkins 1998-09-04 0:00 ` Charles Hixson 1 sibling, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> writes: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > Result := l.count /= r.count > if Result then > from > l.start; r.start > until > not Result or l.off > loop > Result := l.item /= r.item > l.forth; r.forth > end > end > end > > > > The way I look at this problem, is that it's like searching for a > > specific house on an unfamiliar block. As you're driving, when you find > > the house, you stop immediately and declare success. You don't have to > > drive to the end of the block, and then say where the house was. > > Yeah, yeah. Same here, given the amended code. No, no, not the same here. If the test l.count /= r.count returns False, then you know immediately what the return value of the function is, so why not deliver that information right away? That way you can remove the test of result (reducing the level of nesting), and simplify the predicate, (By way of analogy, if you've found the house, then you can park in the driveway right way, instead of driving to the end of the block to announce that you found the house.) Let's once again compare the decision tables. If we re-write the code, to put it into Matt-like (because Matt likes it) syntax: equal (l,r: LIST): BOOLEAN is require l /= Void and r /= Void do if l.count /= r.count then return False end from l.start; r.start until l.off loop if l.item /= r.item then return False end l.forth; r.forth end return True end This version has only two rules in the decision table for the loop predicate: 1 2 l.off T F The uncorrected version has four rules: 1 2 3 4 not Result T T F F l.off T F T F The difference in styles is really a debate about the number of edges in the flow graph vs the number of rules in the decision table. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` James Weirich 1998-09-01 0:00 ` Mike Spille 1998-09-02 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: James Weirich @ 1998-09-01 0:00 UTC (permalink / raw) Matthew> Let's once again compare the decision tables. If we Matthew> re-write the code, to put it into Matt-like (because Matt Matthew> likes it) syntax: Matthew> equal (l,r: LIST): BOOLEAN is Matthew> require Matthew> l /= Void and r /= Void Matthew> do Matthew> if l.count /= r.count then Matthew> return False Matthew> end Matthew> from Matthew> l.start; r.start Matthew> until Matthew> l.off Matthew> loop Matthew> if l.item /= r.item then Matthew> return False Matthew> end Matthew> l.forth; r.forth Matthew> end Matthew> return True Matthew> end Matthew> This version has only two rules in the decision table for Matthew> the loop predicate: Matthew> 1 2 Matthew> l.off T F Yes, but you are ignoring the fact that there are now two loop exits. If you ask the question "When will the loop terminate?", you must consider all the exits, including the early return. So instead of a single, 2 entry table, you have two 2-entry tables. Combining them into a single table will produce the same 4 entry table as the one you produced for Loryn Jenkins's code. Seems to me the complexity is about equivalent. -- -- Jim Weirich jweirich@one.net http://w3.one.net/~jweirich --------------------------------------------------------------------- -- "A distributed system is one in which I cannot get something done -- because a machine I've never heard of is down." --Leslie Lamport ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` James Weirich @ 1998-09-01 0:00 ` Mike Spille 1998-09-02 0:00 ` Nick Leaton 0 siblings, 1 reply; 510+ messages in thread From: Mike Spille @ 1998-09-01 0:00 UTC (permalink / raw) James Weirich wrote: > > Matthew> Let's once again compare the decision tables. If we > Matthew> re-write the code, to put it into Matt-like (because Matt > Matthew> likes it) syntax: > > Matthew> equal (l,r: LIST): BOOLEAN is > Matthew> require > Matthew> l /= Void and r /= Void > Matthew> do > Matthew> if l.count /= r.count then > Matthew> return False > Matthew> end > Matthew> from > Matthew> l.start; r.start > Matthew> until > Matthew> l.off > Matthew> loop > Matthew> if l.item /= r.item then > Matthew> return False > Matthew> end > Matthew> l.forth; r.forth > Matthew> end > Matthew> return True > Matthew> end > > Matthew> This version has only two rules in the decision table for > Matthew> the loop predicate: > > Matthew> 1 2 > Matthew> l.off T F > > Yes, but you are ignoring the fact that there are now two loop exits. > If you ask the question "When will the loop terminate?", you must > consider all the exits, including the early return. > Would your average programmer ask the question "Where will the loop terminate?", or "What does the function do?". I think the latter question is alot more important. I personally subscribe to the technique of "bailing-out" as soon as possible in a function. This has two effects: nesting later on is greatly reduced (I find if-else nesting affects readability), and the early-bailouts give me guarantees later in the code that I don't need to check for. > So instead of a single, 2 entry table, you have two 2-entry tables. > Combining them into a single table will produce the same 4 entry table > as the one you produced for Loryn Jenkins's code. > > Seems to me the complexity is about equivalent. > > -- > -- Jim Weirich jweirich@one.net http://w3.one.net/~jweirich > --------------------------------------------------------------------- > -- "A distributed system is one in which I cannot get something done > -- because a machine I've never heard of is down." --Leslie Lamport -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Mike Spille @ 1998-09-02 0:00 ` Nick Leaton 0 siblings, 0 replies; 510+ messages in thread From: Nick Leaton @ 1998-09-02 0:00 UTC (permalink / raw) Mike Spille wrote: > > Would your average programmer ask the question "Where will the loop > terminate?", or "What does the function do?". I think the latter > question is alot more important. I personally subscribe to > the technique of "bailing-out" as soon as possible in a function. > > This has two effects: nesting later on is greatly reduced (I find > if-else nesting affects readability), and the early-bailouts give > me guarantees later in the code that I don't need to check for. > This doesn't tend to happen in Eiffel, all because of preconditions. The preconditions and postconditions, name of the routine and a comment tell you what the routine does. Early bailout is usually implements checks on arguments passed in, and if they are not consistent, then exits with an error. In Eiffel, this is removed because of the support for DBC. As such, you don't get much nesting, and as has been posted, you can solve the compare two stacks without the loop in an if-then statement. The nesting of the loop in the if then statement is a optimisation, which with a decent compiler, would be optimised out anyway. -- Nick ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` James Weirich @ 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan ` (3 more replies) 1 sibling, 4 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote: > > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > > > equal (l,r: LIST): BOOLEAN is > > require > > l /= Void and r /= Void > > do > > Result := l.count /= r.count > > if Result then > > from > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := l.item /= r.item > > l.forth; r.forth > > end > > end > > end > > > > > > > The way I look at this problem, is that it's like searching for a > > > specific house on an unfamiliar block. As you're driving, when you find > > > the house, you stop immediately and declare success. You don't have to > > > drive to the end of the block, and then say where the house was. > > > > Yeah, yeah. Same here, given the amended code. > > No, no, not the same here. > > If the test l.count /= r.count returns False, then you know immediately > what the return value of the function is, so why not deliver that > information right away? That way you can remove the test of result > (reducing the level of nesting), and simplify the predicate, > > (By way of analogy, if you've found the house, then you can park in the > driveway right way, instead of driving to the end of the block to > announce that you found the house.) > > Let's once again compare the decision tables. If we re-write the code, > to put it into Matt-like (because Matt likes it) syntax: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > if l.count /= r.count then > return False > end > > from > l.start; r.start > until > l.off > loop > if l.item /= r.item then > return False > end > > l.forth; r.forth > end > > return True > end > > This version has only two rules in the decision table for the loop predicate: > > 1 2 > l.off T F > > The uncorrected version has four rules: > > 1 2 3 4 > not Result T T F F > l.off T F T F > > The difference in styles is really a debate about the number of edges in > the flow graph vs the number of rules in the decision table. That we can agree on. But also note James Weirich's comment: >Yes, but you are ignoring the fact that there are now two loop exits. >If you ask the question "When will the loop terminate?", you must >consider all the exits, including the early return. > >So instead of a single, 2 entry table, you have two 2-entry tables. >Combining them into a single table will produce the same 4 entry table >as the one you produced for Loryn Jenkins's code. > >Seems to me the complexity is about equivalent. Now, someone else was kind enough to show me an even simpler way of doing this ... albeit marginally less efficient (and again, I don't care about this criteria, unless my application beforms below specification and my profiler shows me that this is a hot spot). equal (l,r: LIST): BOOLEAN is require l /= Void and r /= Void do from Result := (l.count = r.count) l.start; r.start until not Result or l.off loop Result := (l.item = r.item) l.forth; r.forth end end This, at least, loses your nesting objection. In fact, it has less nesting than your original example. However, it might mislead unless the reader was aware of this sort of idiom. (It does simplify things though; so I think I'll be using this style, where appropriate.) Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Loryn Jenkins @ 1998-09-01 0:00 ` John Volan 1998-09-01 0:00 ` Robert Martin ` (2 more replies) 1998-09-01 0:00 ` Darren New ` (2 subsequent siblings) 3 siblings, 3 replies; 510+ messages in thread From: John Volan @ 1998-09-01 0:00 UTC (permalink / raw) Loryn Jenkins wrote: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > from > Result := (l.count = r.count) > l.start; r.start > until > not Result or l.off > loop > Result := (l.item = r.item) > l.forth; r.forth > end > end This has a certain elegance, but note that: (1) If Result is False after the first assignment, then the 'start' calls are executed unnecessarily. (2) If Result is False after the second assignment (in the body of the loop), then the 'forth' calls and the 'off' test are executed unnessarily. This is inefficient (as you point out) but at least it is harmless ... in this case. (More on that in a moment.) However, suppose Eiffel allowed mid-body loop exits, say with the following sort of syntax: equal (l, r: LIST): BOOLEAN is require l /= Void and r /= Void do Result := (l.count = r.count) if Result then from l.start; r.start until l.off loop Result := (l.item = r.item) until not Result then l.forth; r.forth end end end The 'if' statement avoids the extraneous 'start' calls. The mid-body 'until' clause terminates the loop immediately if its condition holds, avoiding the extraneous 'forth' calls, as well as the 'off' test at the top of the loop. Can anybody demonstrate whether or not this sort of language extension would have an adverse affect on Eiffel's principle of DBC, for the case of loops? There are situations where extraneous calls in the final loop iteration would not be so harmless. For instance, suppose you wished to implement an 'out' function for a LIST class that generated strings of the form: "{}" for an empty list "{A}" for a list with one element "A" "{A, B}" for a list with two elements "A" and "B" etc... In other words, separate the elements by commas, but only if there is more than one element. Here's a first attempt at a solution: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) Result.append (", "); forth end loop end Result.append ("}"); end Unfortunately, this is incorrect, because it places an extraneous comma after the last element. To correct this, we could add a test within the body: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) forth if not after then Result.append (", "); end end loop Result.append ("}"); end Unfortunately, this causes the same 'after' test to be called twice on each iteration! To avoid this, we must unroll the loop: out: STRING is do Result := "{"; if not empty then from start Result.append (item.out) forth until after loop Result.append (", "); Result.append (item.out) forth end loop end Result.append ("}"); end Unfortunately, we've been forced to duplicate code. But suppose you could place an 'until' clause in mid-body: out: STRING is do Result := "{" if not empty then from start loop Result.append (item.out) forth until after then Result.append (", ") end end Result.append ("}") end This would seem the most elegant solution. But again, does this pose any difficulty for DBC in Eiffel? I can't see any problem, but I'm only a newbie with Eiffel. (Just now in the process of devouring OOSC2 from one cover to the other...) -- indexing description: "Signatures for John Volan" self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe" two_cents: "Java would be even cooler with Eiffel's generics, % %assertions/DBC, true MI, feature adaptation, % %selective export, uniform access, etc., etc..." class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant disclaimer: not (opinion implies employer.opinion) end -- class JOHN_VOLAN_SIGNATURE ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` John Volan @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Chris Saunders 1998-09-02 0:00 ` Nick Leaton 2 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) John Volan wrote in message <35ECB8F1.6B33FA56@ac3i.dseg.ti.com>... >There are situations where extraneous calls in the final loop iteration >would not be so harmless. For instance, suppose you wished to implement >an 'out' function for a LIST class that generated strings of the form: > > "{}" for an empty list > "{A}" for a list with one element "A" > "{A, B}" for a list with two elements "A" and "B" > etc... Another solution to this problem is (in C++) void PrintList(vector<string>& list) { cout << "{"; string separator = ""; vector<string>::iterator i; for (i = list.begin(); i != list.end(); i++) { cout << separator << *i; separator = ", "; } cout << "}" << endl; } This is a bit inefficient because the separator variable is needlessly set to ", " in every iteration of the loop. If this inefficiency is really too much to deal with, then we can create a special class to deal with it: class Separator { public: virtual void Separate(ostream& o) = 0; static Separator* theSeparator = &initial; static InitialSeparator initial; static CommanSeparator comma; }; class InitialSeparator : public Separator { public: virtual void Separate(ostream& o) { theSeparator = , } }; class CommaSeparator : public Separator { public: virtual void Separate(ostream& o) { o << ", "; } }; void PrintList(vector<string>& list) { cout << "{"; vector<string>::iterator i; for (i = list.begin(); i != list.end(); i++) { theSeparator.Separate(); cout << *i; } cout << "}" << endl; } This uses the a variation of the 'State' pattern from the Design Patterns book to implement a little finite state machine that ensures that the list is output properly. Actually, a finite state machine is probably a good way to represent this algorithm... The following is a simple state transition table: currentstate event newstate action ------------ ----- -------- ---------------- Starting Start Initial {OutputOpenBrace} Initial Item Subsequent {OutputItem} Initial Done EndState {OutputClosingBrace} Subsequent Item Subsequent {OutputComma OutputItem} Subsequent Done EndState {OutputClosingBrace} EndState * * {} Now we could use SMC (see the freeware section of my website) to build the program: class ListPrinter { public: void OutputOpenBrace() {cout << "{";} void OutputClosingBrace() {cout << "}"} void OutputItem() {cout << itsItem;} void OutputComma() {cout << ", ";} void SetItem(string& s) {itsItem = s;} private: string itsItem; }; /////////////////////////// // Input to SMC // Ouput will be a C++ class named ListPrinterFSM // Context ListPrinter FSMName ListPrinterFSM Initial Starting { Starting Start Initial {OutputOpenBrace} Initial Item Subsequent {OutputItem} Initial Done EndState {OutputClosingBrace} Subsequent Item Subsequent {OutputComma OutputItem} Subsequent Done EndState {OutputClosingBrace} EndState * * {} } void PrintList(vector<string>& list) { ListPrinterFSM fsm; fsm.Start(); vector<string>::iterator i; for (i=list.begin(); i != list.end(); i++) { fsm.SetItem(*i); fsm.Item(); } fsm.Done(); } Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` John Volan 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Chris Saunders 1998-09-02 0:00 ` Nick Leaton 2 siblings, 0 replies; 510+ messages in thread From: Chris Saunders @ 1998-09-02 0:00 UTC (permalink / raw) >There are situations where extraneous calls in the final loop iteration >would not be so harmless. For instance, suppose you wished to implement >an 'out' function for a LIST class that generated strings of the form: > > "{}" for an empty list > "{A}" for a list with one element "A" > "{A, B}" for a list with two elements "A" and "B" > etc... > >In other words, separate the elements by commas, but only if there is >more than one element. Here's a first attempt at a solution: > >out: STRING is > do > Result := "{"; > from > start > until > after > loop > Result.append (item.out) > Result.append (", "); > forth > end loop > end > Result.append ("}"); > end > >Unfortunately, this is incorrect, because it places an extraneous comma >after the last element. To correct this, we could add a test within the >body: My suggestion: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) Result.append (", "); forth end loop end Result.prune_all_trailing (',') Result.append ("}"); end In place of prune_all_trailing you could also use head (Result.count - 1) Costs very little overhead and leaves you with a nice looking loop. Regards Chris Saunders saunders@wchat.on.ca ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` John Volan 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Chris Saunders @ 1998-09-02 0:00 ` Nick Leaton 2 siblings, 0 replies; 510+ messages in thread From: Nick Leaton @ 1998-09-02 0:00 UTC (permalink / raw) John Volan wrote: > > Loryn Jenkins wrote: > > > > equal (l,r: LIST): BOOLEAN is > > require > > l /= Void and r /= Void > > do > > from > > Result := (l.count = r.count) > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := (l.item = r.item) > > l.forth; r.forth > > end > > end > > This has a certain elegance, but note that: > > (1) If Result is False after the first assignment, then the 'start' > calls are executed unnecessarily. > > (2) If Result is False after the second assignment (in the body of the > loop), then the 'forth' calls and the 'off' test are executed > unnessarily. If the until clause is changed to not Result or else l.off Then if Result is false l.off is not evaluated. 'or else' and 'and then' are semi-strict boolean operators and only evaluate the right hand side if necessary. -- Nick ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan @ 1998-09-01 0:00 ` Darren New 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan 1998-09-02 0:00 ` Matthew Heaney 3 siblings, 1 reply; 510+ messages in thread From: Darren New @ 1998-09-01 0:00 UTC (permalink / raw) Loryn Jenkins wrote: > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > from > Result := (l.count = r.count) > l.start; r.start > until > not Result or l.off > loop > Result := (l.item = r.item) > l.forth; r.forth > end > end And of course, this becomes much more readable when you use variables whose names mean what they say. equal (l,r: LIST): BOOLEAN is require l /= Void and r /= Void local stacks_are_known_different : BOOLEAN do from stacks_are_known_different := (l.count /= r.count) l.start; r.start until stacks_are_known_different or l.off loop stacks_are_known_different := (l.item /= r.item) l.forth; r.forth end Result := not stacks_are_known_different end (With a minor renaming to get rid of "not". I don't *think* I broke it.) I think picking the proper names for locals invariably clarifies the code, even at the expense of declaring another local. The first time you assign to "Result", you're not assigning the "result". One of my rules of thumb for clear programming is "have a meaning for every variable that is appropriate at every line of the algorithm". Otherwise, you're using the same variable for multiple unrelated values. Here, it's clear just by looking that you know the stacks are different if the counts are different or the items are different, you stop the loop as soon as you know the stacks are different, and the result is whether you know the stacks are different at the bottom of the loop. This is a bit more pendantic than I usually am, but I think it's *very* clear, and certainly more clear than embedded returns. -- Darren New / Senior Software Architect / First Virtual Holdings Inc http://www.fv.com or info@fv.com -=|=- PGP Key: ftp://ftp.fv.com/pub/fv Fingerprint: 61 7D AF 9E 00 CC C2 ED / D8 4C D7 AA E4 C2 A0 73 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Darren New @ 1998-09-02 0:00 ` Loryn Jenkins 1998-09-02 0:00 ` Matthew Heaney 0 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-02 0:00 UTC (permalink / raw) > I think picking the proper names for locals invariably clarifies the > code, even at the expense of declaring another local. The first time you > assign to "Result", you're not assigning the "result". > > One of my rules of thumb for clear programming is "have a meaning for > every variable that is appropriate at every line of the algorithm". > Otherwise, you're using the same variable for multiple unrelated values. > Here, it's clear just by looking that you know the stacks are different > if the counts are different or the items are different, you stop the > loop as soon as you know the stacks are different, and the result is > whether you know the stacks are different at the bottom of the loop. > > This is a bit more pendantic than I usually am, but I think it's *very* > clear, and certainly more clear than embedded returns. That's a very good point. Thanks for making it. Obviously, I'm with you: I agree that this is a clearer to comprehend, easier to maintain style than the embedded returns. Do you still disagree, Matthew? Given that the complexity is pretty similar---perhaps with some complexity shifted from the flowgraph to the decision table---with the resulting complexity being equivalent. And, I think, all your other points have been addressed by this example ... excepting the 'performance' issue. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Loryn Jenkins @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> writes: > Do you still disagree, Matthew? Given that the complexity is pretty > similar---perhaps with some complexity shifted from the flowgraph to the > decision table---with the resulting complexity being equivalent. And, I > think, all your other points have been addressed by this example ... > excepting the 'performance' issue. I like what you did, but still prefer to bail out immediately, once I know that the answer is false. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote: > > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > Do you still disagree, Matthew? Given that the complexity is pretty > > similar---perhaps with some complexity shifted from the flowgraph to the > > decision table---with the resulting complexity being equivalent. And, I > > think, all your other points have been addressed by this example ... > > excepting the 'performance' issue. > > I like what you did, but still prefer to bail out immediately, once I > know that the answer is false. Thanks. That is your right. Thank you for helping facilitate / participating in the most useful (educational) thread I've read for a *long* time. I certainly have come to a better appreciation of 'tree-structured' programming; and although I won't be using it myself, now understand it ain't all bad ... and, if looked at in a certain way, has its advantages. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan 1998-09-01 0:00 ` Darren New @ 1998-09-01 0:00 ` John Volan 1998-09-02 0:00 ` Matthew Heaney 3 siblings, 0 replies; 510+ messages in thread From: John Volan @ 1998-09-01 0:00 UTC (permalink / raw) [Woops! Sorry for the re-post folks, want to fix some egregious typos:] Loryn Jenkins wrote: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > from > Result := (l.count = r.count) > l.start; r.start > until > not Result or l.off > loop > Result := (l.item = r.item) > l.forth; r.forth > end > end This has a certain elegance, but note that: (1) If Result is False after the first assignment, then the 'start' calls are executed unnecessarily. (2) If Result is False after the second assignment (in the body of the loop), then the 'forth' calls and the 'off' test are executed unnessarily. This is inefficient (as you point out) but at least it is harmless ... in this case. (More on that in a moment.) However, suppose Eiffel allowed mid-body loop exits, say with the following sort of syntax: equal (l, r: LIST): BOOLEAN is require l /= Void and r /= Void do Result := (l.count = r.count) if Result then from l.start; r.start until l.off loop Result := (l.item = r.item) until not Result then l.forth; r.forth end end end The 'if' statement avoids the extraneous 'start' calls. The mid-body 'until' clause terminates the loop immediately if its condition holds, avoiding the extraneous 'forth' calls, as well as the 'off' test at the top of the loop. Can anybody demonstrate whether or not this sort of language extension would have an adverse affect on Eiffel's principle of DBC, for the case of loops? There are situations where extraneous calls in the final loop iteration would not be so harmless. For instance, suppose you wished to implement an 'out' function for a LIST class that generated strings of the form: "{}" for an empty list "{A}" for a list with one element "A" "{A, B}" for a list with two elements "A" and "B" etc... In other words, separate the elements by commas, but only if there is more than one element. Here's a first attempt at a solution: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) Result.append (", "); forth end Result.append ("}"); end Unfortunately, this is incorrect, because it places an extraneous comma after the last element. To correct this, we could add a test within the body: out: STRING is do Result := "{"; from start until after loop Result.append (item.out) forth if not after then Result.append (", "); end end Result.append ("}"); end Unfortunately, this causes the same 'after' test to be called twice on each iteration! To avoid this, we must unroll the loop: out: STRING is do Result := "{"; if not empty then from start Result.append (item.out) forth until after loop Result.append (", "); Result.append (item.out) forth end end Result.append ("}"); end Unfortunately, we've been forced to duplicate code. But suppose you could place an 'until' clause in mid-body: out: STRING is do Result := "{" if not empty then from start loop Result.append (item.out) forth until after then Result.append (", ") end end Result.append ("}") end This would seem the most elegant solution. But again, does this pose any difficulty for DBC in Eiffel? I can't see any problem, but I'm only a newbie with Eiffel. (Just now in the process of devouring OOSC2 from one cover to the other...) -- indexing description: "Signatures for John Volan" self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe" two_cents: "Java would be even cooler with Eiffel's generics, % %assertions/DBC, true MI, feature adaptation, % %selective export, uniform access, etc., etc..." class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant disclaimer: not (opinion implies employer.opinion) end -- class JOHN_VOLAN_SIGNATURE ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Loryn Jenkins ` (2 preceding siblings ...) 1998-09-01 0:00 ` John Volan @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins ` (2 more replies) 3 siblings, 3 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> writes: > Now, someone else was kind enough to show me an even simpler way of > doing this ... albeit marginally less efficient (and again, I don't care > about this criteria, unless my application beforms below specification > and my profiler shows me that this is a hot spot). > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > from > Result := (l.count = r.count) > l.start; r.start > until > not Result or l.off > loop > Result := (l.item = r.item) > l.forth; r.forth > end > end > > This, at least, loses your nesting objection. In fact, it has less > nesting than your original example. However, it might mislead unless the > reader was aware of this sort of idiom. (It does simplify things though; > so I think I'll be using this style, where appropriate.) I like that there's less nesting, but still have a couple of issues with it: 1) The decision table for the predicate still has 4 rules instead of 2. 2) It still bothers me a little that once you calculate the value of Result (the second time, when comparing items), you still do some work after (to increment the iterators), even though the result may already be False. The latter point is only a nit. It's the first point that puts a bee in my bonnet. It may not seem like much in this example, because we're "only" going from 2 rules to 4. But things get scary really fast when going 4 to 8. This was my experience trying to decipher someone else's post, in which a flag was added to a decision table with 4 rules, doubling the size to 8. I wouldn't have been able to figure things out without using a decision table. (I haven't caught on to K-maps yet, but decision tables are my best friend.) BTW: Treat minimizing nesting levels seriously. Whereas Miller's limit was 7 plus or minus 2, for a linear sequence of items, the limit is even lower (around 3) for nested relationships. (This info I read in Structured Design, by Constantine & Yourdon.) ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Loryn Jenkins 1998-09-02 0:00 ` Tim McDermott 1998-09-03 0:00 ` Joe Gamache 2 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-02 0:00 UTC (permalink / raw) > BTW: Treat minimizing nesting levels seriously. Whereas Miller's limit > was 7 plus or minus 2, for a linear sequence of items, the limit is even > lower (around 3) for nested relationships. (This info I read in > Structured Design, by Constantine & Yourdon.) Thanks for the advice. I will do so, as I have done here. By the way, your function exhibits more nesting than mine***. Can you eliminate any? *** My reading of it is that it always had *at least* as much nesting, and now certainly has more. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins @ 1998-09-02 0:00 ` Tim McDermott 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Joe Gamache 2 siblings, 1 reply; 510+ messages in thread From: Tim McDermott @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote:snip > The latter point is only a nit. It's the first point that puts a bee in > my bonnet. It may not seem like much in this example, because we're > "only" going from 2 rules to 4. But things get scary really fast when > going 4 to 8. This seems a little extreme to me. While I have great respect for combinatorial explosion, you are talking about a 3-term boolean expression. There are only 6 ways to put one of those together, and I have no trouble evaluating any of the forms. I know because I just listed them all, and ran through their evaluation with no problem. > This was my experience trying to decipher someone else's post, in which > a flag was added to a decision table with 4 rules, doubling the size to > 8. I wouldn't have been able to figure things out without using a > decision table. (I haven't caught on to K-maps yet, but decision tables > are my best friend.) You should exercise your boolean algebra a little more. DeMorgan's theorem is more useful to me than truth tables. > BTW: Treat minimizing nesting levels seriously. Whereas Miller's limit > was 7 plus or minus 2, for a linear sequence of items, the limit is even > lower (around 3) for nested relationships. (This info I read in > Structured Design, by Constantine & Yourdon.) That depends on the nesting relationships. I find keeping cyclomatic complexity below 10 is the very best rule of thumb. Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Tim McDermott @ 1998-09-03 0:00 ` Matthew Heaney 0 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) Tim McDermott <mcdermott@draper.com> writes: > Matthew Heaney wrote:snip > > > The latter point is only a nit. It's the first point that puts a bee in > > my bonnet. It may not seem like much in this example, because we're > > "only" going from 2 rules to 4. But things get scary really fast when > > going 4 to 8. > > This seems a little extreme to me. While I have great respect for > combinatorial explosion, you are talking about a 3-term boolean expression. > There are only 6 ways to put one of those together, and I have no trouble > evaluating any of the forms. I know because I just listed them all, and ran > through their evaluation with no problem. I don't think I made my point clear. There are 2**N possibilities to consider when evaluating a predicate. That means a 3-term expression has 8 possibilities, not 6: 1 2 3 4 5 6 7 8 P T T T T F F F F Q T T F F T T F F R T F T F T F T F ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins 1998-09-02 0:00 ` Tim McDermott @ 1998-09-03 0:00 ` Joe Gamache 1998-09-04 0:00 ` Charles Hixson 2 siblings, 1 reply; 510+ messages in thread From: Joe Gamache @ 1998-09-03 0:00 UTC (permalink / raw) Matthew Heaney wrote: > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > Now, someone else was kind enough to show me an even simpler way of > > doing this ... albeit marginally less efficient (and again, I don't care > > about this criteria, unless my application beforms below specification > > and my profiler shows me that this is a hot spot). > > > > equal (l,r: LIST): BOOLEAN is > > require > > l /= Void and r /= Void > > do > > from > > Result := (l.count = r.count) > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := (l.item = r.item) > > l.forth; r.forth > > end > > end > > > > This, at least, loses your nesting objection. In fact, it has less > > nesting than your original example. However, it might mislead unless the > > reader was aware of this sort of idiom. (It does simplify things though; > > so I think I'll be using this style, where appropriate.) > > I like that there's less nesting, but still have a couple of issues with > it: > > 1) The decision table for the predicate still has 4 rules instead of 2. > If I follow your logic here it seems seriously flawed to me. You ignore the contribution of the 'if" statement bailout in your orginal example as two additional cases for the decision table. Otherwise, we can carry your arguement to its logical extreme and "improve" your code by ALWAYS making infinite loops and "bailing out" in the middle: function "=" (L, R : Stack_Type) return Boolean is begin if L.Top /= R.Top then return False; end if; Index : Positive := 1; while (True) loop ! is 'loop' supposed to be 'do' ?? can't recall if L.Items (Index) /= R.Items (Index) then return False; end if; if Index = L.Top then return True; ! bail out as soon as I know I can end if; Index := Index + 1; end loop; end "="; Please excuse any syntax errors. I think the above is a nightmare. Do people actually think it is an improvement? But your logic seems to say there are zero cases to consider in the decision tree for the loop predicate. Otherwise there is 4 in your original example and this example. You can not mathematically have it both ways. > 2) It still bothers me a little that once you calculate the value of > Result (the second time, when comparing items), you still do some work > after (to increment the iterators), even though the result may already > be False. > > The latter point is only a nit. It's the first point that puts a bee in > my bonnet. It may not seem like much in this example, because we're > "only" going from 2 rules to 4. But things get scary really fast when > going 4 to 8. > > This was my experience trying to decipher someone else's post, in which > a flag was added to a decision table with 4 rules, doubling the size to > 8. I wouldn't have been able to figure things out without using a > decision table. (I haven't caught on to K-maps yet, but decision tables > are my best friend.) > > BTW: Treat minimizing nesting levels seriously. Whereas Miller's limit > was 7 plus or minus 2, for a linear sequence of items, the limit is even > lower (around 3) for nested relationships. (This info I read in > Structured Design, by Constantine & Yourdon.) This bothers me also. Dr. Miller's work is often quoted in our business. Yet theproject I'm currently working on is distributed on 27 ultrasparc computers and I understand it! Am I some aberration, some wierd freak of nature capable of feats of cognition heretofore undreamed of? As further evidence, my last project consisted over well over 100 classes. I knew and understood not only each class, but their interaction with one another as well. Boy, my ego is really going now. Wait! Everyone else here understands the system on the 27 computers as well. Either this is a rare group of genius individuals or something else is going on. Perhaps it is that Miller's work regarding the "magic" number of 7 +/- 2 was on short term memory. Thus, if you are giving a pitch you don't want too many bullets, classes, boxes, or anything else on it - if you NEED your audience to remember something meaningful. But, for more intensive study the human brain's cognitive limits are often go well beyond 9. Oh no! This means I'm only normal (okay this may now be debateable....) ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Joe Gamache @ 1998-09-04 0:00 ` Charles Hixson 1998-09-05 0:00 ` Patrick Logan 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-04 0:00 UTC (permalink / raw) Joe Gamache wrote: > > Matthew Heaney wrote: > > > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > ... It seems to me that at least a part of this is about how much optimizing you assume that the compilers do. If you assume that they aren't doing much, then you try to write code that will execute efficiently. If you assume that they do LOTS of optimization, then you write code that's maximally clean, and leave it to the compiler to figure out what's most efficient. Of course this is only part of it, but I think that changes in the algorithm that scale linearly are generally overwhelmed by differences between compiler implementations, and also that the best code for this year may not be the best code for next year. I am particularly leery of using constructs like "and then" to optimize performance. That works this year, but two years from not the parallel version of the code will hit a linearizing bottleneck. (Well, two years may be optimistic, but if the code ends up in a library, two years is nothing to the changes that it may need to survive). Perhaps what is needed is a formalization of the (Eiffels?) Command-Query Separation so that compilers can choose to abort a query in progress if it's returned value would be irrelevant. And perhaps the order of the arguments to a boolean operator could reflect the programmers best guess as to which it would be most profitable to try first (I know it is frequently implemented this way, but if it were formalized, then it would become something that both programmers and compilers could depend on, and this could be helpful). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Charles Hixson @ 1998-09-05 0:00 ` Patrick Logan 1998-09-05 0:00 ` Charles Hixson 0 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-05 0:00 UTC (permalink / raw) In comp.object Charles Hixson <charleshixsn@earthlink.net> wrote: : Of course this is only part of it, but I think that changes in the : algorithm that scale linearly are generally overwhelmed by differences : between compiler implementations, and also that the best code for this : year may not be the best code for next year. I have read a little bit on Comp.arch over the last six months or so about how the hard core algorithm/performance people are finding significant differences in performance by paying attention to memory hierarchies, level 2 caches, etc. Some of these folks describe the best results come from treating the L2 and the CPU as an old, limited RAM computer. In this case, going to the off chip RAM is like going to core memory in "olden days". -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Patrick Logan @ 1998-09-05 0:00 ` Charles Hixson 0 siblings, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-05 0:00 UTC (permalink / raw) Well, that was intended more as an example of environmental change. Put more abstractly, code should be written to optimize the implementation of the algorithm. The execution environment WILL change. The compiler implemented for the new environment should optimize the code to run in the environment that it is designed to operate in itself. I realize that a) this is a bit optimistic, and b) there are lots of optimizations that the compiler can't do, because it doesn't understand the purpose of the code but (e.g.): IF queries were guaranteed not to change the state of the object being queried AND there was a method of aborting a query in progress, THEN in certain circumstances code could be executed in parallel without even the overhead of threads. My real question then, I guess, becomes: Is it reasonable to insist that queries not cause any permanent changes to the state of the system, other than returning a value? If you do insist upon this, what about commands that exist within the queries? Is it feasible to even think about enforcing this requirement? I suppose a second question would be: Can queries really be executed in parallel with less overhead than spinning off a thread? Patrick Logan wrote: > > In comp.object Charles Hixson <charleshixsn@earthlink.net> wrote: > > : Of course this is only part of it, but I think that changes in the > : algorithm that scale linearly are generally overwhelmed by differences > : between compiler implementations, and also that the best code for this > : year may not be the best code for next year. > > I have read a little bit on Comp.arch over the last six months or so > about how the hard core algorithm/performance people are finding > significant differences in performance by paying attention to memory > hierarchies, level 2 caches, etc. Some of these folks describe the > best results come from treating the L2 and the CPU as an old, limited > RAM computer. In this case, going to the off chip RAM is like going to > core memory in "olden days". > > -- > Patrick Logan (H) mailto:plogan@teleport.com > (W) mailto:patrickl@gemstone.com > http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-04 0:00 ` Charles Hixson 1998-09-05 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-04 0:00 UTC (permalink / raw) Loryn Jenkins wrote: .. > Ah! For some reason, I thought you were testing the first item on the > stack. So, my amended code, to match your semantics is thus: > > equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > Result := l.count /= r.count > if Result then > from > l.start; r.start > until > not Result or l.off > loop > Result := l.item /= r.item > l.forth; r.forth > end > end > end > ... > > Loryn Jenkins > > PS: I really would agree with you if the only counter examples were Tim > McDermott's and Jim Cochrane's ones. Is the if test important? The until test should catch it anyway, and the code would read more cleanly without it. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Charles Hixson @ 1998-09-05 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) Charles Hixson wrote: > > Loryn Jenkins wrote: > .. > > Ah! For some reason, I thought you were testing the first item on the > > stack. So, my amended code, to match your semantics is thus: > > > > equal (l,r: LIST): BOOLEAN is > > require > > l /= Void and r /= Void > > do > > Result := l.count /= r.count > > if Result then > > from > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := l.item /= r.item > > l.forth; r.forth > > end > > end > > end > > > ... > > > > Loryn Jenkins > > > > Is the if test important? The until test should catch it anyway, and > the code would read more cleanly without it. Not really. It is an optimization. But do note, that if you removed it, you *must* change the loop to the following: > > equal (l,r: LIST): BOOLEAN is > > require > > l /= Void and r /= Void > > do > > from > > l.start; r.start > > until > > not Result or l.off or r.off > > loop > > Result := l.item /= r.item > > l.forth; r.forth > > end > > end ... just in case r is shorter than l. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Loryn Jenkins @ 1998-09-01 0:00 ` dewarr 1998-09-04 0:00 ` Jean-Marc Jezequel 2 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-01 0:00 UTC (permalink / raw) In article <m3yas4q514.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > How is this more complicated? > > > > equal (l,r: LIST): BOOLEAN is > > require > > l.count = r.count > > do > > Result := l.first /= r.first > > if Result then > > from > > l.start; r.start > > until > > not Result or l.off > > loop > > Result := l.item /= r.item > > l.forth; r.forth > > end > > end > > end > > There are a few things I don't like about this: > > 1) You have to test a flag every iteration of the loop. That adds (a > marginal amount of) inefficiency. > > 2) The loop predicate has 4 possible values. The original example had > only 2. > > 3) There's more nesting. > > So yes, I feel the above implementation is more complex than the > original implementation that used muliple returns. > > > Sorry for the language change ... it's the one I'm familiar with. > > AOK, I understood it OK. (I also read the 1st ed of Bertrand's book.) > > > By the way, I'm not sure whether it's a problem in your Ada code, but my > > Eiffel code could fail if r has greater or fewer items than l. Hence the > > precondition. > > That's what the check L.Top /= R.Top means: if the number of items is > different, then you know immediately that the stacks can't be equal. > When you reach the loop, you know the stack depths are the same. > > The way I look at this problem, is that it's like searching for a > specific house on an unfamiliar block. As you're driving, when you find > the house, you stop immediately and declare success. You don't have to > drive to the end of the block, and then say where the house was. > > Likewise for the example I provided. Once you determine that the stacks > are unequal, you quit and go home. You don't need go all the way to the > end of the subprogram to declare victory (unless of course the stacks > happen to really be equal). > > Well it is not necessarily clear that this restatement is less efficient. A compiler could manage to optimize the awkward flag version back to the simple version with exits. Interestingly few compilers do this optimization. A similar case is optimizing an awkward case statement of a finite state machine back to the simple and efficient version with gotos. Given how common serious goto-allergy is, especially in the US, and seeing how many people are willing to contort their code to avoid gotos, these are optimizations that are probably worthwhile including in modern compilers for this class of languages. Robert Dewar -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` dewarr @ 1998-09-04 0:00 ` Jean-Marc Jezequel 1998-09-04 0:00 ` Richard Melvin 2 siblings, 1 reply; 510+ messages in thread From: Jean-Marc Jezequel @ 1998-09-04 0:00 UTC (permalink / raw) IMHO, Dijkstra's point with se/se loops is first on *correctness*, that is linked with provability. This is the most important thing from a software engineering point of view. Maintenability comes second. Readability comes third (but is actualy linked to maintenability). Easyness of writing comes *last*. (well, in the real world issues such as efficiency or more often costs and delay sinterfere at any level in this hierarchy;-). I agree with Bob Martin's point of view on the role of engineers: making trade-offs). According to this point of view, the point is not to craft a piece of code and throw it to the tester in a kind of simulated annealing until it works. IMHO the professional engineer should design a piece of code as trivial as a loop *in such a way that it can be proven correct*. At least one systematic way of doing this have been documented by the structured programming folks (Dijkstra, Hoare...). Let me recall it in the context of the current thread on list equality implemented with a loop: equal (l,r: LIST): BOOLEAN is require l /= Void; r /=Void This is a six steps process: 1. Design the loop invariant. It should provide a concise and preferably formal description of the properties of the loop. But even if it's not formal, it is usefull since it outline the intent. Here, it is simply that the two list r and l are equal so far (which could be made more formal saying that foreach i such as 0<i<l.current_index r.item(i) = l.item(i)) [For those who need refreshing on loop invariant: It is a Boolean expression that must be true on initialization of the loop variables, maintained with each iteration of the loop, and held to be true at the termination of the loop. A loop invariant can be used to reason about the correctness of a loop. see below] 2. Find the termination condition. Here it is: either we find 2 differing elements or we reach the end of one of the lists. That is, if Result contains the comparison result: until not Result or l.off or r.off So now, if the loop terminates, then the loop invariant is true and the termination condition holds (by definition), which means that either the lists are equal or Result=false. This property is called *partial correctness*. Let us see how to prove total correctness. Total correctness is just partial correctness {\em and} the proof that the loop terminates (i.e., the termination condition eventually will hold). The idea of a loop variant is to characterize how each iteration can bring the loop closer to its termination. 3. Find the variant (how the loop can advance toward its termination). [A loop variant is a non-negative integer expression that is decreased by at least one at each iteration. By definition, it cannot go below zero, thus the number of iterations of a loop with a variant is bounded and then the loop eventually terminates.] A suitable variant for this example is: variant l.count-l.current_index+1 In writing the loop body, we must ensure that it is a strictly decreasing function that takes non-negative values only. This proof completes the partial correctness to give the total correctness of the loop. In other words, the loop terminates and computes the right result. 4. Write the body of the loop: 4a) First deduce from the variant the progression instruction, 4b) Then write the code corresponding to the restoration of the invariant. loop Result := l.item /= r.item -- establish invariant l.forth; r.forth -- progression for the variant end 5. Write the initialization part to set up the loop invariant. Result := True; l.start; r.start 6. Optimize, and/or modify to make it more readable e.g., initialize Result to something less trivial: Result := l.first /= r.first from l.start; r.start invariant equal_so_far: --foreach i such as 0<i<l.current_index -- r.item(i) = l.item(i) variant l.count-l.current_index+1 until not Result or l.off --r.off omitted since l.off=>r.off loop Result := l.item /= r.item l.forth; r.forth end 7. Check your proof. Test (it's as easy to make an error in the proof as it is in the code. Eiffel helps here by checking invariants and variants at runtime. But the method is valid and usefull for *any* language). Ship. To sum up my point, when there is a documented way of doing something (here building loops) the engineer should follow it (albeit not blindly: she must still make appropriate trade-offs). Doing it elseway for no good reason is not engineering: it is handcrafting (which is not necessarily pejorative in my mouth). -- Jean-Marc Jezequel Tel : +33 299 847 192 IRISA/CNRS Fax : +33 299 847 171 Campus de Beaulieu e-mail : jezequel@irisa.fr F-35042 RENNES (FRANCE) http://www.irisa.fr/prive/jezequel ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Jean-Marc Jezequel @ 1998-09-04 0:00 ` Richard Melvin 1998-09-07 0:00 ` Jean-Marc Jezequel 0 siblings, 1 reply; 510+ messages in thread From: Richard Melvin @ 1998-09-04 0:00 UTC (permalink / raw) In article <35EFD468.BDD7CB0A@irisa.fr>, Jean-Marc Jezequel <Jean- Marc.Jezequel@irisa.fr> writes > > Result := l.first /= r.first > from l.start; r.start > invariant equal_so_far: --foreach i such as 0<i<l.current_index > -- r.item(i) = l.item(i) > variant l.count-l.current_index+1 > until not Result or l.off --r.off omitted since l.off=>r.off > loop > Result := l.item /= r.item > l.forth; r.forth > end Nice proof. Unfortunately your code contains at least one, and arguably two, bugs: - will throw an exception or return wrong result on unequal length lists. - will interfere with iteration over lists in the calling function (unless the language you are using passes lists by value, not identity). I've got a theory as to the people writing strict single/entry single code are having such a hard time with this (defect rate > 20%): - iteration through a list is actually quite hard, through two lists multiply so - there are quite a lot of opportunities for error. Of course, it doesn't seem that hard to most people, as they have memorised the correct way to loop through a list, given their language and library. - With tree structured code, you can use this memorised pattern of iteration every time, and put the custom code within the loop body, including early exit. - with strict structured code, you can't do this, as you have to adjust the loop condition, at least introducing new terms, and possibly adjusting existing ones. Anyway, it's just a theory - no doubt someone will now post a batch of tree-structured code with bugs. -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Richard Melvin @ 1998-09-07 0:00 ` Jean-Marc Jezequel 0 siblings, 0 replies; 510+ messages in thread From: Jean-Marc Jezequel @ 1998-09-07 0:00 UTC (permalink / raw) To: Richard Melvin Richard Melvin a �crit: > > In article <35EFD468.BDD7CB0A@irisa.fr>, Jean-Marc Jezequel <Jean- > Marc.Jezequel@irisa.fr> writes > > > Nice proof. > > Unfortunately your code contains at least one, and arguably two, bugs: Absolutely. I was interrupted while writing this message just before writing initialization code, and resumed it back only hours later, just before leaving for the week-end. And this stupid computer took what I wrote, not what I meant ;-) Usual problem for many of us. > - will throw an exception or return wrong result on unequal > length lists. True. > > Result := l.first /= r.first Was meant to be Result := l.count /= r.count (copy paste error). > - will interfere with iteration over lists in the calling function > (unless the language you are using passes lists by value, > not identity). true again. There is even another error in it, that magically disappears in step 6 (exercice left to the reader. Hint: the code is correct, the proof is correct, still there is an error. See last line of this message for another hint.) > I've got a theory as to the people writing strict single/entry single > code are having such a hard time with this (defect rate > 20%): I have no theory on that. Was just showing why Dijkstra insisted on se/se loops: in this way programs can be made provable. Sorry guys for my sloppiness in the actual showing. BTW, it illustrate another of my points: don't rely on hand-made proofs *only* (even when you take care of not doing any error in the proof, how can you proove that what you wrote correspond to your *intent*?). -- Jean-Marc Jezequel Tel : +33 299 847 192 IRISA/CNRS Fax : +33 299 847 171 Campus de Beaulieu e-mail : jezequel@irisa.fr F-35042 RENNES (FRANCE) http://www.irisa.fr/prive/jezequel ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney ` (2 preceding siblings ...) 1998-09-01 0:00 ` Loryn Jenkins @ 1998-09-01 0:00 ` Don Harrison 3 siblings, 0 replies; 510+ messages in thread From: Don Harrison @ 1998-09-01 0:00 UTC (permalink / raw) Matthew Heaney wrote (to support the notion of multiple returns): :Here's is something I whipped up for another post recently. It's an :equality operator for a bounded stack. : :The implementation of the function has multiple returns. : :Does this implementation fit your definition of spaghetti code? : :Would the implementation be better by not using multiple returns? : : :function "=" (L, R : Stack_Type) return Boolean is :begin : : if L.Top /= R.Top then : return False; : end if; : : for Index in Positive range 1 .. L.Top loop : if L.Items (Index) /= R.Items (Index) then : return False; : end if; : end loop; : : return True; : :end "="; : : :My feeling is that trying to implement this operation using only a :single return would just make it more complicated. Not really. It's about the same (and the flow of control is clearer IMHO): function "=" (L, R : Stack_Type) return Boolean is Result : Boolean; begin Result := True; if L.Top /= R.Top then Result := False; else for Index in Positive range 1 .. L.Top loop if L.Items (Index) /= R.Items (Index) then Result := False; exit; end if; end loop; end if; return Result; end "="; Don (Harrison). donh at syd.csa.com.au Eiffel - Software engineering with class ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Andrew Hussey 1998-08-31 0:00 ` Mattias Lundstr�m 1998-08-31 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` dewarr 2 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-01 0:00 UTC (permalink / raw) In article <904556531.666222@miso.it.uq.edu.au>, ahussey@it.uq.edu.au (Andrew Hussey) wrote: > In <m3af4mq7f4.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes: > > >I can almost live that. The real problem, however, is that using an > >extra flag to terminate VASTLY complicates the predicate. In fact, the > >flag doubles the number of states I have to think about when mentally > >evaluating the predicate! That's the real source of the loop > >termination errors. > > >(I shouldn't have to remind anyone, but just in case: George Miller did > >a famous study about human cognitive limits, and found that people can > >remember about 7 things, plus or minus 2. That's why complex predicates > >make a programmer's head spin, and why he often gets loop termination > >wrong.) > > >Using an exit from the middle avoids the headaches (literally) > >engendered by using an extra flag in the predicate. When you want to > >exit, you just say that you want to exit, directly. No mental > >gymnastics are required in order to determine whether you'll "really" > >exit, as would be the case using the flag approach. > > That's brilliant, now your code is much easier to write! > Now let's see who has an easier time *testing* their code. > I think you'll find the control-flow errors you introduce > in the spaghetti you produce will more than make up for > any gain you have from rapid coding. > > A. > > If you think that the use of a goto necessarily results in "spaghetti code", then you simply don't understand the (useful) concept of spaghetti code. I often see this, people don't really understand the issues at all, but want to reduce their lack of understanding to a simple rule ("never use a goto"). I guess that if you don't have any understanding of the issues, this is not a terrible rule, but it will result in less clear code in some cases. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Robert Martin ` (3 preceding siblings ...) [not found] ` <35f51e53.48044143@ <m3af4mq7f4.fsf@mheaney.ni.net> @ 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Charles Hixson [not found] ` <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au> ` (2 subsequent siblings) 7 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-08-31 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: >Matthew Heaney wrote in message ... >> >>If theory says use a construct, but observation reveals that programmers >>who use the construct produce more errors, then the theory needs to be >>thrown out. >All else being equal, that would be so. But when observation shows that the >construct reduces the overall cost of maintaining the program, regardless of >its initial cost, then it ought not be thrown out. Yes if what you say is true then we should keep it, but he is saying that programmers who use it are producing more errors. Do you grasp that, or will you insist on stating groundless tautologies? >>For example, there's a pernicious myth that exiting (or returning) from >>the middle of a loop is bad, and that the only proper way to write a >>loop is to state the termination condition explicitly, as a predicate >>appearing at the top of the loop. >Yes. That pernicious myth is called "structured programming". Please cite even just a single structured programming text, or founder where what you say here was asserted. >>This theory was indeed put to the test, and guess what? Programmers >>using a test-and-exit from the middle of the loop produced fewer errors >>than those programmers who tried to put the test at the top of the loop. >>Cognitive Strategies and Looping Constructs: An Empirical Study >>Soloway, Bonar, Ehrlich >>CACM, Nov 83, Vol 26, No 11, p 853-860 >>The researchers found that the exit-from-the-middle construct had a >>better "cognitive fit" than the other constructs. >"Cognitive fit" is probably not a very good criterion for good engineering. >GOTO has a very good cognitive fit. So does a flat Earth. I would assert that 'goto' spaghetti coding is only a cognitive fit to you, and handful of others, not most of us. Flat earth is not cognitive to people living on the coast who see the mast of a ship appear before the bow. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Jeffrey C. Dege ` (2 more replies) 1998-09-01 0:00 ` Charles Hixson 1 sibling, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Ell wrote in message <35f51e53.48044143@news.erols.com>... >"Robert Martin" <rmartin@oma.com> wrote: > >>Matthew Heaney wrote in message ... >>> >>>If theory says use a construct, but observation reveals that programmers >>>who use the construct produce more errors, then the theory needs to be >>>thrown out. > >>All else being equal, that would be so. But when observation shows that the >>construct reduces the overall cost of maintaining the program, regardless of >>its initial cost, then it ought not be thrown out. > >Yes if what you say is true then we should keep it, but he is saying >that programmers who use it are producing more errors. Do you grasp >that, or will you insist on stating groundless tautologies? I grasped it. I am skeptical, but I grasped it. Now, do you grasp that initial programmer errors may not be as serious as latter maintenance problems? If we accept that mid loop breaks reduce initial errors by programmers (something that I have serious doubts about) then if they also cause severe subsequent maintenance problems, they should still be avoided. On the other hand, if the errors produced by single exit loops are fixed once, and then the structures afford easier maintenance, then it may still be best to keep them. > >>>For example, there's a pernicious myth that exiting (or returning) from >>>the middle of a loop is bad, and that the only proper way to write a >>>loop is to state the termination condition explicitly, as a predicate >>>appearing at the top of the loop. > >>Yes. That pernicious myth is called "structured programming". > >Please cite even just a single structured programming text, or founder >where what you say here was asserted. "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. 16-23 "7. On Understanding Programs". Actualy this section says that there are two different kinds of loops. one that is tested at the top; and another which is tested at the bottom. But in all cases, the elements of structure programming have a single entry and a single exit. A loop that exits in the middle, violates this maxim. > >>>The researchers found that the exit-from-the-middle construct had a >>>better "cognitive fit" than the other constructs. > >>"Cognitive fit" is probably not a very good criterion for good engineering. >>GOTO has a very good cognitive fit. So does a flat Earth. > >I would assert that 'goto' spaghetti coding is only a cognitive fit to >you, and handful of others, not most of us. I contend that people are more disposed to write spaghetti, than to take the time and think through the structure of their code. The evidence for this is the vast array of poorly structured programs that have accumulated over the years. Indeed, most novices write *horrible* code, and only gain the ability to structure it well after making the mistakes and experiencing the cost. Therefore I content that spaghetti is the natural state, and that it requires experience and dedication to produce non-spaghetti. Now, I'll grant you that spaghetti is does not have a good cognitive fit with the reader of the code. However, the spaghetti had a very good cognitive fit with the *writer* of the code. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Stephen Leake 1998-08-31 0:00 ` Matthew Heaney 2 siblings, 2 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-08-31 0:00 UTC (permalink / raw) On Mon, 31 Aug 1998 02:00:51 -0500, Robert Martin <rmartin@oma.com> wrote: > >Ell wrote in message <35f51e53.48044143@news.erols.com>... >> >>I would assert that 'goto' spaghetti coding is only a cognitive fit to >>you, and handful of others, not most of us. > >Now, I'll grant you that spaghetti is does not have a good cognitive fit >with the reader of the code. However, the spaghetti had a very good >cognitive fit with the *writer* of the code. Spaghetti code is disorganized and confused. To assert that it is never a cognitive fit is to assert that the writer's cognitive state is never disorganized and confused. And we all know that isn't true. -- The major advances in civilization are processes that all but wreck the societies in which they occur. -- A.N. Whitehead ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Jeffrey C. Dege @ 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-08-31 0:00 UTC (permalink / raw) jdege@jdege.visi.com (Jeffrey C. Dege) wrote: >On Mon, 31 Aug 1998 02:00:51 -0500, Robert Martin <rmartin@oma.com> wrote: >> >>Ell wrote in message <35f51e53.48044143@news.erols.com>... >>> >>>I would assert that 'goto' spaghetti coding is only a cognitive fit to >>>you, and handful of others, not most of us. >>Now, I'll grant you that spaghetti is does not have a good cognitive fit >>with the reader of the code. However, the spaghetti had a very good >>cognitive fit with the *writer* of the code. >Spaghetti code is disorganized and confused. To assert that it is never >a cognitive fit is to assert that the writer's cognitive state is never >disorganized and confused. And we all know that isn't true. If I have been disorganized and confused, you've never been capable of demonstrating it--nor anyone of your pragmatist cohorts. So of what value is your silliness? Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Jeffrey C. Dege 0 siblings, 0 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-08-31 0:00 UTC (permalink / raw) On Mon, 31 Aug 1998 16:50:42 GMT, Ell <ell@access.digex.net> wrote: >jdege@jdege.visi.com (Jeffrey C. Dege) wrote: > >>On Mon, 31 Aug 1998 02:00:51 -0500, Robert Martin <rmartin@oma.com> wrote: >>> >>>Ell wrote in message <35f51e53.48044143@news.erols.com>... >>>> >>>>I would assert that 'goto' spaghetti coding is only a cognitive fit to >>>>you, and handful of others, not most of us. > >>>Now, I'll grant you that spaghetti is does not have a good cognitive fit >>>with the reader of the code. However, the spaghetti had a very good >>>cognitive fit with the *writer* of the code. > >>Spaghetti code is disorganized and confused. To assert that it is never >>a cognitive fit is to assert that the writer's cognitive state is never >>disorganized and confused. And we all know that isn't true. > >If I have been disorganized and confused, you've never been capable of >demonstrating it--nor anyone of your pragmatist cohorts. So of what >value is your silliness? I was under the impression that were discussing novice programmers. Why do you assume that I meant you? -- When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Gene Gajewski 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-08-31 0:00 UTC (permalink / raw) jdege@jdege.visi.com (Jeffrey C. Dege) wrote: The major advances in civilization are processes that all but wreck the societies in which they occur. -- A.N. Whitehead What better quote to show the truly clueless, and confused thinking of you and the other craftites? Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Gene Gajewski 0 siblings, 0 replies; 510+ messages in thread From: Gene Gajewski @ 1998-08-31 0:00 UTC (permalink / raw) Ell wrote in message <35edd483.1368337@news.erols.com>... >jdege@jdege.visi.com (Jeffrey C. Dege) wrote: > > >The major advances in civilization are processes that all but wreck >the societies in which they occur. > -- A.N. Whitehead > >What better quote to show the truly clueless, and confused thinking of >you and the other craftites? > >Elliott <snip> I would have been better reply with a quote countering his point... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Jeffrey C. Dege @ 1998-08-31 0:00 ` Stephen Leake 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Matthew Heaney 2 siblings, 1 reply; 510+ messages in thread From: Stephen Leake @ 1998-08-31 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. > 16-23 "7. On Understanding Programs". Actualy this section says that > there are two different kinds of loops. one that is tested at the top; and > another which is tested at the bottom. But in all cases, the elements of > structure programming have a single entry and a single exit. A loop that > exits in the middle, violates this maxim. If there is only one 'exit' statement, why is this bad? loop ... stuff exit when ; ... stuff end loop; One entry, one exit. Perfectly clear. There's nothing magic about putting the exit statement at the top or the bottom! Personally, I _always_ use 'exit' in a non-'for' loop (ie, I never use 'while' or 'until'), precisely because it is clearer what the exit conditions are, and it makes it easier to move processing to before or after the exit as necessary. -- Stephe ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Stephen Leake @ 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Agent ` (3 more replies) 0 siblings, 4 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Stephen Leake wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: > >> "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. >> 16-23 "7. On Understanding Programs". Actualy this section says that >> there are two different kinds of loops. one that is tested at the top; and >> another which is tested at the bottom. But in all cases, the elements of >> structure programming have a single entry and a single exit. A loop that >> exits in the middle, violates this maxim. > >If there is only one 'exit' statement, why is this bad? > >loop > ... stuff > exit when ; > ... stuff >end loop; > >One entry, one exit. Perfectly clear. There's nothing magic about >putting the exit statement at the top or the bottom! In fact there is. If the exit condition is at the top or the bottom, then the body of the loop will always be excuted an exact integral number of times. However if the loop condition is in the middle, then the loop body will be executed a fractional number of times. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Agent 1998-09-01 0:00 ` Ell 1998-09-01 0:00 ` Phil Goodwin ` (2 subsequent siblings) 3 siblings, 1 reply; 510+ messages in thread From: Agent @ 1998-08-31 0:00 UTC (permalink / raw) Robert Martin wrote in message <6sfcft$70p$1@hirame.wwa.com>... >Stephen Leake wrote in message ... >>If there is only one 'exit' statement, why is this bad? >> >>loop >> ... stuff >> exit when ; >> ... stuff >>end loop; >> >>One entry, one exit. Perfectly clear. There's nothing magic about >>putting the exit statement at the top or the bottom! > >In fact there is. If the exit condition is at the top or the bottom, then >the body of the loop will always be excuted an exact integral number of >times. However if the loop condition is in the middle, then the loop body >will be executed a fractional number of times. There are two "loop bodies" in this case. The upper body will be executed n times, and the lower body will be executed n-1 times. It is a little more difficult to keep track of, but mid-decision loops *are* useful; Knuth thinks so, anyway, and I agree based on my own experiences. -- Agent ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Agent @ 1998-09-01 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin [not found] ` <6sfqul$ggg$1@hirame. <6sidsq$e6c$1@hirame.wwa.com> 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-09-01 0:00 UTC (permalink / raw) "Agent" <agent@siu.edu> wrote: >Robert Martin wrote in message <6sfcft$70p$1@hirame.wwa.com>... >>Stephen Leake wrote in message ... >>>If there is only one 'exit' statement, why is this bad? >>> >>>loop >>> ... stuff >>> exit when ; >>> ... stuff >>>end loop; >>> >>>One entry, one exit. Perfectly clear. There's nothing magic about >>>putting the exit statement at the top or the bottom! >> >>In fact there is. If the exit condition is at the top or the bottom, >then >>the body of the loop will always be excuted an exact integral number of >>times. However if the loop condition is in the middle, then the loop >body >>will be executed a fractional number of times. So what? Big deal. It's *not* non-intuitive, unreadable, hard to maintain spaghetti code (even less so with comments), and that's all that *really* matters. *Those* are the key issues, not blind bondage in some imaginary stockade of dogmatic pain. Elliott >There are two "loop bodies" in this case. The upper body will be >executed n times, and the lower body will be executed n-1 times. It is >a little more difficult to keep track of, but mid-decision loops *are* >useful; Knuth thinks so, anyway, and I agree based on my own >experiences. > >-- Agent > -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Ell @ 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Tim Ottinger 1998-09-01 0:00 ` dennison [not found] ` <6sfqul$ggg$1@hirame. <6sidsq$e6c$1@hirame.wwa.com> 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Ell wrote in message <35ed3d4a.2378710@news.erols.com>... >"Agent" <agent@siu.edu> wrote: > >>Robert Martin wrote in message <6sfcft$70p$1@hirame.wwa.com>... >>>Stephen Leake wrote in message ... >>>>One entry, one exit. Perfectly clear. There's nothing magic about >>>>putting the exit statement at the top or the bottom! >>> >>>In fact there is. If the exit condition is at the top or the bottom, >>then >>>the body of the loop will always be excuted an exact integral number of >>>times. However if the loop condition is in the middle, then the loop >>body >>>will be executed a fractional number of times. > >So what? The the invariants of the loop body are different depending on whether the iteration is the last or not. Also, a programmer must be aware that the last statement in the loop body will not be executed on the last iteration. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Tim Ottinger 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` dennison 1 sibling, 1 reply; 510+ messages in thread From: Tim Ottinger @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > The the invariants of the loop body are different depending on whether the > iteration is the last or not. Also, a programmer must be aware that the > last statement in the loop body will not be executed on the last iteration. Of course, the example is "in the small". Very small things tend to be fairly easy to understand. To really appreciate the rules, you have to have a moderately complex loop with if/then/else or switch/case in the middle, preferably nested three levels deep or more ;-) I personally like checking rules at the front of a function, and returning early if conditions aren't met... at least for checking invariants. Assert is better if you want to abort when the condition isn't met. But the question I have is what happens when we have exceptions. Those are most certainly an early exit and may occur at unpredicted times. How do the rules for single entry/exit apply in an exception-supporting language? Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Tim Ottinger @ 1998-09-01 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Tim Ottinger wrote in message <35EBF28B.FD4F38EC@oma.com>... >But the question I have is what happens when we have exceptions. Those >are >most certainly an early exit and may occur at unpredicted times. How >do >the rules for single entry/exit apply in an exception-supporting >language? For exceptions, they don't apply. And because of that, language designers have bene forced to invent a suite of extraordinary language features to help deal with it. In C++, we use destructors to clean up resources. In Java we use 'finally' clauses. These solutions work, but suffer from the fact that the state of the algorithm may have been by the time they are entered; and such state may have to be recaptured by inspecting data elements (something very difficult to do inside a destructor!). In the end, one of the better schemes for dealing with exceptions is to re-enstate the single-entry/single-exit (se/se) mechanism by using fine grained try/catch blocks: try { // block 1 do something that might throw. try { // block 2, new algorithm state do something else that might throw. cleanup block 2. } catch(...) { cleanup block 2; throw; } cleanup block 1 } catch(...) { cleanup block 1. throw; } The 'finally' approach in Java is superior to this because it doesn't require the duplicated cleanup code. And when used in a fine-grained way can almost completely recapture the tracking of algorithm state that se/se structures do. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Tim Ottinger @ 1998-09-01 0:00 ` dennison 1998-09-01 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: dennison @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sfqul$ggg$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Ell wrote in message <35ed3d4a.2378710@news.erols.com>... > >"Agent" <agent@siu.edu> wrote: > > > >>Robert Martin wrote in message <6sfcft$70p$1@hirame.wwa.com>... > >>>Stephen Leake wrote in message ... > > >>>>One entry, one exit. Perfectly clear. There's nothing magic about > >>>>putting the exit statement at the top or the bottom! > >>> > >>>In fact there is. If the exit condition is at the top or the bottom, > >>then > >>>the body of the loop will always be excuted an exact integral number of > >>>times. However if the loop condition is in the middle, then the loop > >>body > >>>will be executed a fractional number of times. > > > >So what? > > The the invariants of the loop body are different depending on whether the > iteration is the last or not. Also, a programmer must be aware that the > last statement in the loop body will not be executed on the last iteration. Yes, but if that's what the algorithm is *supposed* to do, rephrasing it with flags and if statements won't change that. -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` dennison @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Andrew Reilly 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) dennison@telepath.com wrote in message <6sh30l$k4i$1@nnrp1.dejanews.com>... >In article <6sfqul$ggg$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: >> >> Ell wrote in message <35ed3d4a.2378710@news.erols.com>... >> >"Agent" <agent@siu.edu> wrote: >> > >> >>Robert Martin wrote in message <6sfcft$70p$1@hirame.wwa.com>... >> >>>Stephen Leake wrote in message ... >> >> >>>>One entry, one exit. Perfectly clear. There's nothing magic about >> >>>>putting the exit statement at the top or the bottom! >> >>> >> >>>In fact there is. If the exit condition is at the top or the bottom, >> >>then >> >>>the body of the loop will always be excuted an exact integral number of >> >>>times. However if the loop condition is in the middle, then the loop >> >>body >> >>>will be executed a fractional number of times. >> > >> >So what? >> >> The the invariants of the loop body are different depending on whether the >> iteration is the last or not. Also, a programmer must be aware that the >> last statement in the loop body will not be executed on the last iteration. > >Yes, but if that's what the algorithm is *supposed* to do, rephrasing it with >flags and if statements won't change that. On the contrary, it is possible to create a loop body with a single invariant, and whose last line will be executed in every iteration. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Andrew Reilly 1998-09-01 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Andrew Reilly @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sh4o4$afu$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: > > dennison@telepath.com wrote in message <6sh30l$k4i$1@nnrp1.dejanews.com>... >>In article <6sfqul$ggg$1@hirame.wwa.com>, >> "Robert Martin" <rmartin@oma.com> wrote: >>> iteration is the last or not. Also, a programmer must be aware that the >>> last statement in the loop body will not be executed on the last iteration. >> >>Yes, but if that's what the algorithm is *supposed* to do, rephrasing it with >>flags and if statements won't change that. > > On the contrary, it is possible to create a loop body with a single > invariant, and whose last line will be executed in every iteration. How can you say this? Or are you counting the endloop statement as the last line? If the algorithm requires middle exit, and you achieve that with a flag and an if..endif section around the second half of the loop, then the second part doesn't execute on the last iteration, exactly like a break. -- Andrew Reilly Reilly@zeta.org.au ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Andrew Reilly @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` dennison 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Andrew Reilly wrote in message <6si29e$1ul@gurney.reilly.home>... >In article <6sh4o4$afu$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> writes: >> >> dennison@telepath.com wrote in message <6sh30l$k4i$1@nnrp1.dejanews.com>... >>>In article <6sfqul$ggg$1@hirame.wwa.com>, >>> "Robert Martin" <rmartin@oma.com> wrote: >>>> iteration is the last or not. Also, a programmer must be aware that the >>>> last statement in the loop body will not be executed on the last iteration. >>> >>>Yes, but if that's what the algorithm is *supposed* to do, rephrasing it with >>>flags and if statements won't change that. >> >> On the contrary, it is possible to create a loop body with a single >> invariant, and whose last line will be executed in every iteration. > >How can you say this? > >Or are you counting the endloop statement as the last line? Correct. More specifically, I can guarantee that if I put a line of code just above the endloop statement (closing brace in my case) it will be executed in every iteration. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` dennison 0 siblings, 0 replies; 510+ messages in thread From: dennison @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sidsq$e6c$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Correct. More specifically, I can guarantee that if I put a line of code > just above the endloop statement (closing brace in my case) it will be > executed in every iteration. Well, if this loop is an implementation of middle-exited loop algorithm (remember what started this thread), then that line will get executed one extra iteration. Is that what you want? Maybee, maybee not. You have to stop and think about it. Just because you rephrased the middle-exited loop as a multiple-conditional "while" with conditional code in the body doesn't magically give you the ability to blindly throw code at the end of the loop and expect it to behave the way you want it to. -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <6sfqul$ggg$1@hirame. <6sidsq$e6c$1@hirame.wwa.com>]
* Re: Software landmines (loops) [not found] ` <6sfqul$ggg$1@hirame. <6sidsq$e6c$1@hirame.wwa.com> @ 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Charles Hixson 0 siblings, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <6sidsq$e6c$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> wrote: > >Correct. More specifically, I can guarantee that if I put a line of code >just above the endloop statement (closing brace in my case) it will be >executed in every iteration. How would you feel about a loop...exit_when...end_loop structure? It has only one exit point. You could still add something to the end of every iteration by putting it before the exit_when. This seems pretty safe to me. Do you see any reason this would be less manageable than a top- or bottom-exit loop? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Patrick Doyle @ 1998-09-03 0:00 ` Charles Hixson 1998-09-03 0:00 ` John G. Volan 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-03 0:00 UTC (permalink / raw) In order for that to be an equivalently obvious form one would need to adopt an indentation convention that caused the exit test to stand-out as well as the top and the bottom of the loop do. Probably not hard, especially with colored-syntax editors (environments?), but not a current standard. (Well, at least not one that I know.) Patrick Doyle wrote: ... > How would you feel about a loop...exit_when...end_loop structure? > It has only one exit point. You could still add something to > the end of every iteration by putting it before the exit_when. > > This seems pretty safe to me. Do you see any reason this would > be less manageable than a top- or bottom-exit loop? > > -PD > > -- > -- > Patrick Doyle > doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Charles Hixson @ 1998-09-03 0:00 ` John G. Volan 0 siblings, 0 replies; 510+ messages in thread From: John G. Volan @ 1998-09-03 0:00 UTC (permalink / raw) Charles Hixson wrote: > > In order for that to be an equivalently obvious form one would need to > adopt an indentation convention that caused the exit test to stand-out > as well as the top and the bottom of the loop do. Sure, why not? See my post on another branch of this thread (gads, such metaphor mixing!), describing a possible Eiffel extension that would satisfy your criterion ("Mid-Loop 'Until' Proposal"). > Probably not hard, > especially with colored-syntax editors (environments?), but not a > current standard. (Well, at least not one that I know.) > > Patrick Doyle wrote: > ... > > How would you feel about a loop...exit_when...end_loop structure? > > It has only one exit point. You could still add something to > > the end of every iteration by putting it before the exit_when. > > > > This seems pretty safe to me. Do you see any reason this would > > be less manageable than a top- or bottom-exit loop? I think the key question is whether one can devise a reasonable semantics for such a construct such that important principles like Design By Contract are upheld. (Again, cf. my "Mid-Loop 'Until' Proposal" post.) -- indexing description: "Signatures for John G. Volan" self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe" two_cents: "Java would be even cooler with Eiffel's assertions/DBC, % %generics, true MI, feature adaptation, selective export, % %uniform access, expanded types, etc., etc..." class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant disclaimer: not (opinion implies employer.opinion) end -- class JOHN_VOLAN_SIGNATURE ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Agent @ 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-10-01 0:00 ` Charles H. Sampson 3 siblings, 1 reply; 510+ messages in thread From: Phil Goodwin @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sfcft$70p$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Stephen Leake wrote in message ... > >"Robert Martin" <rmartin@oma.com> writes: > > > >> "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. > >> 16-23 "7. On Understanding Programs". Actualy this section says that > >> there are two different kinds of loops. one that is tested at the top; > and > >> another which is tested at the bottom. But in all cases, the elements of > >> structure programming have a single entry and a single exit. A loop that > >> exits in the middle, violates this maxim. > > > >If there is only one 'exit' statement, why is this bad? > > > >loop > > ... stuff > > exit when ; > > ... stuff > >end loop; > > > >One entry, one exit. Perfectly clear. There's nothing magic about > >putting the exit statement at the top or the bottom! > > In fact there is. If the exit condition is at the top or the bottom, then > the body of the loop will always be excuted an exact integral number of > times. However if the loop condition is in the middle, then the loop body > will be executed a fractional number of times. So what? Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Phil Goodwin @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell [not found] ` <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com> 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Phil Goodwin wrote in message <6shp40$ec8$1@nnrp1.dejanews.com>... >In article <6sfcft$70p$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: >> >> Stephen Leake wrote in message ... >> >One entry, one exit. Perfectly clear. There's nothing magic about >> >putting the exit statement at the top or the bottom! >> >> In fact there is. If the exit condition is at the top or the bottom, then >> the body of the loop will always be excuted an exact integral number of >> times. However if the loop condition is in the middle, then the loop body >> will be executed a fractional number of times. > >So what? So... I can guarantee that any line of code placed at the end of the loop body will be executed for each iteration of the loop. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 1998-09-01 0:00 ` Robert Martin [not found] ` <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com> 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Phil Goodwin wrote in message <6shp40$ec8$1@nnrp1.dejanews.com>... :>In article <6sfcft$70p$1@hirame.wwa.com>, :> "Robert Martin" <rmartin@oma.com> wrote: :>> :>> Stephen Leake wrote in message ... :>> >One entry, one exit. Perfectly clear. There's nothing magic about :>> >putting the exit statement at the top or the bottom! :>> :>> In fact there is. If the exit condition is at the top or the bottom, : then :>> the body of the loop will always be excuted an exact integral number of :>> times. However if the loop condition is in the middle, then the loop : body :>> will be executed a fractional number of times. :> :>So what? : So... I can guarantee that any line of code placed at the end of the loop : body will be executed for each iteration of the loop. Maybe, juuussst maybe, you like many of the rest of us might be able to design the loop so that "any line of code placed at the end of loop" doesn't matter if the exit/return occurs before the end of the loop? Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney ` (5 more replies) 0 siblings, 6 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Ell wrote in message ... >In comp.object Robert Martin <rmartin@oma.com> wrote: > >: Phil Goodwin wrote in message <6shp40$ec8$1@nnrp1.dejanews.com>... >:>In article <6sfcft$70p$1@hirame.wwa.com>, >:> "Robert Martin" <rmartin@oma.com> wrote: >:>> >:>> Stephen Leake wrote in message ... >:>> >One entry, one exit. Perfectly clear. There's nothing magic about >:>> >putting the exit statement at the top or the bottom! >:>> >:>> In fact there is. If the exit condition is at the top or the bottom, >: then >:>> the body of the loop will always be excuted an exact integral number of >:>> times. However if the loop condition is in the middle, then the loop >: body >:>> will be executed a fractional number of times. >:> >:>So what? > > >: So... I can guarantee that any line of code placed at the end of the loop >: body will be executed for each iteration of the loop. > >Maybe, juuussst maybe, you like many of the rest of us might be able to >design the loop so that "any line of code placed at the end of loop" >doesn't matter if the exit/return occurs before the end of the loop? Lets just say, for grins, that I must make a change to the loop. For some odd reason I must count the number of times that the loop body completes. Where do I put the code that does this counting? I'd like to make it the last line of the loop. But if there are early exits, then I must find each and every early exit and add the code just before they exit. Of course, later, someone else will make a change that forces yet another early exit. They find where to add the early exit, but they must remember to bump the counter before they exit. Of course later on, someone asks us to sieze and release a mutex for each iteration of the loop. We'd like to put the seize as the first line of the loop body, and the release as the last line of the loop body. But if there are early exits, then we must put a release before every exit. Of course later on someone adds yet another early exit to the loop, and must remember to bump the counter and release the mutex. .... Has anybody out there ever had an experience like this? Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` dennison ` (4 subsequent siblings) 5 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > Of course later on, someone asks us to sieze and release a mutex for each > iteration of the loop. We'd like to put the seize as the first line of the > loop body, and the release as the last line of the loop body. But if there > are early exits, then we must put a release before every exit. No. Use a controlled type (construction/deconstruction) to automatically seize and release: loop declare Lock : Mutex_Lock (Mutex'Access); begin <use the resource controlled by Mutex> end; end loop; When you enter the loop, the Lock object elaborates, and during its initialization, it automatically calls the Seize operation of Mutex. When you leave the loop - via a return, or an exit, or an exception, or whatever - the Lock object is Finalized, during which time it automatically calls the Release operation of Mutex. So no, you don't have to worry about bailing out early. There is no maintenance penalty for an early return from the loop. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Richard Melvin 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: > >> Of course later on, someone asks us to sieze and release a mutex for each >> iteration of the loop. We'd like to put the seize as the first line of the >> loop body, and the release as the last line of the loop body. But if there >> are early exits, then we must put a release before every exit. > >No. Use a controlled type (construction/deconstruction) to >automatically seize and release: > >loop > declare > Lock : Mutex_Lock (Mutex'Access); > begin > <use the resource controlled by Mutex> > end; >end loop; > > >When you enter the loop, the Lock object elaborates, and during its >initialization, it automatically calls the Seize operation of Mutex. > >When you leave the loop - via a return, or an exit, or an exception, or >whatever - the Lock object is Finalized, during which time it >automatically calls the Release operation of Mutex. > >So no, you don't have to worry about bailing out early. There is no >maintenance penalty for an early return from the loop. This is true if: 1. Your language has controlled types. 2. The cleanup that needs to be done can be done from the finalizer. For example, in C++ the equivalent scheme is to use a destructor. However the destructor is in a completely different scope. So extraordinary means may need to be used to allow the destructor access to the variables that need finalization. Consider the case of a complex data structure. You are in the midst of changing a set of variables within it. Suddenly you realize that you must exit early. Before you can exit, you have to put the data structure back the way it was. In C++, getting a destructor to do this can be horrific. The point is that controlled types are not a generally applicable solution, since not all languages have them, and not all languages implement them well. BTW, in essense a controlled type is simply a way to enforce that a scope has a single exit. By using single-entry/single-exit style, *all* your variables are controlled -- albeit manually. (excluding exceptions). Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Richard Melvin 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >So no, you don't have to worry about bailing out early. There is no > >maintenance penalty for an early return from the loop. > > This is true if: > > 1. Your language has controlled types. Agreed. But C++ does have the equivalent of Ada95 controlled types. It may be that you have a philosophical problem with using deconstructors for dealing with resource management issues that can be handled via traditional techniques - like a single point of exit from a loop. Fair enough. But I argue that in a language with exception propagation, you're going to have to be thinking about resource management anyway, even if you're not writing a loop. So I think the resource management argument is a bit of a red herring. > 2. The cleanup that needs to be done can be done from the finalizer. For > example, in C++ the equivalent scheme is to use a destructor. However the > destructor is in a completely different scope. So extraordinary means may > need to be used to allow the destructor access to the variables that need > finalization. > > Consider the case of a complex data structure. You are in the midst of > changing a set of variables within it. Suddenly you realize that you must > exit early. Before you can exit, you have to put the data structure back > the way it was. In C++, getting a destructor to do this can be horrific. I don't see this as a hard problem. Let the object cache the new settings until a Commit operation is invoked. If you bail out early, then Commit doesn't get called, and the data structure retains its original value. > Btw, in essense a controlled type is simply a way to enforce that a scope > has a single exit. By using single-entry/single-exit style, *all* your > variables are controlled -- albeit manually. (excluding exceptions). But resource management in the presence of exceptions is precisely my point. Your parenthetical disclaimer is a little like saying, "All objects can levitate. (excluding gravitation)." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Tim Ottinger 1 sibling, 1 reply; 510+ messages in thread From: Richard Melvin @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sjl6v$5qh$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> writes > >Consider the case of a complex data structure. You are in the midst of >changing a set of variables within it. Suddenly you realize that you must >exit early. Before you can exit, you have to put the data structure back >the way it was. In C++, getting a destructor to do this can be horrific. This seems a weak argument, as there can easily be no way whatsoever to put things back the way they were - the most obvious example is a sort function. (Unless you copy the initial state of the array before sorting, which can be done just as easily in a little stack-based transaction object.) -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Richard Melvin @ 1998-09-02 0:00 ` Tim Ottinger 0 siblings, 0 replies; 510+ messages in thread From: Tim Ottinger @ 1998-09-02 0:00 UTC (permalink / raw) Richard Melvin wrote: > This seems a weak argument, as there can easily be no way whatsoever to > put things back the way they were - the most obvious example is a sort > function. > > (Unless you copy the initial state of the array before sorting, which > can be done just as easily in a little stack-based transaction object.) Actually, did you see the C++ Report articles on exception-safe containers? This is exactly what had to be done... Yeah, we suddenly have to be aware of unit of work all through our apps. We have to be able to commit or rollback at just about any time, and ensure the commit is atomic fairly often. As if software weren't hard enough... but it's kind of like doing accounting. If you know that the transactions balance, then they are very unlikely to throw the ledger off-balance when you post them (not that you stop checking). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` dennison 1998-09-02 0:00 ` Richard Melvin ` (3 subsequent siblings) 5 siblings, 0 replies; 510+ messages in thread From: dennison @ 1998-09-02 0:00 UTC (permalink / raw) In article <6siijm$h1m$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Of course later on, someone asks us to sieze and release a mutex for each > iteration of the loop. We'd like to put the seize as the first line of the > loop body, and the release as the last line of the loop body. But if there > are early exits, then we must put a release before every exit. > > Of course later on someone adds yet another early exit to the loop, and must > remember to bump the counter and release the mutex. > > .... Has anybody out there ever had an experience like this? In my experience it is more likely that I'm going to have to either add code to one of the branches that doesn't always get executed, or create a new (non-exiting) if-conditional inside the loop. In both cases my cause is helped greatly by not having a lot of extra conditional code already in the loop. But if the loop is naturally middle-exiting, then you will HAVE to have that coditional code in the loop (or have one copy of it outside the loop, which is a problem as well). Part of my problem is that a conditional in a loop tells me "this code can execute some iterations and not others". I have to go figure out exactly when by examining the entire loop to see what affects the conditional, and all the preceeding code to figure out its initial condition. I have to do a *lot* of digging just to figure out that it once it is false, it will never be true again. Using an "exit" or "return" tells me that information up front. I'm inclined to believe that the construct that conveys the most information about what I am doing is going to be the one that makes reading and maintainence easiest. Now I will freely admit that someone could embed lots of returns and exits within different levels of if statements and inner loops, and make a completely confusing mess. In that case, yes switching to flags would probably be better. But as long as the overall structure of the loop is simpler with the early exit construct, I don't see why it shouldn't be used. -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` dennison @ 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Richard MacDonald (dogmat) ` (2 subsequent siblings) 5 siblings, 0 replies; 510+ messages in thread From: Richard Melvin @ 1998-09-02 0:00 UTC (permalink / raw) In article <6siijm$h1m$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> writes > >Lets just say, for grins, that I must make a change to the loop. For some >odd reason I must count the number of times that the loop body completes. I'm sorry, this really is an invalid argument. Any change case must be based on functionality, not on the existing structure of the code. Otherwise I can blow any of your dependency management principles out of the water with a change case carefully designed to cause maximum pain and distress (e.g. 'all Visitors must be re-written to be case statements'). You wouldn't really agree that the above proved case statements were better, would you? Just because you're the only one using change-case based arguments, doesn't mean you're the only one thinking about design for maintainability. It'd be interesting to do a proper change-case comparison. I guess that would need a set of 5 or 6 reasonable, functionality-based changes to a function written in 'pure-structured' and 'tree-structured' styles. Changes that require restructuring count against, changes made correctly first time count for. As a control, you could throw in a true spaghetti implementation - if the analysis didn't show this was worse, then there's something wrong with the analysis. As a starter, try extending a fixed-length array comparison function to be a stack comparison :-) -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin ` (2 preceding siblings ...) 1998-09-02 0:00 ` Richard Melvin @ 1998-09-02 0:00 ` Richard MacDonald (dogmat) 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-0309982244140001@dialup62.tlh.talstar.com> 5 siblings, 1 reply; 510+ messages in thread From: Richard MacDonald (dogmat) @ 1998-09-02 0:00 UTC (permalink / raw) Robert Martin wrote in message <6siijm$h1m$1@hirame.wwa.com>... >Lets just say, for grins, that I must make a change to the loop. For some >odd reason I must count the number of times that the loop body completes. >Where do I put the code that does this counting? I'd like to make it the >last line of the loop. But if there are early exits, then I must find each >and every early exit and add the code just before they exit. > >Of course, later, someone else will make a change that forces yet another >early exit. They find where to add the early exit, but they must remember >to bump the counter before they exit. Solved by putting the counter at the start of the loop. That seems to be the "right" place to put it, surely. >Of course later on, someone asks us to sieze and release a mutex for each >iteration of the loop. We'd like to put the seize as the first line of the >loop body, and the release as the last line of the loop body. But if there >are early exits, then we must put a release before every exit. > >Of course later on someone adds yet another early exit to the loop, and must >remember to bump the counter and release the mutex. > Better example. However, my solution for this would be to have a simple loop with three lines: (1) Seize the mutex. (2) Call a subroutine to do whatever (with one entry and one or more exits). (3) Release the mutex. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Richard MacDonald (dogmat) @ 1998-09-03 0:00 ` Matthew Heaney 0 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) "Richard MacDonald (dogmat)" <macdonaldrj@bv.com> writes: > Better example. However, my solution for this would be to have a simple loop > with three lines: (1) Seize the mutex. (2) Call a subroutine to do whatever > (with one entry and one or more exits). (3) Release the mutex. This is the example Bob Eachus presented. There really is one single point of exit - at the point of call. function "=" (L, R : T) return Boolean is Result : Boolean; begin Seize (Mutex); Result := Do_Equality (L, R); Release (Mutex); return Result; end; Now you can terminate the loop (inside Do_Equality now) as early and often as you want, without any maintenance penalty. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin ` (3 preceding siblings ...) 1998-09-02 0:00 ` Richard MacDonald (dogmat) @ 1998-09-03 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-0309982244140001@dialup62.tlh.talstar.com> 5 siblings, 0 replies; 510+ messages in thread From: mfinney @ 1998-09-03 0:00 UTC (permalink / raw) In <6siijm$h1m$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: >Lets just say, for grins, that I must make a change to the loop. For some >odd reason I must count the number of times that the loop body completes. >Where do I put the code that does this counting? I'd like to make it the >last line of the loop. But if there are early exits, then I must find each >and every early exit and add the code just before they exit. >Of course, later, someone else will make a change that forces yet another >early exit. They find where to add the early exit, but they must remember >to bump the counter before they exit. >Of course later on, someone asks us to sieze and release a mutex for each >iteration of the loop. We'd like to put the seize as the first line of the >loop body, and the release as the last line of the loop body. But if there >are early exits, then we must put a release before every exit. >Of course later on someone adds yet another early exit to the loop, and must >remember to bump the counter and release the mutex. >..... Has anybody out there ever had an experience like this? Not a problem...I would simply double click the opening {, hit tab to shift the block right, alt-{ to create a new block, a search and replace for "return" in the high-lighted block to use a different multi-level exit control structure (probably a goto to a name at the end of the block in C/C++) and add a wrapper the top of the block -- a do {/*code*/} while (false); multiLevelExitName: would do the trick nicely. My code is still tree structured, and I can now add new code just before or after the do..while to satisify your requirements. Also, the above took about 10 or 15 seconds, perhaps 30 with the search and replace. If the return has a value, then I might need to add a block variable to contain the return value and my edit for the return would be slightly more complex -- but even so, the edit cost is trivial compared to understanding the needed changes. Now...if I were still using a card punch, I would... (well, I guess that nobody cares about that anymore <g>) Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0309982244140001@dialup62.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0309982244140001@dialup62.tlh.talstar.com> @ 1998-09-04 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) gio+van+no+ni+8@tal+star+spam.com (Giovanni 8) wrote: >"[R]eading a thousand-page source listing to learn about the > components & architecture of a software system is a formidable, > extremely time-consuming challenge. Sometimes it is an > impossible task because a maintenance programmer's 'span of > understanding' is only 7K to 15K source code lines; & to > understand this amount of code requires about 3 to 6 months > of time." --- Carma McClure 1992 _The 3 Rs of Software Automation_ > pg 97 (citing Fletcher J. Buckley 1989-11-?? "Some Standards > for Software Maintenance" _IEEE Computer_ vol 22 #1 pg 69) Hence one of the major reasons I recommend that holistic analysis and physical design (global, and local architectural) object models be created. I find that the average person gains a more comprehensive understanding of a system or its parts in a quicker amount of time viewing graphical models as opposed to reading code. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com> @ 1998-09-15 0:00 ` mfinney 0 siblings, 0 replies; 510+ messages in thread From: mfinney @ 1998-09-15 0:00 UTC (permalink / raw) In <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com>, gio+van+no+ni+8@tal+star+spam.com (Giovanni 8) writes: >"[T]he air force estimates that it will require 25% of the > country's entire 18-25 year old population to maintain all > its software systems by the year 2000. [H]igh-quality > software is difficult to develop... most software efforts > of any magnitude are fraught with problems & failures & > that software projects usually take longer to complete & > cost more than planned." --- Carma McClure 1992 > _The 3 Rs of Software Automation_ pg 5 (citing Eric Bush > 1988 "A CASE for Existing Systems" _Language Technology > White Paper_ pg 27) Clearly the only solution is to abolish the air force! <g> Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Agent 1998-09-01 0:00 ` Phil Goodwin @ 1998-09-01 0:00 ` Matthew Heaney 1998-10-01 0:00 ` Charles H. Sampson 3 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >One entry, one exit. Perfectly clear. There's nothing magic about > >putting the exit statement at the top or the bottom! > > In fact there is. If the exit condition is at the top or the bottom, then > the body of the loop will always be excuted an exact integral number of > times. However if the loop condition is in the middle, then the loop body > will be executed a fractional number of times. I think we're losing site of the forest through the trees. The important thing is the postcondition for the loop. Is the postcondition satisfied or not? If the postcondition is satisfied, then what difference does the number of iterations (fractional or otherwise) make? Our goal is NOT "execute the loop body an integral number of times." Our goal IS to satisfy the loop postcondition, in the simplest way possible. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin ` (2 preceding siblings ...) 1998-09-01 0:00 ` Matthew Heaney @ 1998-10-01 0:00 ` Charles H. Sampson 1998-10-02 0:00 ` Robert C. Martin 1998-10-02 0:00 ` Ell 3 siblings, 2 replies; 510+ messages in thread From: Charles H. Sampson @ 1998-10-01 0:00 UTC (permalink / raw) Robert Martin <rmartin@oma.com> wrote: > Stephen Leake wrote in message ... > >If there is only one 'exit' statement, why is this bad? > > > >loop > > ... stuff > > exit when ; > > ... stuff > >end loop; > > > >One entry, one exit. Perfectly clear. There's nothing magic about > >putting the exit statement at the top or the bottom! > > In fact there is. If the exit condition is at the top or the bottom, then > the body of the loop will always be excuted an exact integral number of > times. However if the loop condition is in the middle, then the loop body > will be executed a fractional number of times. Well, this is certainly a twist to me. I was taught the n-and-a- half loop as an example of the inadequacy of loop structures in most programming languages. Now it seems that everything has been turned around 180 degrees and there is some sort of software principle (in some peoples' minds) that the entire body of a loop must execute "an exact integral number of times." As another responder has pointed out (not in these words), in the presence of conditional statements it's not clear what this condition means. My guess is that it's this: Every statement immediately in the loop body executes on every iteration of the loop. If this is an accurate statement of this new principle, my immediate re- sponse is: So what? Why should we care? I apologize for responding to a post that's 31 days old. I got in on this long thread very late and I'm running very hard to catch up. Charlie -- To get my correct email address, replace the "claveman" by "csampson" in my fake (anti-spam) address. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-01 0:00 ` Charles H. Sampson @ 1998-10-02 0:00 ` Robert C. Martin 1998-10-02 0:00 ` Charles H. Sampson ` (4 more replies) 1998-10-02 0:00 ` Ell 1 sibling, 5 replies; 510+ messages in thread From: Robert C. Martin @ 1998-10-02 0:00 UTC (permalink / raw) Charles H. Sampson wrote in message <1dg8p3r.vfredh1aou58iN@n207167116191.inetworld.net>... >Robert Martin <rmartin@oma.com> wrote: > >> Stephen Leake wrote in message ... >> >If there is only one 'exit' statement, why is this bad? >> > >> >loop >> > ... stuff >> > exit when ; >> > ... stuff >> >end loop; >> > >> >One entry, one exit. Perfectly clear. There's nothing magic about >> >putting the exit statement at the top or the bottom! >> >> In fact there is. If the exit condition is at the top or the bottom, then >> the body of the loop will always be excuted an exact integral number of >> times. However if the loop condition is in the middle, then the loop body >> will be executed a fractional number of times. > > Well, this is certainly a twist to me. I was taught the n-and-a- >half loop as an example of the inadequacy of loop structures in most >programming languages. Now it seems that everything has been turned >around 180 degrees and there is some sort of software principle (in some >peoples' minds) that the entire body of a loop must execute "an exact >integral number of times." As another responder has pointed out (not in >these words), in the presence of conditional statements it's not clear >what this condition means. My guess is that it's this: Every statement >immediately in the loop body executes on every iteration of the loop. >If this is an accurate statement of this new principle, my immediate re- >sponse is: So what? Why should we care? > > I apologize for responding to a post that's 31 days old. I got in >on this long thread very late and I'm running very hard to catch up. > The question that the post was addressing had to do with the definition of structured programming. A mid exit loop does not fall within the bounds defined by structured programming because the loop body does not then have a single entry and a single exit. This has nothing to do with whether mid exit loops are good or bad. It only has to do with whether mid exit loops conform to structured programming or not. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Robert C. Martin @ 1998-10-02 0:00 ` Charles H. Sampson 1998-10-03 0:00 ` Reimer Behrends 1998-10-02 0:00 ` John I. Moore, Jr. ` (3 subsequent siblings) 4 siblings, 1 reply; 510+ messages in thread From: Charles H. Sampson @ 1998-10-02 0:00 UTC (permalink / raw) Robert C. Martin <rmartin@oma.com> wrote: > Charles H. Sampson wrote in message > <1dg8p3r.vfredh1aou58iN@n207167116191.inetworld.net>... > >Robert Martin <rmartin@oma.com> wrote: > > > >> Stephen Leake wrote in message ... > >> >If there is only one 'exit' statement, why is this bad? > >> > > >> >loop > >> > ... stuff > >> > exit when ; > >> > ... stuff > >> >end loop; > >> > > >> >One entry, one exit. Perfectly clear. There's nothing magic about > >> >putting the exit statement at the top or the bottom! > >> > >> In fact there is. If the exit condition is at the top or the bottom, > then > >> the body of the loop will always be excuted an exact integral number of > >> times. However if the loop condition is in the middle, then the loop > body > >> will be executed a fractional number of times. > > > > Well, this is certainly a twist to me. I was taught the n-and-a- > >half loop as an example of the inadequacy of loop structures in most > >programming languages. Now it seems that everything has been turned > >around 180 degrees and there is some sort of software principle (in some > >peoples' minds) that the entire body of a loop must execute "an exact > >integral number of times." As another responder has pointed out (not in > >these words), in the presence of conditional statements it's not clear > >what this condition means. My guess is that it's this: Every statement > >immediately in the loop body executes on every iteration of the loop. > >If this is an accurate statement of this new principle, my immediate re- > >sponse is: So what? Why should we care? > > The question that the post was addressing had to do with the definition of > structured programming. A mid exit loop does not fall within the bounds > defined by structured programming because the loop body does not then have a > single entry and a single exit. But it does. Just look. That's not a for-loop or a while-loop. It's a loop that can only be executed with an exit statement and it has just one. (Yes, an exception can cause it to exit too, but gimme a break.) The problem everybody is chewing on has from time to time led me to propose an Ada programming style: No exit statements in for-loops and while-loops. (The precise statement is a little more complicated.) With this restriction, the termination conditions of for-loops and while-loops are clear. Any loop that can't reasonably be expressed that way is to be written as an "infinite" loop with exit statement(s). Un- fortunately, the neatness of the loop index in Ada, self-declaring with its scope being the loop itself, is a siren song that I haven't been able fully to resist. Incidentally, my meaning of "can't reasonably be expressed" in the previous paragraph uses the maintenance programmer as a frame of refer- ence. There have been a number of charges of "You're only interested in what makes writing the code easy for you" thrown around in this thread. I always program for the maintenance programmer, even when that mainte- nance programmer is going to be me. Charlie -- To get my correct email address, replace the "claveman" by "csampson" in my fake (anti-spam) address. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Charles H. Sampson @ 1998-10-03 0:00 ` Reimer Behrends 1998-10-04 0:00 ` Charles H. Sampson 0 siblings, 1 reply; 510+ messages in thread From: Reimer Behrends @ 1998-10-03 0:00 UTC (permalink / raw) Charles H. Sampson (claveman@inetworld.net) wrote: [...] > But it does. Just look. That's not a for-loop or a while-loop. > It's a loop that can only be executed with an exit statement and it has > just one. (Yes, an exception can cause it to exit too, but gimme a > break.) You may notice, however, that the loop _body_ has two different exits for a mid-exit loop. [...] Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Reimer Behrends @ 1998-10-04 0:00 ` Charles H. Sampson 1998-10-05 0:00 ` Reimer Behrends 0 siblings, 1 reply; 510+ messages in thread From: Charles H. Sampson @ 1998-10-04 0:00 UTC (permalink / raw) Reimer Behrends <behrends@cse.msu.edu> wrote: > Charles H. Sampson (claveman@inetworld.net) wrote: > [...] > > But it does. Just look. That's not a for-loop or a while-loop. > > It's a loop that can only be executed with an exit statement and it has > > just one. (Yes, an exception can cause it to exit too, but gimme a > > break.) > > You may notice, however, that the loop _body_ has two different exits > for a mid-exit loop. I don't know about others, but I don't notice any such thing. Here is a cut down version of the loop we were discussing. loop <first part> exit <second part> end loop Please point out the two exits (neither <first part> nor <second part> has one) or give the definition of <loop body> that you're using. Charlie -- To get my correct email address, replace the "claveman" by "csampson" in my fake (anti-spam) address. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-04 0:00 ` Charles H. Sampson @ 1998-10-05 0:00 ` Reimer Behrends 1998-10-05 0:00 ` Patrick Logan 1998-10-06 0:00 ` Charles H. Sampson 0 siblings, 2 replies; 510+ messages in thread From: Reimer Behrends @ 1998-10-05 0:00 UTC (permalink / raw) Charles H. Sampson (claveman@inetworld.net) wrote: > Reimer Behrends <behrends@cse.msu.edu> wrote: [Mid-exit loops.] > > You may notice, however, that the loop _body_ has two different exits > > for a mid-exit loop. > > I don't know about others, but I don't notice any such thing. Here > is a cut down version of the loop we were discussing. > > loop > <first part> > exit > <second part> > end loop > > Please point out the two exits (neither <first part> nor <second part> > has one) or give the definition of <loop body> that you're using. The loop body is of course the following part of the code: <first part> exit <second part> It has an exit at the "exit" statement, and one at the end of <second part>, where control flow leaves the body to reenter at the top. And I'm not kidding you. Try to put the loop body into a procedure of its own, and this becomes very visible. (Ease of procedural decomposition is usually one of the benefits of strict single-entry, single-exit structures.) Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-05 0:00 ` Reimer Behrends @ 1998-10-05 0:00 ` Patrick Logan 1998-10-06 0:00 ` Charles H. Sampson 1 sibling, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-10-05 0:00 UTC (permalink / raw) In comp.object Reimer Behrends <behrends@cse.msu.edu> wrote: : > : > loop : > <first part> : > exit : > <second part> : > end loop : > : > Please point out the two exits... : <first part> : exit : <second part> : It has an exit at the "exit" statement, and one at the end of <second : part>, where control flow leaves the body to reenter at the top. And : I'm not kidding you. Try to put the loop body into a procedure of its : own, and this becomes very visible. (Ease of procedural decomposition is : usually one of the benefits of strict single-entry, single-exit : structures.) Well, you can easily put this into *two* procedures and end up with a "structured program"... void first_part() { <first part> if (!condition) second_part(); } void second_part() { <second part> first_part(); } ...maybe a measure of the degree of "structuredness" of a loop is *how many* well structured procedures result from the conversion? -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-05 0:00 ` Reimer Behrends 1998-10-05 0:00 ` Patrick Logan @ 1998-10-06 0:00 ` Charles H. Sampson 1998-10-11 0:00 ` Reimer Behrends 1 sibling, 1 reply; 510+ messages in thread From: Charles H. Sampson @ 1998-10-06 0:00 UTC (permalink / raw) Reimer Behrends <behrends@cse.msu.edu> wrote: > Charles H. Sampson (claveman@inetworld.net) wrote: > > Reimer Behrends <behrends@cse.msu.edu> wrote: > [Mid-exit loops.] > > > You may notice, however, that the loop _body_ has two different exits > > > for a mid-exit loop. > > > > I don't know about others, but I don't notice any such thing. Here > > is a cut down version of the loop we were discussing. > > > > loop > > <first part> > > exit > > <second part> > > end loop > > > > Please point out the two exits (neither <first part> nor <second part> > > has one) or give the definition of <loop body> that you're using. > > The loop body is of course the following part of the code: > > <first part> > exit > <second part> > > It has an exit at the "exit" statement, and one at the end of <second > part>, where control flow leaves the body to reenter at the top. And > I'm not kidding you. Try to put the loop body into a procedure of its > own, and this becomes very visible. (Ease of procedural decomposition is > usually one of the benefits of strict single-entry, single-exit > structures.) > O. k., I might grudgingly grant you a half score on that one. You pretty clearly said "loop body", but I was so fixed on "loop" that I didn't notice that you had changed the frame of reference. I think I can be forgiven for my mistake; this whole subthread has been about exits from loops, not exits from loop bodies. Furthermore, it's not clear why that transfer of control is consid- ered an exit from the loop body. Prior to the transfer a statement of the body is executing. After the transfer a statement of the body is executing. Where is the exit part? Then there's the concept of transfer of control itself. I'm sur- prised about that. Is that still taught in CS departments? Certainly I was taught it (I'm a VERY old programmer) and I still have to think about it in the rare cases when I'm mucking about among the 0s and 1s, but when I'm working in as good a high-level language as Ada I don't think in terms of control at all any more. For example, a loop body for me is simply a sequence of statement that is repeatedly executed until some condition arises. (In case anyone wants to say, "Well, and exit statement contradicts that concept," an implicit effect of the execution of an exit statement is to abort the execution of the rest of the loop body.) For an if-then-else, there are two sequences of statements, of which one will execute depending on the value of a Boolean expression; I don't think of transferring control from the evaluation code to the else part if the expression evaluates to false. I don't even think in terms of transfer of control when an exception is raised; raising an exception simply causes a certain dynamically determined exception handler to exe- cute. Without thinking about it too hard, I'll grant your claim about ease of decomposition. I don't want to think too hard about it because I have the strong impression that this is another "who cares?" issue. In my entire career I have rarely written the following construct: <loop head> <procedure call> end loop Actually, I can't remember ever doing it, but I assume that I must have at least a few times. Charlie -- To get my correct email address, replace the "claveman" by "csampson" in my fake (anti-spam) address. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-06 0:00 ` Charles H. Sampson @ 1998-10-11 0:00 ` Reimer Behrends 0 siblings, 0 replies; 510+ messages in thread From: Reimer Behrends @ 1998-10-11 0:00 UTC (permalink / raw) Charles H. Sampson (claveman@inetworld.net) wrote: > Reimer Behrends <behrends@cse.msu.edu> wrote: [...] > > The loop body is of course the following part of the code: > > > > <first part> > > exit > > <second part> > > > > It has an exit at the "exit" statement, and one at the end of <second > > part>, where control flow leaves the body to reenter at the top. And > > I'm not kidding you. Try to put the loop body into a procedure of its > > own, and this becomes very visible. (Ease of procedural decomposition is > > usually one of the benefits of strict single-entry, single-exit > > structures.) > > O. k., I might grudgingly grant you a half score on that one. You > pretty clearly said "loop body", but I was so fixed on "loop" that I > didn't notice that you had changed the frame of reference. Hmm. I was under the impression that I had phrased my reply with sufficient precision to not confuse the non-casual reader. My apologies if this wasn't the case. In any event, I didn't intend to "score". I just wished to point out an aspect that had apparently been overlooked in the discussion. [...] > Furthermore, it's not clear why that transfer of control is consid- > ered an exit from the loop body. Prior to the transfer a statement of > the body is executing. After the transfer a statement of the body is > executing. Where is the exit part? I have very little interest in abstractly discussing whether any particular control structure can be construed as having a single entry and/or single exit. Rather, there are certain advantages commonly associated with classical single-entry/single-exit control structures (ease of decomposition, clear control flow, etc.). I am arguing that these advantages are not present in a mid-exit loop, no matter whether you can technically say that a mid-exit loop has a single exit, and I was pointing out the reason why. [...] > Without thinking about it too hard, I'll grant your claim about > ease of decomposition. I don't want to think too hard about it because > I have the strong impression that this is another "who cares?" issue. > In my entire career I have rarely written the following construct: > > <loop head> > <procedure call> > end loop > > Actually, I can't remember ever doing it, but I assume that I must have > at least a few times. I am perfectly aware that using abstractions on a regular basis is not a popular notion; mostly, I think, because some people still believe that using a procedure/class/etc. instead of inserting code directly will invariably slow their code down to a crawl. Of course, they tend to forgot about things like maintenance cost. Personally, I am pretty sick of code that spans several pages without any apparent benefit. [...] Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Robert C. Martin 1998-10-02 0:00 ` Charles H. Sampson @ 1998-10-02 0:00 ` John I. Moore, Jr. 1998-10-02 0:00 ` Ell ` (2 more replies) 1998-10-02 0:00 ` Ell ` (2 subsequent siblings) 4 siblings, 3 replies; 510+ messages in thread From: John I. Moore, Jr. @ 1998-10-02 0:00 UTC (permalink / raw) Robert C. Martin wrote in message <6v2nr9$t8l$1@hirame.wwa.com>... >The question that the post was addressing had to do with the definition of >structured programming. A mid exit loop does not fall within the bounds >defined by structured programming because the loop body does not then have > a single entry and a single exit. I'm sorry, Martin. I usually agree with your posts, but I will have to object to this one. Whose definition are you using for structured programming? Some of the earliest articles and books on structured programming were written by Harlan Mills of IBM, and he always defined a loop with a middle exit as an integral part of structured programming. He called it a do-while-do loop. _____________________________________________________________ John I. Moore, Jr. SoftMoore Consulting 16233 Monty Court Rockville, MD 20853-1344 phone: (301) 924-0680 email: softmoore@compuserve.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` John I. Moore, Jr. @ 1998-10-02 0:00 ` Ell 1998-10-03 0:00 ` John Goodsen 1998-10-03 0:00 ` Robert C. Martin 2 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-02 0:00 UTC (permalink / raw) "John I. Moore, Jr." <70672.1744@compuserve.com> wrote: >Robert C. Martin wrote in message <6v2nr9$t8l$1@hirame.wwa.com>... >> >>The question that the post was addressing had to do with the definition of >>structured programming. A mid exit loop does not fall within the bounds >>defined by structured programming because the loop body does not then have >> a single entry and a single exit. >... Whose definition are you using for structured >programming? Some of the earliest articles and books on structured >programming were written by Harlan Mills of IBM, and he always >defined a loop with a middle exit as an integral part of structured >programming. He called it a do-while-do loop. I've seen no structured programming literature which said that a code module must only a single entry and a single exit (se/se). I've seen quotes from structured literature about flowchart pages having a single entry and single exit point, but nothing about for example about having to navigate a loop using se/se. Very significantly, according to Dijkstra, one of chief creators of structured programming, the definition of structured programming has a modelling aspect which is even more important than any maxims about code control flow navigation. Or rather the navigation issue was resolved in terms of a new more productive modelling paradigm. This is evidenced by Dijkstra's remark that the first thing he thinks of when structured programming is mentioned is "abstraction"--in particular hierarchies of abstraction. (Art of Literate Programming, D Knuth, CLSC, pg 72). "Abstraction" meaning as Webster says: The act of separating the inherit qualities or properties of something from the actual physical object or concept to which they belong. Ie. separating the contextually essential, logical aspect of an object from the physical object itself. This indicates that to cure the spaghetti ills of programming at the time, Dijkstra, went beyond mere matters of navigation to modelling. Dijkstra advocated disciplined navigation between well designed (loosely coupled, highly cohesive) abstractions--with the abstractions being our present day functions/routines/procedures. Here we have another advance in software engineering based on modelling, just as modelling is the key benefit of OO to present day software engineering. Dijkstra took a "giant's" step into modelling rather than advocate a technocratic, navigation maxim of questionable value (single entrance/single exit), Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` John I. Moore, Jr. 1998-10-02 0:00 ` Ell @ 1998-10-03 0:00 ` John Goodsen 1998-10-03 0:00 ` Robert C. Martin 2 siblings, 0 replies; 510+ messages in thread From: John Goodsen @ 1998-10-03 0:00 UTC (permalink / raw) -- John I. Moore, Jr. <70672.1744@compuserve.com> wrote in message <6v39i0$fte$1@winter.news.erols.com>... >Robert C. Martin wrote in message <6v2nr9$t8l$1@hirame.wwa.com>... >>The question that the post was addressing had to do with the definition of >>structured programming. A mid exit loop does not fall within the bounds >>defined by structured programming because the loop body does not then have >> a single entry and a single exit. > > >I'm sorry, Martin. I usually agree with your posts, but I will have to >object to this one. Whose definition are you using for structured >programming? Some of the earliest articles and books on structured >programming were written by Harlan Mills of IBM, and he always >defined a loop with a middle exit as an integral part of structured >programming. He called it a do-while-do loop. > I read "mid exit loop" to mean an unnatural exit from the current scope - like a goto or a return that is put inside a loop structure. -- John Goodsen RADSoft / Training, Mentoring and Consulting in: jgoodsen@radsoft.com - UML modeling and OOA/D principles http://www.radsoft.com - Use Centered Object-Oriented Design 602.283.0142 - Rapid Incremental S/W Delivery Process "Example isn't another way to teach, it is the only way to teach. " - Albert Einstein ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` John I. Moore, Jr. 1998-10-02 0:00 ` Ell 1998-10-03 0:00 ` John Goodsen @ 1998-10-03 0:00 ` Robert C. Martin 1998-10-03 0:00 ` Richard D Riehle ` (4 more replies) 2 siblings, 5 replies; 510+ messages in thread From: Robert C. Martin @ 1998-10-03 0:00 UTC (permalink / raw) John I. Moore, Jr. <70672.1744@compuserve.com> wrote in message <6v39i0$fte$1@winter.news.erols.com>... >Robert C. Martin wrote in message <6v2nr9$t8l$1@hirame.wwa.com>... >>The question that the post was addressing had to do with the definition of >>structured programming. A mid exit loop does not fall within the bounds >>defined by structured programming because the loop body does not then have >> a single entry and a single exit. > > >I'm sorry, Martin. I usually agree with your posts, but I will have to >object to this one. Whose definition are you using for structured >programming? Some of the earliest articles and books on structured >programming were written by Harlan Mills of IBM, and he always >defined a loop with a middle exit as an integral part of structured >programming. He called it a do-while-do loop. Yes, Mills did make this definition. However, I am referring to the work of Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the notion of single entry and single exit within the body of a loop. I believe that Mills' do-while-do loop is an unauthorized addition to Dijkstra's work. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Robert C. Martin @ 1998-10-03 0:00 ` Richard D Riehle 1998-10-03 0:00 ` Ell ` (3 subsequent siblings) 4 siblings, 0 replies; 510+ messages in thread From: Richard D Riehle @ 1998-10-03 0:00 UTC (permalink / raw) In article <6v4d5l$blb$1@hirame.wwa.com>, "Robert C. Martin" <rmartin@oma.com> wrote: in response to a note by John I Moore, Jr. about the do-while-do loop suggested by Harlan Mills, > >Yes, Mills did make this definition. However, I am referring to the work of >Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the >notion of single entry and single exit within the body of a loop. I believe >that Mills'do-while-do loop is an unauthorized addition to Dijkstra's work. Is every pronouncement by Dijkstra the equivalent of Holy writ? Software is a fledgling discipline even today. It was certainly an immature practice in the 1960's. I seem to recall that Albert Einstein once said that we should try to make everything as simple as possible but not simpler. The notion of "single-entry/single-exit" is obsolete. It has been for a long time. Instead, rational programmers understand the need for control structures that are readable, understandable, and maintainable. This requires them to make the code as simple as possible "but not simpler." Single-entry/single-exit has the disadvantage of sometimes making the code not only as simple as possible, but also simpler. Perhaps we should also disallow discontinuous mathematical functions. Richard Riehle richard@adaworks.com http://www.adaworks.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Robert C. Martin 1998-10-03 0:00 ` Richard D Riehle @ 1998-10-03 0:00 ` Ell 1998-10-03 0:00 ` John I. Moore, Jr. ` (2 subsequent siblings) 4 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-03 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> wrote: >John I. Moore, Jr. <70672.1744@compuserve.com> wrote in message >> >>Robert C. Martin wrote in message <6v2nr9$t8l$1@hirame.wwa.com>... >>> >>>The question that the post was addressing had to do with the definition of >>>structured programming. A mid exit loop does not fall within the bounds >>>defined by structured programming because the loop body does not then have >>> a single entry and a single exit. >>I'm sorry, Martin. I usually agree with your posts, but I will have to >>object to this one. Whose definition are you using for structured >>programming? Some of the earliest articles and books on structured >>programming were written by Harlan Mills of IBM, and he always >>defined a loop with a middle exit as an integral part of structured >>programming. He called it a do-while-do loop. >Yes, Mills did make this definition. However, I am referring to the work of >Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the >notion of single entry and single exit within the body of a loop. I believe >that Mills' do-while-do loop is an unauthorized addition to Dijkstra's work. I hope you are not referring to the Dijkstra quotes on how to properly create flowcharts. And I hope you are not alleging that structured programming boils down to exiting from a loop. Another thing to remember is that while a procedure may return to its caller from multiple places the flow of control always returns to the same place in the caller. Either way, it was abstraction and not simple navigation which came to Dijkstra's mind when structured programming was mentioned. We holistic, pre-code modellers will always have that, I'm happy to say. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Robert C. Martin 1998-10-03 0:00 ` Richard D Riehle 1998-10-03 0:00 ` Ell @ 1998-10-03 0:00 ` John I. Moore, Jr. 1998-10-05 0:00 ` Robert C. Martin 1998-10-06 0:00 ` Matt Kennel 1998-10-05 0:00 ` dewarr 1998-10-09 0:00 ` Matthew Heaney 4 siblings, 2 replies; 510+ messages in thread From: John I. Moore, Jr. @ 1998-10-03 0:00 UTC (permalink / raw) Robert C. Martin wrote in message <6v4d5l$blb$1@hirame.wwa.com>... >Yes, Mills did make this definition. However, I am referring to the >work of Dijkstra in the late 60's and early 70's. Dijkstra was very >clear about the notion of single entry and single exit within the >body of a loop. I believe that Mills' do-while-do loop is an >unauthorized addition to Dijkstra's work. Two points: 1. Mills also wrote about structured programming in the 60's and 70's. He was a pioneer and champion of the ideas in the same sense as Dijkstra. 2. Mills construct of do-while-do has a single entry and single exit, as do all of the other structured programming constructs. Using an Ada-like syntax, consider the following: loop get x; exit when x satisfies some condition; process x; end loop; I contend that this logic is natural, that the loop has only a single entry and exit, and that it doesn't violate any of the structured programming guidelines. Of course, one can rewrite it by using a standard while-loop, just as one can rewrite any repeat-until loop using a while-loop, but in order to do so you must repeat some part of the logic outside of the loop. _____________________________________________________________ John I. Moore, Jr. SoftMoore Consulting 16233 Monty Court Rockville, MD 20853-1344 phone: (301) 924-0680 email: softmoore@compuserve.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` John I. Moore, Jr. @ 1998-10-05 0:00 ` Robert C. Martin 1998-10-06 0:00 ` Matt Kennel 1 sibling, 0 replies; 510+ messages in thread From: Robert C. Martin @ 1998-10-05 0:00 UTC (permalink / raw) John I. Moore, Jr. <70672.1744@compuserve.com> wrote in message <6v5en9$d46 >2. Mills construct of do-while-do has a single entry and single exit, > as do all of the other structured programming constructs. Using > an Ada-like syntax, consider the following: > > loop > get x; > exit when x satisfies some condition; > process x; > end loop; > > I contend that this logic is natural, that the loop has only a > single entry and exit, and that it doesn't violate any of the > structured programming guidelines. Of course, one can rewrite > it by using a standard while-loop, just as one can rewrite any > repeat-until loop using a while-loop, but in order to do so you > must repeat some part of the logic outside of the loop. Ooops. Sorry, I was mistaking mid-exit loops for loops with extra exits in them. Yes, a pure mid-exit loop (e.g. Mills' do-while-do *is* compatible with structured programming. Sorry for the fuss. You were right and I was wrong. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` John I. Moore, Jr. 1998-10-05 0:00 ` Robert C. Martin @ 1998-10-06 0:00 ` Matt Kennel 1998-10-06 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: Matt Kennel @ 1998-10-06 0:00 UTC (permalink / raw) On Sat, 3 Oct 1998 11:02:08 -0400, John I. Moore, Jr. wrote: :2. Mills construct of do-while-do has a single entry and single exit, : as do all of the other structured programming constructs. Using : an Ada-like syntax, consider the following: : : loop : get x; : exit when x satisfies some condition; : process x; : end loop; : : I contend that this logic is natural, that the loop has only a : single entry and exit, and that it doesn't violate any of the : structured programming guidelines. Of course, one can rewrite : it by using a standard while-loop, just as one can rewrite any : repeat-until loop using a while-loop, but in order to do so you : must repeat some part of the logic outside of the loop. Why is that loop morally superior to one like loop get x; exit when x satisfies some condition; partially process x; exit if the preliminary processing shows something wrong continue to process x; end loop; Which does not have a single exit? -- * Matthew B. Kennel/Institute for Nonlinear Science, UCSD * * "To chill, or to pop a cap in my dome, whoomp! there it is." * Hamlet, Fresh Prince of Denmark. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-06 0:00 ` Matt Kennel @ 1998-10-06 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-06 0:00 UTC (permalink / raw) NOSPAMmbkennelNOSPAM@yahoo.com (Matt Kennel) wrote: >On Sat, 3 Oct 1998 11:02:08 -0400, John I. Moore, Jr. wrote: >:2. Mills construct of do-while-do has a single entry and single exit, >: as do all of the other structured programming constructs. Using >: an Ada-like syntax, consider the following: >: >: loop >: get x; >: exit when x satisfies some condition; >: process x; >: end loop; >: >: I contend that this logic is natural, that the loop has only a >: single entry and exit, and that it doesn't violate any of the >: structured programming guidelines. Of course, one can rewrite >: it by using a standard while-loop, just as one can rewrite any >: repeat-until loop using a while-loop, but in order to do so you >: must repeat some part of the logic outside of the loop. > >Why is that loop morally superior to one like > > loop > get x; > exit when x satisfies some condition; > partially process x; > exit if the preliminary processing shows something wrong > continue to process x; > end loop; > >Which does not have a single exit? This one: >: loop >: get x; >: exit when x satisfies some condition; >: process x; >: end loop; based on discussion I think should really be: loop get x; exit when x satisfies some condition; process x; reloop; Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Robert C. Martin ` (2 preceding siblings ...) 1998-10-03 0:00 ` John I. Moore, Jr. @ 1998-10-05 0:00 ` dewarr 1998-10-04 0:00 ` Robert C. Martin 1998-10-09 0:00 ` Matthew Heaney 4 siblings, 1 reply; 510+ messages in thread From: dewarr @ 1998-10-05 0:00 UTC (permalink / raw) In article <6v4d5l$blb$1@hirame.wwa.com>, "Robert C. Martin" <rmartin@oma.com> wrote: > Yes, Mills did make this definition. However, I am referring to the work of > Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the > notion of single entry and single exit within the body of a loop. I believe > that Mills' do-while-do loop is an unauthorized addition to Dijkstra's work. What a hilarious post. I am sure that HM would be very amused by the idea that he had to get "authorization" from EWD for stating what he (very reasonably) defined as his notion of structured programming :-) -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-05 0:00 ` dewarr @ 1998-10-04 0:00 ` Robert C. Martin 1998-10-05 0:00 ` Ell 1998-10-05 0:00 ` Ell 0 siblings, 2 replies; 510+ messages in thread From: Robert C. Martin @ 1998-10-04 0:00 UTC (permalink / raw) dewarr@my-dejanews.com wrote in message <6v9eg5$b55$1@nnrp1.dejanews.com>... >In article <6v4d5l$blb$1@hirame.wwa.com>, > "Robert C. Martin" <rmartin@oma.com> wrote: > >> Yes, Mills did make this definition. However, I am referring to the work of >> Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the >> notion of single entry and single exit within the body of a loop. I believe >> that Mills' do-while-do loop is an unauthorized addition to Dijkstra's work. > > >What a hilarious post. I am sure that HM would be very amused by the idea >that he had to get "authorization" from EWD for stating what he (very >reasonably) defined as his notion of structured programming :-) For your entertainment, below my signature I have included a post which appeared about a month ago. It was initially sent by Ray Gardner. It gives us some insight into how Dijkstra felt regarding Harland Mills and his additions to Structured Programming. As for Mills' notions regarding SM, he is entitled to have them. And you are entitled to consider that mid-exit loops are part of SP because Mills said so. And I, I am entitled to conclude that mid-exit loops are not part of SP because Dijkstra unambiguously excluded them. And, in this matter, I think Dijkstra has priority. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com ====================================================================== Here's a clue, maybe. Don't read too much into it. From "EWD494: Trip Report E.W. Dijkstra 16th April/7th May, 1975, U.S.A. and Canada", reprinted in _Selected Writings on Computing: A Personal Perspective_, E.W. Dijkstra, Springer-Verlag, 1982 (a _really_ neat sample of Dijkstra's EWD papers, which I think were mostly circulated only to colleagues by a sort of samizdat): [Dijkstra stays with A. Wasserman, lectures at Berkeley, speaks at ACM Pacific 75, lectures at Stanford, stays at Knuth's house. Parties back at Wasserman's, meeting Karp, Floyd, and Backus. Goes to LA for the International Conference on Software Reliability. Acerbic remarks. Goes to ISI (?) to meet with Manna, Ershov, Burstall, Randell, Turski, Wulf, and others, sees an unconvincing demonstration of automatic program-proving. Goes to Phoenix for an ACM Chapter meeting [damn, why didn't we ever get him to Denver when we had a viable chapter?], goes to Mission Viejo to visit the Burroughs Large Systems Plant. Flies to Montreal to attend an IBM conference on Software Engineering Education.] "... in my innocence I had expected an audience of computer scientists. My driver, however, was a manager, who opened the conversation with something like 'so you are the world expert on structured programming and chief programmer teams.'. Then I knew that I was out in the wilderness and politely refused to be associated with Harlan D. Mills." [More very acerbic remarks: "The ... conference was very instructive for me, although I learned a lot without which I would have been happier. At most fify percent of the partcipants were computing scientists; the rest were either IBM officials or managers of the [DP] departments of large IBM customers. I had full opportunity to observe all the intricate love/hate relations between the angles of the triangle 'university-manufacturer- customer'. It was all very frightening and I wish that I had a mastery of my pen like Arthur Koestler, for then I could have written a companion volume to his 'The Call Girls'." "The central victims in this drama are the [MBAs] and the firms dependent on their services ... They really have painted themselves into a corner with very sticky molasses! They have made a number of unforgiveable mistakes. One mistake is that they have based their full automation upon the IBM/360. When that machine was announced, it was immediately clear to many -- even inside IBM!-- that it would be practically impossible to write decent software for it... You cannot program a crooked machine to go straight ... The next mistake is that they decided to program in COBOL. ... OS/360 is no longer 'logical spaghetti', but 'logical barbed wire'. ... on the whole it was ghastly; unreal. I was severely shocked by the cultural level of the business participants. ..."] "Later I heard Harlan Mills give a summing up of some of the things I had said --together with some Harlanesk additions-- for that business audience. It was terrible, a misuse of language to which to the best of my powers I could not give a meaning. So, every third phrase I interrupted Harlan 'please could you explain or restate what you tried to say', but it was hopeless. Tom Hull helped me and I was very grateful to him. Later, when it was all over, our eyes met, and Tom gasped 'Jezus!'. It was the first time that I had heard him use strong language. How to sell empty but impressive slogans under the cloak of academic respectibility... ." "Turski's comments were short: 'They don't want computer scientists, nor software engineers, they want brainwashed mental cripples.'. It is too true... ." "On the last morning, Harlan Mills gave the summing up talk. It was again very much of the same, but, remarkably enough, I learned something from him, viz. the expression 'entry level jobs'. His argument was that the university should not train experts --as an aside: training and education were constantly confused-- because the jobs those experts should get were not 'entry level jobs'. This may be a profound difference between the academic community and (at least some of) the business community: there is not the slightest objection to giving the most responible university function, viz. a full professorship, to a youngster who has just got his Ph.D. It does not happen so very often, because really brilliant people are rare; but nothing in the university environment forbids it ... But to the business communities represented it was unthinkable to give a youngster any real responsibility... ." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-04 0:00 ` Robert C. Martin @ 1998-10-05 0:00 ` Ell 1998-10-05 0:00 ` Ell 1998-10-05 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-10-05 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> wrote: >... And I, I am entitled to conclude that mid-exit loops are not part >of SP because Dijkstra unambiguously excluded them. Where? > And, in this matter, I think Dijkstra has priority. Why? Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-05 0:00 ` Ell @ 1998-10-05 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-05 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >"Robert C. Martin" <rmartin@oma.com> wrote: > >>... And I, I am entitled to conclude that mid-exit loops are not part >>of SP because Dijkstra unambiguously excluded them. >Where? And even if he did it isn't the essence of SP. Abstraction is. Modelling is! :-} And I can show you where Dijkstra said that himself. ("Art of Literate Programming", D. Knuth, CLSC, pg 72) Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-04 0:00 ` Robert C. Martin 1998-10-05 0:00 ` Ell @ 1998-10-05 0:00 ` Ell 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-10-05 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> wrote: >For your entertainment, below my signature I have included a post which >appeared about a month ago. It was initially sent by Ray Gardner. It gives >us some insight into how Dijkstra felt regarding Harland Mills and his >additions to Structured Programming. > >[elided post] I can see nothing in it that makes a reasoned and meaningful case against Mills with regard to anything, including software engineering. Perhaps it was due to how he was quoted, but on the whole the quote is fuzzy, mildly incoherent and hard to get anything out of. It seems he had some problem with IBM, the 360, and universities and that Mills was somehow involved in with them in ways he did not like. But it is really not clear. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Robert C. Martin ` (3 preceding siblings ...) 1998-10-05 0:00 ` dewarr @ 1998-10-09 0:00 ` Matthew Heaney 1998-10-09 0:00 ` Ell 4 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-10-09 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> writes: > Yes, Mills did make this definition. However, I am referring to the work of > Dijkstra in the late 60's and early 70's. Dijkstra was very clear about the > notion of single entry and single exit within the body of a loop. I think it's debateable whether Dijkstra was "very clear" about the a single exit means, given the popularity of this thread. Dijkstra's argument was to avoid constructions in which you could jump out of one abstraction directly into another, and to restrict oneself to "systematic sequencing mechanisms." Based on my own reading of his monograph, I would interpret "single exit" to include early returns (or loop exits), because all returns go to a single point - the point of call. > I believe that Mills' do-while-do loop is an unauthorized addition to > Dijkstra's work. I don't think Dijkstra is in the business of "authorizing" what loop constructs are allowed. Indeed, as David Gries has pointed out, in his monograph, Dijkstra nowhere defines what "structured programming" actually means. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-09 0:00 ` Matthew Heaney @ 1998-10-09 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-09 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> wrote: >I don't think Dijkstra is in the business of "authorizing" what >loop constructs are allowed. Indeed, as David Gries has pointed out, in >his monograph, Dijkstra nowhere defines what "structured programming" >actually means. In a quote close to an overall view he said that the first thing he thought of when someone mentioned structured programming was "abstraction". ("The Art of Literate Programming", D. Knuth, CLSC, page 72) This tends to back up the point I (and I think Heaney) have made in previous articles that it seems Dijkstra was emphasizing that navigation should mainly take place between coherent abstractions as opposed navigating between free standing entities. It also makes me think that modelling was a key aspect of the structured paradigm because the essential act of abstraction, "the act or process of separating the inherent qualities or properties of something from the actual physical object or concept to which they belong" is also the essence of modelling and simulation in software engineering generally. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Robert C. Martin 1998-10-02 0:00 ` Charles H. Sampson 1998-10-02 0:00 ` John I. Moore, Jr. @ 1998-10-02 0:00 ` Ell 1998-10-03 0:00 ` Ell 1998-10-05 0:00 ` Graham Perkins 1998-10-09 0:00 ` Matthew Heaney 4 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-10-02 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> wrote: >The question that the post was addressing had to do with the definition of >structured programming. A mid exit loop does not fall within the bounds >defined by structured programming because the loop body does not then have a >single entry and a single exit. > >This has nothing to do with whether mid exit loops are good or bad. It only >has to do with whether mid exit loops conform to structured programming or >not. Correction, I should have said "end-exit" rather that "single entry/single exit (se/se)" in my last post in this thread. Both "end-exit" and "mid-exit" loops may adhere to the principles of structured programming. There is no structured literature which argues against loop (or other entity) "mid-exit" in structured coding. There is literature which stipulates using single entry to and single exit from flowcharts pages, but that is not the same thing. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Ell @ 1998-10-03 0:00 ` Ell 1998-10-03 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-10-03 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >Correction, I should have said "end-exit" rather that "single >entry/single exit (se/se)" in my last post in this thread. Actually, I guess there are some who strongly and wrongly argue for general adherence to "end-exit" and against "multiple-exit" for some alleged dependency management (DM) benefit. The 2 concepts are of course easily related because none "end-exit" might include "multiple-exit". Anyone who looks at a fair amount of non-OO, procedural code made by knowledgeable, and experienced programmers will see the quite generous and proper use of "non end-exits" and "multiple-exists". Of course the code is usually squeakingly correct with respect to DM, intuitive key domain entity expression, overall conceptual readability. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-03 0:00 ` Ell @ 1998-10-03 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-10-03 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >Anyone who looks at a fair amount of non-OO, procedural code made by >knowledgeable, and experienced programmers will see the quite generous >and proper use of "non end-exits" and "multiple-exists". Of course >the code is usually squeakingly correct with respect to DM, intuitive >key domain entity expression, overall conceptual readability. rather: >Anyone who looks at a fair amount of non-OO, procedural code made by >knowledgeable, and experienced programmers will see the quite generous >and proper use of "non end-exits" and "multiple-exits". Of course >the code is usually squeakingly correct with respect to DM, intuitive >key domain entity expression, [as well as] >overall conceptual readability. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Robert C. Martin ` (2 preceding siblings ...) 1998-10-02 0:00 ` Ell @ 1998-10-05 0:00 ` Graham Perkins 1998-10-08 0:00 ` s350817 1998-10-09 0:00 ` Matthew Heaney 4 siblings, 1 reply; 510+ messages in thread From: Graham Perkins @ 1998-10-05 0:00 UTC (permalink / raw) Robert C. Martin wrote: > >> >loop > >> > ... stuff > >> > exit when ; > >> > ... stuff > >> >end loop; > ... > The question that the post was addressing had to do with the definition of > structured programming. A mid exit loop does not fall within the bounds > defined by structured programming because the loop body does not then have a > single entry and a single exit. I beg to differ. The construct as a whole has single entry and exit points. So I think we could be entitled to regard it as a structured programming construct. Try slicing a CASE flowchart across the middle .. you get more than one flow line crossing the cut! Crucially, other parts of the program may not transfer control to any intermediate point between LOOP-EXIT, nor gain control from any such point. ---------------------------------------------------------------- Graham Perkins, De Montfort University, Milton Keynes http://www.mk.dmu.ac.uk/~gperkins/ ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-05 0:00 ` Graham Perkins @ 1998-10-08 0:00 ` s350817 0 siblings, 0 replies; 510+ messages in thread From: s350817 @ 1998-10-08 0:00 UTC (permalink / raw) Graham Perkins wrote: > > Robert C. Martin wrote: > > >> >loop > > >> > ... stuff > > >> > exit when ; > > >> > ... stuff > > >> >end loop; > > ... > > The question that the post was addressing had to do with the definition of > > structured programming. A mid exit loop does not fall within the bounds > > defined by structured programming because the loop body does not then have a > > single entry and a single exit. > > I beg to differ. > > The construct as a whole has single entry and exit points. So I > think we could be entitled to regard it as a structured programming > construct. Try slicing a CASE flowchart across the middle .. you > get more than one flow line crossing the cut! > > Crucially, other parts of the program may not transfer control > to any intermediate point between LOOP-EXIT, nor gain control > from any such point. > > ---------------------------------------------------------------- > Graham Perkins, De Montfort University, Milton Keynes > http://www.mk.dmu.ac.uk/~gperkins/ Assignment 1. Q 11 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-02 0:00 ` Robert C. Martin ` (3 preceding siblings ...) 1998-10-05 0:00 ` Graham Perkins @ 1998-10-09 0:00 ` Matthew Heaney 4 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-10-09 0:00 UTC (permalink / raw) "Robert C. Martin" <rmartin@oma.com> writes: > The question that the post was addressing had to do with the definition of > structured programming. A mid exit loop does not fall within the bounds > defined by structured programming because the loop body does not then have a > single entry and a single exit. > > This has nothing to do with whether mid exit loops are good or bad. It only > has to do with whether mid exit loops conform to structured programming or > not. The specific text of what Dijkstra said is (from section 7, "On Understanding Programs"): <<These flowcharts share the property that they have a single entry at the top and a single exit at the bottom: as indicated by the dotted block they can again be interpreted (by disregarding what is inside the dotted lines) as a single action in a sequential computation.>> [p. 19] He says later that: <<Alternatively: restricting ourselves to the three mentioned types of decomposition leads to flowcharts of a restricted topology compared with the flowcharts one can make when arrows can be drawn from any block leading into any other.>> [p. 20] I think the last part is very significant. As Bob Eachus pointed out, a subprogram with an early return really does have "single exit," because all returns lead to the same place, to the POINT OF CALL. Dijkstra's complaint was that you can't tell what the program does at run-time by reading the program text. One cause is the unbridled use of the goto statement, when you can jump out of a sequential abstraction (the block to which Dijkstra refers) into any other. By returning early from a subprogram, you are not "jumping into another abstraction." You are merely tracing another edge that leads to the SAME NODE (the point of call) in the graph of the program. He sums up that section by noting that: <<The moral of the story is that when we acknowledge our duty to control the computations (intellectually!) via the program text evoking them, that then we should restrict ourselves in all humility to the most systematic sequencing mechanisms, ensuring that "progress through the computation" is mapped on "progress through the text" in the most straightforward manner.>> [p. 23] I argue that an early return (appropriately used, of course) meets his criterion of understanding the mapping of static program text to dynamic program behavior. The whole point of structured programming is NOT to "use only these three control flow constructs." It is as he states in that last summary paragraph: that programs should be intellectually manageable. If a mid-loop exit simplifies a loop, or an early return simplifies a subprogram, then by all means use it. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-01 0:00 ` Charles H. Sampson 1998-10-02 0:00 ` Robert C. Martin @ 1998-10-02 0:00 ` Ell 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-10-02 0:00 UTC (permalink / raw) claveman@inetworld.net (Charles H. Sampson) wrote: > I apologize for responding to a post that's 31 days old. I got in >on this long thread very late and I'm running very hard to catch up. You shouldn't drag the group back down a road we just traveled the whole distance of for your benefit. What do you expect, for all of us to hop back on board and relive the journey until you catch up? We've dealt with loop and half and moved on far beyond that. If you must, you should contact those you have questions for off-line. Elliott -- :=***=: VOTE NO TO MODERATION! :=***=: CRAFTISM SHOULD NOT USE USENET RESOURCES TO AVOID CRITICISM! MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Study Phony Crafite OO vs. Genuine OO: http://www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Stephen Leake @ 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Patrick Logan ` (2 more replies) 2 siblings, 3 replies; 510+ messages in thread From: Matthew Heaney @ 1998-08-31 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >>>For example, there's a pernicious myth that exiting (or returning) from > >>>the middle of a loop is bad, and that the only proper way to write a > >>>loop is to state the termination condition explicitly, as a predicate > >>>appearing at the top of the loop. > > > >>Yes. That pernicious myth is called "structured programming". > > > >Please cite even just a single structured programming text, or founder > >where what you say here was asserted. > > "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. > 16-23 "7. On Understanding Programs". You might also want to read Structured Programming: Theory and Practice, by Linger, Mills, and Witt (Addison-Wesley, 1979). (It was Harlan Mills to whom I was alluding when I referred to "doctrinaire mathematicians." I've read his work, and what can I say, it just doesn't speak to me.) I also very highly recommend The Science of Programming, by David Gries. He comes from the Dijkstra/Hoare school, and I find his advice a lot more useful. But your mileage may vary. > Actually this section says that there are two different kinds of > loops. one that is tested at the top; and another which is tested at > the bottom. But in all cases, the elements of structure programming > have a single entry and a single exit. A loop that exits in the > middle, violates this maxim. I think the issue is meaning vs syntax. When I use an exit from the middle, it's to say that "I want to terminate the loop, NOW." The problem with exit at the top is that it defers the actual termination. I have to make sure no code gets executed unintentionally between the place at which the exit flag is set, and the bottom of the loop. I can almost live that. The real problem, however, is that using an extra flag to terminate VASTLY complicates the predicate. In fact, the flag doubles the number of states I have to think about when mentally evaluating the predicate! That's the real source of the loop termination errors. (I shouldn't have to remind anyone, but just in case: George Miller did a famous study about human cognitive limits, and found that people can remember about 7 things, plus or minus 2. That's why complex predicates make a programmer's head spin, and why he often gets loop termination wrong.) Using an exit from the middle avoids the headaches (literally) engendered by using an extra flag in the predicate. When you want to exit, you just say that you want to exit, directly. No mental gymnastics are required in order to determine whether you'll "really" exit, as would be the case using the flag approach. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney @ 1998-08-31 0:00 ` Patrick Logan 1998-09-01 0:00 ` dewarr 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Gene Gajewski 2 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-08-31 0:00 UTC (permalink / raw) In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: : > Actually this section says that there are two different kinds of : > loops. one that is tested at the top; and another which is tested at : > the bottom. But in all cases, the elements of structure programming : > have a single entry and a single exit. A loop that exits in the : > middle, violates this maxim. : I think the issue is meaning vs syntax. When I use an exit from the : middle, it's to say that "I want to terminate the loop, NOW." Almost every time I am tempted to terminate a loop in the middle, I ultimately choose not to. More important than that, IMHO, is that a loop's body not have a lot of text in it. If it is a five or ten line loop, at the most, then even if it terminates in the middle it will be easier to read. So a loop should communicate the control aspect of the operation, the body should rely on procedures/methods to carry out the bulk of the work. This also has the benefit of making the bulk of the work more reusable. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Patrick Logan @ 1998-09-01 0:00 ` dewarr 0 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-01 0:00 UTC (permalink / raw) In article <LRzG1.4391$f01.3488385@news.teleport.com>, Patrick Logan <plogan@user1.teleport.com> wrote: > In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: > > : > Actually this section says that there are two different kinds of > : > loops. one that is tested at the top; and another which is tested at > : > the bottom. But in all cases, the elements of structure programming > : > have a single entry and a single exit. A loop that exits in the > : > middle, violates this maxim. > > : I think the issue is meaning vs syntax. When I use an exit from the > : middle, it's to say that "I want to terminate the loop, NOW." > > Almost every time I am tempted to terminate a loop in the middle, I > ultimately choose not to. > > More important than that, IMHO, is that a loop's body not have a lot > of text in it. If it is a five or ten line loop, at the most, then > even if it terminates in the middle it will be easier to read. So a > loop should communicate the control aspect of the operation, the body > should rely on procedures/methods to carry out the bulk of the work. > > This also has the benefit of making the bulk of the work more > reusable. > > -- > Patrick Logan (H) mailto:plogan@teleport.com > (W) mailto:patrickl@gemstone.com > http://www.gemstone.com > Yes, that is really the key point here. The use of continue is almost always better replaced by something else, but not quite always. I actually feel that the provision of the keyword continue in C is a mistake, it encourages people to overuse this kind of skip. In Ada, you need to use "goto Continue_Loop", to get this effect. For those who are not hopelessly goto-allergic, this is just right, it makes you think "do I really need to use this special kind of goto, or is there a better way of doing things?" If the answer is yes, you really need to use this special kind of goto, then go ahead and use it! -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Patrick Logan @ 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Phlip 1998-08-31 0:00 ` Gene Gajewski 2 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-08-31 0:00 UTC (permalink / raw) >"Robert Martin" <rmartin@oma.com> writes: Matthew Heaney wrote: >> >>>For example, there's a pernicious myth that exiting (or returning) from >> >>>the middle of a loop is bad, and that the only proper way to write a >> >>>loop is to state the termination condition explicitly, as a predicate >> >>>appearing at the top of the loop. RCM wrote: >> >>Yes. That pernicious myth is called "structured programming". Elliott wrote: >> >Please cite even just a single structured programming text, or founder >> >where what you say here was asserted. > "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. > 16-23 "7. On Understanding Programs". > Actually this section says that there are two different kinds of > loops. one that is tested at the top; and another which is tested at > the bottom. But in all cases, the elements of structure programming > have a single entry and a single exit. A loop that exits in the > middle, violates this maxim. Please show me a Dijkstra, Dahle, Hoare quote that says "the elements of structure[d] programming have a single entry and single exit." Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Phlip 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) >RCM wrote: >>> >>Yes. That pernicious myth is called "structured programming". > >Elliott wrote: >>> >Please cite even just a single structured programming text, or founder >>> >where what you say here was asserted. RCM replied: >> "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. >> 16-23 "7. On Understanding Programs" Ell wrote in message <35ead1be.659708@news.erols.com>... >Please show me a Dijkstra, Dahle, Hoare quote that says "the elements >of structure[d] programming have a single entry and single exit." p19, in the section entitled: "Notes on Structured Programming": "These flowcharts also share the property of a single entry at the top and a single exit at the bottom." Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Charles Hixson 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-08-31 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: > > >>RCM wrote: >>>> >>Yes. That pernicious myth is called "structured programming". >> >>Elliott wrote: >>>> >Please cite even just a single structured programming text, or founder >>>> >where what you say here was asserted. > > >RCM replied: >>> "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. >>> 16-23 "7. On Understanding Programs" > > >Ell wrote in message <35ead1be.659708@news.erols.com>... >>Please show me a Dijkstra, Dahle, Hoare quote that says "the elements >>of structure[d] programming have a single entry and single exit." > >p19, in the section entitled: "Notes on Structured Programming": "These >flowcharts also share the property of a single entry at the top and a single >exit at the bottom." ??? Where is the generalized design heuristic? It certainly is not this statement. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Robert Martin 1998-09-03 0:00 ` Steven Perryman 1998-09-01 0:00 ` Charles Hixson 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Ell wrote in message <35eb36d9.729148@news.erols.com>... >"Robert Martin" <rmartin@oma.com> wrote: > >> >> >>>RCM wrote: >>>>> >>Yes. That pernicious myth is called "structured programming". >>> >>>Elliott wrote: >>>>> >Please cite even just a single structured programming text, or founder >>>>> >where what you say here was asserted. >> >> >>RCM replied: >>>> "Structured Programming", Dijkstra, Dahl, Hoare, Academic Press, 1972. p. >>>> 16-23 "7. On Understanding Programs" >> >> >>Ell wrote in message <35ead1be.659708@news.erols.com>... >>>Please show me a Dijkstra, Dahle, Hoare quote that says "the elements >>>of structure[d] programming have a single entry and single exit." >> >>p19, in the section entitled: "Notes on Structured Programming": "These >>flowcharts also share the property of a single entry at the top and a single >>exit at the bottom." > >??? > >Where is the generalized design heuristic? It certainly is not this >statement. The chapter that I have cited and quoted is a general description of structured programming, its constituents, its motivations, and its benefits. If you are looking for a one-liner, I'm afraid that Dijkstra wasn't anticipating you. But the design heuristic is in the chapter in any case; just not conviently isolated into a single quotable sentence. The essence of the chapter is that all programs ought to be constructed from simpler elements that have singly entry points and single exit points. The motivation is understandabililty and provability. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Steven Perryman 0 siblings, 0 replies; 510+ messages in thread From: Steven Perryman @ 1998-09-03 0:00 UTC (permalink / raw) In article <6sfqlr$gat$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: >The chapter that I have cited and quoted is a general description of >structured programming, its constituents, its motivations, and its benefits. >If you are looking for a one-liner, I'm afraid that Dijkstra wasn't >anticipating you. But the design heuristic is in the chapter in any case; >just not conviently isolated into a single quotable sentence. >The essence of the chapter is that all programs ought to be constructed from >simpler elements that have singly entry points and single exit points. The >motivation is understandabililty and provability. Correct. The bottom line has always been this : Dijkstra defined a set of primitive 'blocks' (if, while etc) . He asserts some 'state of being' prior to entering each block, and the state after exiting that block. Using the single-entry single-exit concept, he was able to precisely reason and verify the behaviour of those blocks. The blocks can then be used to build higher-level blocks (repeat-until, case etc) . These concepts then appear to have been taken on by folks like the Yourdon brigade et al, applied to functions and modules, resulting in the era that is called 'structured programming' (FWIW, I don't know when the term was officially first used, as is the case for the term 'OO' ) . While Elliott rants on looking for the one-liner soundbite that isn't, the rest of us know and accept that Dijkstra's work very much underpins the notions of 'structured programming in the small' . Regards, Steven Perryman stevenp@nortel.co.uk ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Charles Hixson 1 sibling, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-01 0:00 UTC (permalink / raw) Possibly instead of discussing what the original documents said, years before any (or at least any common) languages supported structured programming, we should talk about either our own experiences, or about studies of people using structured languages (since most of them contain facilities enabling non-structured programming also). I was impressed by structured programming when I first read a book describing how to do it in PL/1, and immediately started trying to restructure the FORTRAN programs that I was writing. This was NOT encouraged by the language design, but the results were encouraging enough to convince me to switch to more structured languages as they became available to me. They did NOT convince me that EVERYTHING should be structured. I feel free to allow myself one unstructrued construct per routine, provided that it is well documented, and has only local effect. I rarely need this permission, but sometimes I do. If I need two unstructured constructs, then I try REALLY HARD to break the routine in half. This rule keeps the routines intelligible, and lets me do whatever I need to do. Theory is great, and I try to be guided by those theories that I consider best. But I am, at heart, a practitioner, and my test for how good I think a theory is, is "How well can I use this?" ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin @ 1998-08-31 0:00 ` Phlip 1998-08-31 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: Phlip @ 1998-08-31 0:00 UTC (permalink / raw) Ell wrote: >Please show me a Dijkstra, Dahle, Hoare quote that says "the elements >of structure[d] programming have a single entry and single exit." Uh, I'd be more interested in any of those guys saying "functions should be short". Anything else is just an excuse to keep functions remotely comprehensible even if they'r long... -- Phlip (no replies - address changed) ======= http://users.deltanet.com/~tegan/home.html ======= -- The lunatics have stock options in the asylum -- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Phlip @ 1998-08-31 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-08-31 0:00 UTC (permalink / raw) Phlip wrote in message <6sf8nn$34n$1@news0-alterdial.uu.net>... >Ell wrote: > >>Please show me a Dijkstra, Dahle, Hoare quote that says "the elements >>of structure[d] programming have a single entry and single exit." > >Uh, I'd be more interested in any of those guys saying "functions should be >short". > >Anything else is just an excuse to keep functions remotely comprehensible >even if they'r long... Short functions can still be badly structured. Short does not, necessarily, imply good. (although it can sure help). The stack compare function is a good example, it is short, but could still be better structured through the use of single/entry and single/exit. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Patrick Logan 1998-08-31 0:00 ` Ell @ 1998-08-31 0:00 ` Gene Gajewski 2 siblings, 0 replies; 510+ messages in thread From: Gene Gajewski @ 1998-08-31 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: > <schnip> >The problem with exit at the top is that it defers the actual >termination. I have to make sure no code gets executed unintentionally >between the place at which the exit flag is set, and the bottom of the >loop. > >I can almost live that. The real problem, however, is that using an >extra flag to terminate VASTLY complicates the predicate. In fact, the >flag doubles the number of states I have to think about when mentally >evaluating the predicate! That's the real source of the loop >termination errors. > >(I shouldn't have to remind anyone, but just in case: George Miller did >a famous study about human cognitive limits, and found that people can >remember about 7 things, plus or minus 2. That's why complex predicates >make a programmer's head spin, and why he often gets loop termination >wrong.) I've been following this thread for some time.... I wasn't aware that anyone did any specific research on cognitive limits, but I posit this is something intuitive. I've made a post to this sometime before. I believe we encounter such things as a rule that states 'there shall be but one exit point' because there are those who analyze code mechanistically, without bothering to aquire an understanding of what the code is doing. I sat recently sat through a 'code review', which was really a boss's one-on-one style check, and got hammered severely about some constructs I used in a particular function. A real knock-down/drag-out bitch fest. The words 'Well, I understand it NOW that I've read it" were actually uttered during that session, and not by me.... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Charles Hixson 1 sibling, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-01 0:00 UTC (permalink / raw) Actually, flat earth is a good example. Flat-earth makes a good local map (for a properly choosen size of local). It just doesn't extend well to a global solution. The same is true of 'goto'. Ell wrote: > > "Robert Martin" <rmartin@oma.com> wrote: > ... > >"Cognitive fit" is probably not a very good criterion for good engineering. > >GOTO has a very good cognitive fit. So does a flat Earth. > > I would assert that 'goto' spaghetti coding is only a cognitive fit to > you, and handful of others, not most of us. > > Flat earth is not cognitive to people living on the coast who see the > mast of a ship appear before the bow. > > Elliott > -- > :=***=: Objective * Pre-code Modelling * Holistic :=***=: > Hallmarks of the best SW Engineering > "The domain object model is the foundation of OOD." > Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell > Copyright 1998 Elliott. exclusive of others' writing. may be copied > without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au> @ 1998-09-01 0:00 ` Gerry Quinn 1998-09-01 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Gerry Quinn @ 1998-09-01 0:00 UTC (permalink / raw) In article <904556531.666222@miso.it.uq.edu.au>, ahussey@it.uq.edu.au (Andrew Hussey) <m3af4mq7f4.fsf@mheaney.ni.net> wrote: >>Using an exit from the middle avoids the headaches (literally) >>engendered by using an extra flag in the predicate. When you want to >>exit, you just say that you want to exit, directly. No mental >>gymnastics are required in order to determine whether you'll "really" >>exit, as would be the case using the flag approach. > >That's brilliant, now your code is much easier to write! >Now let's see who has an easier time *testing* their code. >I think you'll find the control-flow errors you introduce >in the spaghetti you produce will more than make up for >any gain you have from rapid coding. > A characteristic of 'spaghetti' is that the strings both start and finish in unpredictable places, leading to a tangled mass. Multiple exits to a single destination are not spaghetti. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Gerry Quinn @ 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerry Quinn ` (3 more replies) 0 siblings, 4 replies; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... >Multiple exits to a single destination are not spaghetti. Spaghetti is not a well defined term. However, multiple exits to a single destination represent a problem. The two exits come from two different states within the algorithm. If the single destination must do some work that depends upon that state (or if in the future, that single destination must be modified to do work that depends upon that state), then the code in the single destination is going to get pretty ugly. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-01 0:00 ` Gerry Quinn 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Mike Spille ` (2 subsequent siblings) 3 siblings, 1 reply; 510+ messages in thread From: Gerry Quinn @ 1998-09-01 0:00 UTC (permalink / raw) In article <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > >Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... > >>Multiple exits to a single destination are not spaghetti. > >Spaghetti is not a well defined term. > How strange, then, that such sloppy language is endemic among those who believe they hold the line against sloppy coding... >However, multiple exits to a single destination represent a problem. The >two exits come from two different states within the algorithm. If the >single destination must do some work that depends upon that state (or if in >the future, that single destination must be modified to do work that depends >upon that state), then the code in the single destination is going to get >pretty ugly. > All code presents a problem, and a perfectionist could never write a line, one is so often forced to choose between alternatives each of which is ugly in its own way. When cleanup is unlikely to be needed, multiple exits are unlikely to pose a problem, and indeed can only be avoided by artificially extending the process. All conventional computation proceeds by the discarding of algorithmic states, and all destinations eventually end in one, irrespective of the merging mechanisms employed. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Gerry Quinn @ 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Gerry Quinn 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Gerry Quinn wrote in message <6shbca$66c$1@news.indigo.ie>... >In article <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: >> >>Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... >> >>>Multiple exits to a single destination are not spaghetti. >> >>Spaghetti is not a well defined term. >> >How strange, then, that such sloppy language is endemic among those >who believe they hold the line against sloppy coding... It's not strange at all. The common definition of Spaghetti is: "I don't like it.". Please note that in this thread I have not characterized anyone elses examples as spaghetti. I have tried to stick to more substantive complaints. I think this is important. Spaghetti is a subjective term that accomplishes little as a description. > >When cleanup is unlikely to be needed, multiple exits are unlikely to >pose a problem. Granted. But do the benefits of multiple exits outweigh the risks that cleanup might one day be needed? That is an engineering decision; and does not have a general answer. There are ,indeed, times when I will use multiple exits. But I have to be pretty sure that the code is short lived, and will not be subject to maintenance during its short lifetime. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Gerry Quinn 1998-09-02 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Gerry Quinn @ 1998-09-02 0:00 UTC (permalink / raw) In article <6shhq7$lut$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: >Gerry Quinn wrote in message <6shbca$66c$1@news.indigo.ie>... >>In article <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> >wrote: >>>Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... >>> >>>>Multiple exits to a single destination are not spaghetti. >>> >>>Spaghetti is not a well defined term. >>> >>How strange, then, that such sloppy language is endemic among those >>who believe they hold the line against sloppy coding... > >It's not strange at all. The common definition of Spaghetti is: "I don't >like it.". > Spaghetti does have a meaning - it is a metaphor for code in which multiple goto statements jump to multiple labels, forward and backwards. It describes such code very well (it also well describes threads on Usenet...). It does not describe what we have been talking about here. Thirty years ago, primitive versions of Basic may indeed have lent themselves to such code due to an absence of proper control structures. And of course assembler is typically full of spaghetti for the same reason. >Please note that in this thread I have not characterized anyone elses >examples as spaghetti. I have tried to stick to more substantive >complaints. I think this is important. Spaghetti is a subjective term that >accomplishes little as a description. I would say rather that it is an objective term, nowadays used incorrectly as a term of abuse by those who do not actually understand the meaning of the word. [--] - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Gerry Quinn @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Gerry Quinn 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Gerry Quinn wrote in message <6sjbso$1lk$2@news.indigo.ie>... >I would say rather that [spaghetti] is an objective term, nowadays used >incorrectly as a term of abuse by those who do not actually understand >the meaning of the word. FYI, here is the entry in the Hacker Jargon Dictionary: spaghetti code /n./ Code with a complex and tangled control structure, esp. one using many GOTOs, exceptions, or other `unstructured' branching constructs. Pejorative. The synonym `kangaroo code' has been reported, doubtless because such code has so many jumps in it. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 1998-09-04 0:00 ` Andre Tibben 1998-09-02 0:00 ` Gerry Quinn 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) On Wed, 2 Sep 1998 08:41:47 -0500, "Robert Martin" <rmartin@oma.com> wrote: >Gerry Quinn wrote in message <6sjbso$1lk$2@news.indigo.ie>... > >>I would say rather that [spaghetti] is an objective term, nowadays used >>incorrectly as a term of abuse by those who do not actually understand >>the meaning of the word. >FYI, here is the entry in the Hacker Jargon Dictionary: > >spaghetti code /n./ Code with a complex and tangled control structure, esp. >one using many GOTOs, exceptions, or other `unstructured' branching >constructs. Pejorative. The synonym `kangaroo code' has been reported, >doubtless because such code has so many jumps in it. 'exit', and 'return' are not "unstructured" branching as I see it. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-04 0:00 ` Andre Tibben 1998-09-04 0:00 ` Patrick Doyle 0 siblings, 1 reply; 510+ messages in thread From: Andre Tibben @ 1998-09-04 0:00 UTC (permalink / raw) Ell wrote: > >FYI, here is the entry in the Hacker Jargon Dictionary: > > > >spaghetti code /n./ Code with a complex and tangled control structure, esp. > >one using many GOTOs, exceptions, or other `unstructured' branching > >constructs. Pejorative. The synonym `kangaroo code' has been reported, > >doubtless because such code has so many jumps in it. > > 'exit', and 'return' are not "unstructured" branching as I see it. They are unstructered in the sense that they can be placed anywhere in the enclosing function. A much more structered way to express return values would be to have a special place to specify the return value (possibly just an expression before the end) and use the 'return'or 'exit' keyword only for special cases where you do want to exit at another place. An editor could in that case use a really ugly color to make it apparent that extra care is needed when changing the code. Andre Tibben ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Andre Tibben @ 1998-09-04 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-04 0:00 UTC (permalink / raw) In article <35EF1276.2AF4D06B@a1.nl>, Andre Tibben <a.tibben@a1.nl> wrote: >Ell wrote: >> >> 'exit', and 'return' are not "unstructured" branching as I see it. > >They are unstructered in the sense that they can be placed anywhere in >the enclosing function. More importantly, they are unstructured in the sense that they are not implementing any of the *structures* that Dijkstra proposed. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Gerry Quinn 1998-09-02 0:00 ` Robert Martin [not found] ` <6skqf3$ <35F0B5B0.8E2D0166@s054.aone.net.au> 1 sibling, 2 replies; 510+ messages in thread From: Gerry Quinn @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sjijg$36r$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > >Gerry Quinn wrote in message <6sjbso$1lk$2@news.indigo.ie>... > >>I would say rather that [spaghetti] is an objective term, nowadays used >>incorrectly as a term of abuse by those who do not actually understand >>the meaning of the word. > > >FYI, here is the entry in the Hacker Jargon Dictionary: > >spaghetti code /n./ Code with a complex and tangled control structure, esp. >one using many GOTOs, exceptions, or other `unstructured' branching >constructs. Pejorative. The synonym `kangaroo code' has been reported, >doubtless because such code has so many jumps in it. > Seems clear enough. Single entry and multiple exits is not a complex or tangled structure. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Gerry Quinn @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` sureshvv [not found] ` <6skqf3$ <35F0B5B0.8E2D0166@s054.aone.net.au> 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Gerry Quinn wrote in message <6skhcm$1dr$2@news.indigo.ie>... >In article <6sjijg$36r$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: >> >>Gerry Quinn wrote in message <6sjbso$1lk$2@news.indigo.ie>... >> >>>I would say rather that [spaghetti] is an objective term, nowadays used >>>incorrectly as a term of abuse by those who do not actually understand >>>the meaning of the word. >> >> >>FYI, here is the entry in the Hacker Jargon Dictionary: >> >>spaghetti code /n./ Code with a complex and tangled control structure, esp. >>one using many GOTOs, exceptions, or other `unstructured' branching >>constructs. Pejorative. The synonym `kangaroo code' has been reported, >>doubtless because such code has so many jumps in it. >> > >Seems clear enough. Single entry and multiple exits is not a >complex or tangled structure. Nor did I say it was. I simply said that it carries certain risks. ==================================================================== I have found the enthusiasm for this thread quite interesting; but also a bit disquieting. Structured Programming is one of the foundational elements of software engineering. Knowledge of the benefits and costs of single-entry/single-exit functions should be firmly ingrained in all software engineers. In this thread I have not demanded that everyone *must* use se/se, nor have I accused anyone of writing spaghetti, nor have I said that people who use multiple exits are wrong to do so. What I have done is discuss and demonstrate some of the risks of multiple exits, and some of the benefits of se/se. I have pointed out that "readability" is not the only concern, and that the simplest modules are not always the most maintainable. And yet the reactions have ranged from: "the benefits of se/se don't really exist" to "se/se is not a fundemental part of structured programming". I find these reactions puzzling, at best. Are tree structures OK? The word OK has no meaning in this context. They have a benefit, and they have a cost, and in some situations the cost and benefit will work out such that there is a net gain. Is it OK to write code with multiple exits? In some cases, yes; in others, no. The important thing is not whether a technique is "good" or "bad", the important thing is to understand the costs and benefits of a technique. Engineering is the ability to make trade-offs. To make those decisions, we must know what we are trading off for what. We cannot rely on simple maxims like "readability is best", or "never use gotos", or "only do the minimum", or "never use multiple exits". We have to be more intelligent than that. We have to be engineers. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Ell 1998-09-04 0:00 ` Ell 1998-09-03 0:00 ` sureshvv 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-03 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: >I have found the enthusiasm for this thread quite interesting; but also a >bit disquieting. Structured Programming is one of the foundational elements >of software engineering. Knowledge of the benefits and costs of >single-entry/single-exit functions should be firmly ingrained in all >software engineers. Your completely unsubstantiated, fantasy lie that "single entry, single exit" is a key aspect of structured programming is deplorable, and stinks to high heaven. Think "avoid unstructured control flow", and not "avoid single entry, single exit". Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ell @ 1998-09-04 0:00 ` Ell 1998-09-03 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >"Robert Martin" <rmartin@oma.com> wrote: > >>I have found the enthusiasm for this thread quite interesting; but also a >>bit disquieting. Structured Programming is one of the foundational elements >>of software engineering. Knowledge of the benefits and costs of >>single-entry/single-exit functions should be firmly ingrained in all >>software engineers. >Your completely unsubstantiated, fantasy lie that "single entry, >single exit" is a key aspect of structured programming is deplorable, >and stinks to high heaven. >Think "avoid unstructured control flow", and not "avoid single entry, >single exit". Rather: Think "avoid unstructured control flow", and not "avoid [creating code which has multiple exits]". That's the true spirit of one aspect of the structured paradigm as I see it. The other being that we should use abstractions to design code and to model functional domain processes. It was Dijkstra who said he thinks of *abstraction* when someone mentions "structured programming". (The Art of Literate Programming, Knuth, CLCS, page 72) Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell @ 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Ell wrote in message <35f23ce2.7649859@news.erols.com>... > >Think "avoid unstructured control flow", and not "avoid [creating code >which has multiple exits]". You had best define 'unstructured' in this context. Dijkstra's definition of 'unstructured control flow' is control flow that does not conform precisely to the four standard sequencing elements {sequence, selection, top exit loop, bottom exit loop}, all of which have a single entry and a single exit. >That's the true spirit of one aspect of the structured paradigm as I >see it. The other being that we should use abstractions to design >code and to model functional domain processes. > >It was Dijkstra who said he thinks of *abstraction* when someone >mentions "structured programming". Indeed, Dijkstra talks about abstraction quite a bit in the book "Structured programming". One of his uses of the term is that the four sequencing elements he recommends can all be considered to be units whose internals can, at times, be ignored (i.e. abstracted away) because they have a single entry and a single exit. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Doyle 1998-09-04 0:00 ` Robert Martin 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: > >Ell wrote in message <35f23ce2.7649859@news.erols.com>... > >> >>Think "avoid unstructured control flow", and not "avoid [creating code >>which has multiple exits]". >You had best define 'unstructured' in this context. Dijkstra's definition >of 'unstructured control flow' is control flow that does not conform >precisely to the four standard sequencing elements {sequence, selection, top >exit loop, bottom exit loop}, all of which have a single entry and a single >exit. Where is this documented? Where has Dijkstra stated that flow control must conform precisely to the 4 specific elements you mention? I know that sequence, selection, and *looping * are major appropriate flow control elements, but please show where Dijkstra says that "top exit loop" and "bottom exit loop" are, or should be standard flow control elements. >>That's the true spirit of one aspect of the structured paradigm as I >>see it. The other being that we should use abstractions to design >>code and to model functional domain processes. >> >>It was Dijkstra who said he thinks of *abstraction* when someone >>mentions "structured programming". >Indeed, Dijkstra talks about abstraction quite a bit in the book "Structured >programming". One of his uses of the term is that the four sequencing >elements he recommends can all be considered to be units whose internals >can, at times, be ignored (i.e. abstracted away) because they have a single >entry and a single exit. Please refer to relevant citations to back up this assertion. I have seen nothing that Dijkstra refers to explicitly about se/se on other than what you quoted about flowcharts. And this everyone knows is how to create flowcharts on a page - one entry point, one exit. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell @ 1998-09-04 0:00 ` Patrick Doyle 1998-09-05 0:00 ` Ell 1998-09-04 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-09-04 0:00 UTC (permalink / raw) In article <35ef7dff.24318728@news.erols.com>, Ell <ell@access.digex.net> wrote: > >"Robert Martin" <rmartin@oma.com> wrote: >> >>You had best define 'unstructured' in this context. Dijkstra's definition >>of 'unstructured control flow' is control flow that does not conform >>precisely to the four standard sequencing elements {sequence, selection, top >>exit loop, bottom exit loop}, all of which have a single entry and a single >>exit. > >Where is this documented? Where has Dijkstra stated that flow control >must conform precisely to the 4 specific elements you mention? I know >that sequence, selection, and *looping * are major appropriate flow >control elements, but please show where Dijkstra says that "top exit >loop" and "bottom exit loop" are, or should be standard flow control >elements. When Robert does so, do you promise to finally admit you're wrong? :-) -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Patrick Doyle @ 1998-09-05 0:00 ` Ell 1998-09-05 0:00 ` Jeffrey C. Dege 1998-09-05 0:00 ` Loryn Jenkins 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-09-05 0:00 UTC (permalink / raw) doylep@ecf.toronto.edu (Patrick Doyle) wrote: >Ell <ell@access.digex.net> wrote: >> >>"Robert Martin" <rmartin@oma.com> wrote: >>> >>>You had best define 'unstructured' in this context. Dijkstra's definition >>>of 'unstructured control flow' is control flow that does not conform >>>precisely to the four standard sequencing elements {sequence, selection, top >>>exit loop, bottom exit loop}, all of which have a single entry and a single >>>exit. >>Where is this documented? Where has Dijkstra stated that flow control >>must conform precisely to the 4 specific elements you mention? I know >>that sequence, selection, and *looping * are major appropriate flow >>control elements, but please show where Dijkstra says that "top exit >>loop" and "bottom exit loop" are, or should be standard flow control >>elements. >When Robert does so, do you promise to finally admit you're wrong? :-) How long will take for him not to show evidence, as he well should, before you acknowledge that he's blowing smoke? And moreover at that point will you acknowledged that you gave RCM the "gut feeling" benefit of the doubt, as evidenced by your comments above, because you have an ideological affinity with him, or for some other non-valid reason? Whatever it is that causes you to spontaneously adopt RCM's position in a discussion, it is not based on facts. Because generally I've produced more concrete, and more accurate facts on the issues than he has over the years. And likewise I have generally adopted the more correct position in discussions on comp.object over the years. If you acknowledge this, will you then quit as proposed moderator? Because as evidenced here, you will accept RCM's position without facts simply because you have an ideological affinity, or other non-valid reason to do so. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Ell @ 1998-09-05 0:00 ` Jeffrey C. Dege 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-05 0:00 UTC (permalink / raw) On Sat, 05 Sep 1998 02:47:33 GMT, Ell <ell@access.digex.net> wrote: >doylep@ecf.toronto.edu (Patrick Doyle) wrote: > > >>When Robert does so, do you promise to finally admit you're wrong? :-) > >How long will take for him not to show evidence, as he well should, >before you acknowledge that he's blowing smoke? > >And moreover at that point will you acknowledged that you gave RCM the >"gut feeling" benefit of the doubt, as evidenced by your comments >above, because you have an ideological affinity with him, or for some >other non-valid reason? I expect the reason that Patrick Doyle believes that Robert Martin is correct in claiming that Dijsktra advocated se/se is because every reference to structured programming they've ever seen also claimed that Dijkstra advocated se/se. I don't have Dijkstra's books and articles available, but the software engineering texts I do have are unanimous on this point. From "Software Engineering, Methods and Management", by Annelise von Mayrhuaser, 1990, (ISBN 0-12-727320-4), p. 373: The goal of the coding effort is to translate the design into a set of Single-Entry-Single-Exit (SESE) modules. From "Software Engineering", by Stephen R. Schach, 1990, (ISBN 0-256-08515-3), p. 311: A product is structured if the code blocks are connected by concatenation, selection, and iteration only, and every block has exactly one entry and one exit. Neither of these authors are seminal figures in SE like Dijkstra or Knuth, But then, these aren't ground-breaking expositions of new ideas, they are undergraduate-level textbooks for SE survey courses, which is why I have them lying around the house. These two quotes do not, admittedly, demonstrate that Dijkstra advocated se/se as a part of structured programming. They do, however, explain why Robert and Patrick are so adamanent about the idea that se/se is a part of structured programming, because the authors of the college textbooks said so. It is certainly possible that Dijkstra didn't stress se/se in his original work on structured programming. The only one of his early works on the subject I have access to is his GOTO letter, which doesn't begin to explore the consequences of the idea. But what is certainly true is that the programming profession, for a great many years now, has considered se/se one of the fundamental principles of structured programming. -- The aim of science is to seek the simplest explanations of complex facts. Seek simplicity and distrust it. -- Whitehead. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Jeffrey C. Dege @ 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Matthew Heaney ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-05 0:00 UTC (permalink / raw) jdege@jdege.visi.com (Jeffrey C. Dege) writes: > These two quotes do not, admittedly, demonstrate that Dijkstra advocated > se/se as a part of structured programming. They do, however, explain > why Robert and Patrick are so adamanent about the idea that se/se is > a part of structured programming, because the authors of the college > textbooks said so. > > It is certainly possible that Dijkstra didn't stress se/se in his > original work on structured programming. The only one of his early > works on the subject I have access to is his GOTO letter, which > doesn't begin to explore the consequences of the idea. But what > is certainly true is that the programming profession, for a great > many years now, has considered se/se one of the fundamental > principles of structured programming. The best answer to the question "What is structured programming?" was provided by David Gries, in Chap 6, On Structured Programming, of his book Programming Methodology (Springer-Verlag, 1978). The chapter begins with the statement: "The term structured programming has been used with many different meanings since Edsger W. Dijkstra first coined the term. Actually, the term appeared in the title of his monograph Notes On Structured Programming [that's the "little black book" - matt], but as far as I can determine not in the monograph itself!" So Dijkstra never precisely defined the term "structured programming." Next sentence in Gries: "The lack of a precise definition has allowed, even encouraged, people to use it as they wished, to attribute to sp ["sp" is how Gries abbreviates "structured programming" - matt] what they themselves learned from reading Notes On Structures Programming, however different this might have been from Dijkstra's intent." Now we're getting warm. Ed Yourdon other authors have stated that structured programming means single entry/single exit modules, but did Dijkstra say this specifically? The answer would appear to be no. (I myself have the little black book around, and I'm going to make it a point to re-read it. Sadly, this classic text is long out of print, but I was able to find one in a used bookstore.) Next sentence of Gries: "Taken out of context or viewed in the wrong light, some of the resulting definations of sp that have appeared in the literature seem stupid (e.g., sp is programming without gotos), and it is quite understandable that programmers have looked askance when asked to learn and practice it." Gries lists impressions that various people have of sp. Here are some of them: (start of quote) 1. It is a return to common sense. 2. It is the general method by which our leading programmers program. 3. It is programming without the use of goto statements. 5. It is top down programming 6. sp theory deals with converting arbitrarily large and complex flowcharts into standard forms so that they can be represented by iterating and nesting a small number of basic and standard control logic structures (these usually being sequencing, alternation, and iteration) 7. sp is a manner of organizing and coding programs that makes that programs easily understood and modified 8. The purpose of sp is to control complexity through theory and discipline 9. sp should be characterized not by the absence of gotos, but by the presence of structure 10. A major function of the structuring of the program is to keep a correctness proof feasible [this one comes from Dijkstra, in Notes On Structured Programming] 11. A fundamental concept (of sp) is a proof of correctness. 13. sp is no panacea--it really consists of a formal notation for orderly thinking, an attribute not commonly inherent in programmers or any other type... (end of quote) Take a close look at item 10, from Dijkstra himself. Dijkstra stated in his original ACM letter is that there is a "conceptual gap between the static program and the dynamic process." His complaint was that an _unstructured_ program made it hard to reason about the program's behavior. What some advocates of the se/se policy seem to be forgetting is that the whole point is being able to mentally reason about behavior. By reading the program text, can you figure out what this program does? I provided a couple of simple examples, one of them an idiom for using a special input value to terminate a loop: loop Get (N); exit when N = 0; <process N> end loop; Is there anyone who doesn't understand what this code fragment does? Structured programming means keeping the code simple, where "simple" means "being able to easily tell what it does." It means being able to prove that it's correct. See item 7. In spite of the fact that this loop exits from the middle, I would argue that it does indeed fit the defination of a "structured" program. We've been debating whether a program that terminates a loop from the middle, or does an early return, is really a "structured" program, but I think this misses the point. We should instead be asking, Can I mentally reason about this program's behavior? Am I able to write a correctness proof for this program? Am I confident that this program works? That's the real meaning of "structured." Back to Gries: "Let me give C. A. R. Hoare's definition, which I feel captures the essence of sp: "The task of organizing one's thought in a way that leads, in a reasonable time, to an understandable expression of a computing task, has come to be called sp."" Again, I would argue that in my comparision operation, even though it terminates via multiple returns, can indeed be called a "structured" program, because it's "an understandable expression of a computing task." I chose the implementation I did precisely because it simplifies mental reasoning about its behavior. When I get the answer, deliver it NOW, without trying to navigate a circuitous route to the end of the subprogram, only to deliver it THEN. Two more lines I'd like to quote from Gries: "I would add to this that one should always strive for simplicity and elegance. The simplest solution is always the easiest to understand." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney @ 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Robert Martin 1998-09-08 0:00 ` Tim McDermott 1998-09-05 0:00 ` Robert Martin 1998-09-09 0:00 ` Tim Ottinger 2 siblings, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-05 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> writes: > What some advocates of the se/se policy seem to be forgetting is that > the whole point is being able to mentally reason about behavior. By > reading the program text, can you figure out what this program does? > > I provided a couple of simple examples, one of them an idiom for using a > special input value to terminate a loop: > > loop > Get (N); > exit when N = 0; > <process N> > end loop; > > Is there anyone who doesn't understand what this code fragment does? > > Structured programming means keeping the code simple, where "simple" > means "being able to easily tell what it does." It means being able to > prove that it's correct. See item 7. > > In spite of the fact that this loop exits from the middle, I would argue > that it does indeed fit the defination of a "structured" program. I've been flipping through Structured Programming, by Linger, Mills, and Witt (Addison-Wesley, 1979), which I read a couple of years ago. In Chap 3 they list a few control structures, among them: (start of quote) The dowhiledo structure has general form do1 dopart1 while whiletest do2 dopart2 od The dowhiledo below prints individual characters from a string, up to a blank character: do1 get next character from string while character not blank do2 print character od (end of quote) Except for the sense of the whiletest, this is the similar to the Ada fragment I presented earlier. For example: loop Get (From => S, Char => C); exit when C = ' '; Put (C); end loop; So we see that the middle exit loop construct really does fit the definition of "structured." Harlan Mills was a mathematician who believed in writing provably correct programs, and his book Structured Programming shows how to do that for, among other loops, the dowhiledo form. The dowhildo form is discussed again on p116-7, in the section on prime programs. His definition (p118) of structured programming is: (start of quote) Definition: A structured program is a compound program constructed from a fixed basis set of prime programs. (end of quote) In other words, his basis set forms a set of axioms, from which program behavior can be derived. He includes the dowhiledo form in his set of axioms. Conclusion: Feel free to exit from the middle of a loop. This form of loop stands as a peer to other forms, among them the whiledo and dountil constructs. If anyone argues that "oh, but it's not structured," then hand them a copy of Mills' book. Software Productivity (Dorset House, 1988) is a collection of Mills' papers. Highly recommended! ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney @ 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 1998-09-08 0:00 ` Tim McDermott 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-05 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >I've been flipping through Structured Programming, by Linger, Mills, and >Witt (Addison-Wesley, 1979), which I read a couple of years ago. In >Chap 3 they list a few control structures, among them: > >The dowhiledo structure >So we see that the middle exit loop construct really does fit the >definition of "structured." According to Harlan Mills. But not according to Dijkstra. >Conclusion: Feel free to exit from the middle of a loop. No, you should not feel free to do anything. You should weigh the costs of everything you do. You should not feel free to use top-exit loops, you should not feel free to use 'exceptions', you should not feel free to use 'templates', etc, etc. Everything has a cost/benefit value that needs to be assessed. Once making that assessment, you *decide* to use certain structures. And if you *decide* to use mid-exit loops, so be it. But the decision should *never* be: "I used it because it is part of structured programming", or "I used it because its part of object oriented programming", or "I used it because it is a well known design pattern". > This form of >loop stands as a peer to other forms, among them the whiledo and dountil >constructs. If anyone argues that "oh, but it's not structured," then >hand them a copy of Mills' book. I haven't read this book, so I can't say if it is good or bad. Probably it is very good. However, I don't recognize Mill's authority to add to the definition of SP. Dijkstra coined the term, he has the right to say what gets added to it, and what gets taken away from it. I would admit to dowhiledo being part of SP if dowhiledo fell into the common usage of SP. Unfortunately, you posted some 14 or more definitions that were part of the common usage of SP. Those 14 definition, in one way or another, encompassed *all* of programming; making common usage meaningless. That makes me want to go back to the originator and stick to his definition. BTW, if every you use a programming structure that you have thought through and decided to used based upon your judgement of the situation, and then someone else wrinkles up their nose and says "but its not structured programming", you have the perfect right to say: "So what?". *You* are the engineer, *You* are responsible, *You* make the decision. But you'd better understand the cost/benefit trade-off. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-06 0:00 UTC (permalink / raw) > I haven't read this book, so I can't say if it is good or bad. Probably it > is very good. However, I don't recognize Mill's authority to add to the > definition of SP. Dijkstra coined the term, he has the right to say what > gets added to it, and what gets taken away from it. That's getting a bit extreme, isn't it, Robert? Academics are forever renegotiating the boundaries in any area of discourse. I know, in my area, Systemic-Functional Linguistics, there is an awful lot of discussions as to the details, goals, methods and boundaries. To alienate every academic working within the tradition other than the founder (Halliday) would seem to me to be nonsense. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Loryn Jenkins @ 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-05 0:00 UTC (permalink / raw) Loryn Jenkins wrote in message <35F1BB50.C57557E1@s054.aone.net.au>... >> I haven't read this book, so I can't say if it is good or bad. Probably it >> is very good. However, I don't recognize Mill's authority to add to the >> definition of SP. Dijkstra coined the term, he has the right to say what >> gets added to it, and what gets taken away from it. > >That's getting a bit extreme, isn't it, Robert? > >Academics are forever renegotiating the boundaries in any area of >discourse. I know, in my area, Systemic-Functional Linguistics, there is >an awful lot of discussions as to the details, goals, methods and >boundaries. > >To alienate every academic working within the tradition other than the >founder (Halliday) would seem to me to be nonsense. Granted. On the other hand, lets say that I wrote a book in which I said that the C assert statement was another perfectly acceptable way of implementing Design by Contract. And then lets say that some other guy read my book and quoted it in a newsgroup like this. Would Design by Contract suddenly now incorporate my use of the C assert statement? I think not. I think Meyer, and the folks who have studied his work would stake a stance against such an inclusion. I didn't mean to alienate Harlan Mills work; I expect that it is quite good. But I am also not willing to accept Mathew Heaney's demand that mid exit loops are part of the structured paradigm just because he quoted Mill's book. I'll want more substantiation than that. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Loryn Jenkins 1998-09-06 0:00 ` Charles Hixson 1998-09-07 0:00 ` Ray Gardner 0 siblings, 2 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-06 0:00 UTC (permalink / raw) Robert Martin wrote: > > Loryn Jenkins wrote in message <35F1BB50.C57557E1@s054.aone.net.au>... > >> I haven't read this book, so I can't say if it is good or bad. Probably > it > >> is very good. However, I don't recognize Mill's authority to add to the > >> definition of SP. Dijkstra coined the term, he has the right to say what > >> gets added to it, and what gets taken away from it. > > > >That's getting a bit extreme, isn't it, Robert? > > > >Academics are forever renegotiating the boundaries in any area of > >discourse. I know, in my area, Systemic-Functional Linguistics, there is > >an awful lot of discussions as to the details, goals, methods and > >boundaries. > > > >To alienate every academic working within the tradition other than the > >founder (Halliday) would seem to me to be nonsense. > > Granted. On the other hand, lets say that I wrote a book in which I said > that the C assert statement was another perfectly acceptable way of > implementing Design by Contract. Yes, but DBC can be implemented with comments. Remember, it's a methodological principle, not a language feature, per se. (It's just *sooo* nice to have compiler support.) I do take your point, though. > And then lets say that some other guy read > my book and quoted it in a newsgroup like this. Would Design by Contract > suddenly now incorporate my use of the C assert statement? I think not. I > think Meyer, and the folks who have studied his work would stake a stance > against such an inclusion. > > I didn't mean to alienate Harlan Mills work; I expect that it is quite good. > But I am also not willing to accept Mathew Heaney's demand that mid exit > loops are part of the structured paradigm just because he quoted Mill's > book. I'll want more substantiation than that. That's true. The academic tradition then, causes one to ask, "Was Dijkstra aware of Mills' work? Was he aware of it? Did he agree / disagree with it? Did Dijkstra treat Mills as 'on the playing field', or 'out of the ball park'? Did their writings target or influence the same sets of practitioners?" All these seem to be social questions. Questions of discourse. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Loryn Jenkins @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Patrick Doyle 1998-09-07 0:00 ` Ray Gardner 1 sibling, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) I find myself not understanding the basis of this discussion. To me it seems reasonable to ask, "Do reasonable experts in the field consider that loops that exit in the middle are a part of structured programming". The answer, obviously, is: This is not a matter of total agreement. There have been agruments that say: If you have to repeat blocks of code, then you are violating the principles of structured programming. There have been statements made that: "Loops should be single entry/single exit" (so that program correctness can be proved?). These are both valid points. But if the same code can be topologically transformed from one form to another without altering it's deep flow of control (e.g., pull all of the code within isolatable blocks into a function call, and then call it, and accept a returned value. Then we can say while (the) ... if (the) gostack := distimms (the, doshes,"."); loop testing a flag each time throught the loop. When is it true? That's hard to say without examining the code in detail (which I haven't invented). Is this really any different from: while (the) ... exit when (\the); gostack := distimms (the, doshes,"."); loop But this identity is only obvious because the huge chunk of code has been factored out into the distimms routine. In fact when we look at this, we can see that it is also equivalent to: if (the) { beginloop ... exit when (\the); gostack := distimms (the, doshes,"."); endloop } If these are all equivalent, does it really make sense to say that one of them is structured and another isn't. Consider a further pair of transforms: if (the) { when (firstPartOfTheLoop (the) ) { if (the) gostack := distimms (the, doshes, "."); } } and if (the) { when (the) { flag := firstPartOfTheLoop (the); if (the) gostack := distimms (the, doshes, "."); } flag := firstPartOfTheLoop (the); } Now, I obviously haven't checked these with a compiler, but baring typos I think that is is obvious that these pieces of code are all isomorphic, so it seems TO ME unreasonable to claim that some of them are structured and others of them aren't. I would like to hear about why others would find it reasonable. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-06 0:00 UTC (permalink / raw) In article <35F246E3.4424EF94@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: > >Now, I obviously haven't checked these with a compiler, but baring typos >I think that is is obvious that these pieces of code are all isomorphic, >so it seems TO ME unreasonable to claim that some of them are structured >and others of them aren't. > >I would like to hear about why others would find it reasonable. Dijkstra's structures are Turing equivalent, given a basic block at least as powerful as assignment. Thus, saying that a program is structured because a structured program can be transformed into it makes every conceivable program structured. So, unless we want to dilute the term to meaninglessness, I think we ought to disallow such transformations. Remember, structured programming is about the relationship between the text of a program and its dynamic behaviour. Thus, one can't neglect the text as you have done, and claim that transformations lead to equivalent programs, any more than you could alter the dynamic behaviour and consider it equivalent. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Loryn Jenkins 1998-09-06 0:00 ` Charles Hixson @ 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Patrick Logan 1 sibling, 1 reply; 510+ messages in thread From: Ray Gardner @ 1998-09-07 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> wrote: > Robert Martin wrote: > > > > I didn't mean to alienate Harlan Mills work; I expect that it is quite good. > > But I am also not willing to accept Mathew Heaney's demand that mid exit > > loops are part of the structured paradigm just because he quoted Mill's > > book. I'll want more substantiation than that. > > That's true. The academic tradition then, causes one to ask, "Was > Dijkstra aware of Mills' work? Was he aware of it? Did he agree / > disagree with it? Did Dijkstra treat Mills as 'on the playing field', or > 'out of the ball park'? Did their writings target or influence the same > sets of practitioners?" > > All these seem to be social questions. Questions of discourse. Here's a clue, maybe. Don't read too much into it. From "EWD494: Trip Report E.W. Dijkstra 16th April/7th May, 1975, U.S.A. and Canada", reprinted in _Selected Writings on Computing: A Personal Perspective_, E.W. Dijkstra, Springer-Verlag, 1982 (a _really_ neat sample of Dijkstra's EWD papers, which I think were mostly circulated only to colleagues by a sort of samizdat): [Dijkstra stays with A. Wasserman, lectures at Berkeley, speaks at ACM Pacific 75, lectures at Stanford, stays at Knuth's house. Parties back at Wasserman's, meeting Karp, Floyd, and Backus. Goes to LA for the International Conference on Software Reliability. Acerbic remarks. Goes to ISI (?) to meet with Manna, Ershov, Burstall, Randell, Turski, Wulf, and others, sees an unconvincing demonstration of automatic program-proving. Goes to Phoenix for an ACM Chapter meeting [damn, why didn't we ever get him to Denver when we had a viable chapter?], goes to Mission Viejo to visit the Burroughs Large Systems Plant. Flies to Montreal to attend an IBM conference on Software Engineering Education.] "... in my innocence I had expected an audience of computer scientists. My driver, however, was a manager, who opened the conversation with something like 'so you are the world expert on structured programming and chief programmer teams.'. Then I knew that I was out in the wilderness and politely refused to be associated with Harlan D. Mills." [More very acerbic remarks: "The ... conference was very instructive for me, although I learned a lot without which I would have been happier. At most fify percent of the partcipants were computing scientists; the rest were either IBM officials or managers of the [DP] departments of large IBM customers. I had full opportunity to observe all the intricate love/hate relations between the angles of the triangle 'university-manufacturer- customer'. It was all very frightening and I wish that I had a mastery of my pen like Arthur Koestler, for then I could have written a companion volume to his 'The Call Girls'." "The central victims in this drama are the [MBAs] and the firms dependent on their services ... They really have painted themselves into a corner with very sticky molasses! They have made a number of unforgiveable mistakes. One mistake is that they have based their full automation upon the IBM/360. When that machine was announced, it was immediately clear to many -- even inside IBM!-- that it would be practically impossible to write decent software for it... You cannot program a crooked machine to go straight ... The next mistake is that they decided to program in COBOL. ... OS/360 is no longer 'logical spaghetti', but 'logical barbed wire'. ... on the whole it was ghastly; unreal. I was severely shocked by the cultural level of the business participants. ..."] "Later I heard Harlan Mills give a summing up of some of the things I had said --together with some Harlanesk additions-- for that business audience. It was terrible, a misuse of language to which to the best of my powers I could not give a meaning. So, every third phrase I interrupted Harlan 'please could you explain or restate what you tried to say', but it was hopeless. Tom Hull helped me and I was very grateful to him. Later, when it was all over, our eyes met, and Tom gasped 'Jezus!'. It was the first time that I had heard him use strong language. How to sell empty but impressive slogans under the cloak of academic respectibility... ." "Turski's comments were short: 'They don't want computer scientists, nor software engineers, they want brainwashed mental cripples.'. It is too true... ." "On the last morning, Harlan Mills gave the summing up talk. It was again very much of the same, but, remarkably enough, I learned something from him, viz. the expression 'entry level jobs'. His argument was that the university should not train experts --as an aside: training and education were constantly confused-- because the jobs those experts should get were not 'entry level jobs'. This may be a profound difference between the academic community and (at least some of) the business community: there is not the slightest objection to giving the most responible university function, viz. a full professorship, to a youngster who has just got his Ph.D. It does not happen so very often, because really brilliant people are rare; but nothing in the university environment forbids it ... But to the business communities represented it was unthinkable to give a youngster any real responsibility... ." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ray Gardner @ 1998-09-07 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-07 0:00 UTC (permalink / raw) In comp.object Ray Gardner <rgardner@nyx.net> wrote: : "EWD494: Trip Report E.W. Dijkstra 16th April/7th May, 1975, : U.S.A. and Canada", reprinted in _Selected Writings on Computing: : A Personal Perspective_, E.W. Dijkstra, Springer-Verlag, 1982 (a : _really_ neat sample of Dijkstra's EWD papers, which I think were : mostly circulated only to colleagues by a sort of samizdat): I love this book. I've had it for almost 15 years. I pick it up several tiems a year and read his trip reports, etc. What a personality! Dijkstra gave a talk at Data General in Boston in the mid 1980's. What a character! At that time, he claimed to not be using a computer or to want one. We gave him one of the first PC compatible lap tops ever made. He looked at it, and said he'd consider using it. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Robert Martin @ 1998-09-08 0:00 ` Tim McDermott 1998-09-08 0:00 ` Patrick Doyle 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 2 replies; 510+ messages in thread From: Tim McDermott @ 1998-09-08 0:00 UTC (permalink / raw) Matthew Heaney wrote: > (start of quote) > The dowhiledo structure has general form > > do1 > dopart1 > while > whiletest > do2 > dopart2 > od snip > Conclusion: Feel free to exit from the middle of a loop. As defined, you can exit from the middle of a dowhiledo, but not from the top or bottom. This is still a se/se structure. You can't use this structure to justify multiple returns. Note too, that Chapter 3 deals with PDL. in Chapter 4, (titled "Structured Programming") Paragraph 4.2.2 states: "A _proper program_ [Mills italics - Tim] is a program with a control stucture that 1. has a single entry line and a single exit line, and 2. for each node, has a path through that node from the entry line to the exit line." Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Tim McDermott @ 1998-09-08 0:00 ` Patrick Doyle 1998-09-08 0:00 ` Patrick Logan 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-09-08 0:00 UTC (permalink / raw) In article <35F56A3B.8DEA51A7@draper.com>, Tim McDermott <mcdermott@draper.com> wrote: > >As defined, you can exit from the middle of a dowhiledo, but not from the top >or bottom. This is still a se/se structure. You can't use this structure to >justify multiple returns. I don't like multiple exits much myself, but something occurred to me... An if-then-else statement can have multiple returns: if a = 1 then ... elseif a = 2 then ... elseif a = 3 then ... end Each "elseif" is an exit from this block of code, as is the "end". How does this figure into the se/se picture? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Patrick Doyle @ 1998-09-08 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-08 0:00 UTC (permalink / raw) In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: : An if-then-else statement can have multiple returns: : if a = 1 then : ... : elseif a = 2 then : ... : elseif a = 3 then : ... : end : Each "elseif" is an exit from this block of code, as is the "end". : How does this figure into the se/se picture? This is the definitions of IF/ELSE. The rationale is that there are several blocks of code, but only *one* will execute. That one block itself has a single entry and exit. BTW the cutest thing about Smalltalk is that IF/ELSE is implemented using the single entry/exit form you are alluding to above. In Smalltalk, True is a class and False is a class. Both inherit from Boolean. True>>ifTrue: trueBlock ifFalse: falseBlock ^trueBlock value False>>ifTrue: trueBlock ifFalse: falseBlock ^falseBlock value So in this case IF/ELSE is implemented in a "pure" SE/SE fashion! 8^) -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Tim McDermott 1998-09-08 0:00 ` Patrick Doyle @ 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) Tim McDermott <mcdermott@draper.com> writes: > Matthew Heaney wrote: > > > (start of quote) > > The dowhiledo structure has general form > > > > do1 > > dopart1 > > while > > whiletest > > do2 > > dopart2 > > od > > snip > > > Conclusion: Feel free to exit from the middle of a loop. > > As defined, you can exit from the middle of a dowhiledo, but not from the top > or bottom. This is still a se/se structure. You can't use this structure to > justify multiple returns. But if dopart1 or dopart2 is just a "skip" statement, then it reduces to a top or bottom exit. For example, making the dopart2 part a "skip" is just our old friend dountil (except for the sense of the predicate). Remember: the goal is to satisfy the postcondition, and to be able to prove that you do. I can and do justify multiple returns, by proving that the postcondition is indeed satisfied. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Matthew Heaney @ 1998-09-05 0:00 ` Robert Martin 1998-09-09 0:00 ` Tim Ottinger 2 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-05 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... > >The best answer to the question "What is structured programming?" was >provided by David Gries, in Chap 6, On Structured Programming, of his >book Programming Methodology (Springer-Verlag, 1978). > >The chapter begins with the statement: > >"The term structured programming has been used with many different >meanings since Edsger W. Dijkstra first coined the term. Actually, the >term appeared in the title of his monograph Notes On Structured >Programming [that's the "little black book" - matt], but as far as I can >determine not in the monograph itself!" > >So Dijkstra never precisely defined the term "structured programming." If one looks at the little black book, one sees on its cover the words "Structured Programming" writtin in Gold. When one opens the book, one sees that the first section was written by Dijkstra and is entitled "Notes on Structured Programmin". In part 7 of this first section we find the flow charts which describe the four cannonical control flows; the term "single entry at the top and a single exit at the bottom", and a discussion of the benefits of constructing programs from these four single-entry/single-exit forms. In light of this it seems that Gries was incorrect when he asserted that Dijkstra never precisely defined "structured programming". It is probably true that the book nowhere says: "Structured Programming is..."; but I think that requiring such a statement is unecessary. The contents of the book *is* the definition of Structured Programming. > >Next sentence in Gries: > >"The lack of a precise definition has allowed, even encouraged, people >to use it as they wished, to attribute to sp ["sp" is how Gries >abbreviates "structured programming" - matt] what they themselves >learned from reading Notes On Structures Programming, however different >this might have been from Dijkstra's intent." I don't believe it was a lack of precision that caused this. I think it was a lack of study. There are plenty of folks, even now, who will simply assume that they know what a technique is without taking the time to study it. This has happened with structured programming, and it has happeded with object oriented programming. > >Now we're getting warm. Ed Yourdon other authors have stated that >structured programming means single entry/single exit modules, but did >Dijkstra say this specifically? The answer would appear to be no. I quite disagree. Dijkstra very clearly recommended that programs be constructed from his four single-entry/single-exit control structures in his "notes on structured programming". >(I myself have the little black book around, and I'm going to make it a >point to re-read it. Sadly, this classic text is long out of print, but >I was able to find one in a used bookstore.) I lost my first copy about ten years ago; but I was able to find another without too much trouble. They are around. > > >10. A major function of the structuring of the program is to keep a >correctness proof feasible [this one comes from Dijkstra, in Notes On >Structured Programming] >Take a close look at item 10, from Dijkstra himself. Dijkstra stated in >his original ACM letter is that there is a "conceptual gap between the >static program and the dynamic process." His complaint was that an >_unstructured_ program made it hard to reason about the program's >behavior. This is also a major theme running through his section of the book. >What some advocates of the se/se policy seem to be forgetting is that >the whole point is being able to mentally reason about behavior. By >reading the program text, can you figure out what this program does? Yes, this was the point. But the *mechanism* named "structured programming" was Dijkstra's way of addressing that point. There may be lots and lots of different ways to address the point, but the only one that can be called "structured programming" is the one that uses Dijkstra's four cannonical control flows. >I provided a couple of simple examples, one of them an idiom for using a >special input value to terminate a loop: > >loop > Get (N); > exit when N = 0; > <process N> >end loop; > >Is there anyone who doesn't understand what this code fragment does? > >Structured programming means keeping the code simple, where "simple" >means "being able to easily tell what it does." It means being able to >prove that it's correct. See item 7. That list was pretty funny. I especially like item 1. "A return to common sense". Or item 8 "controlling complexity through theory and discipline." Most of those definitions are either wrong or meaningless. Item 7. is no different. It certainly describes an attribute of structured programming "easy to read and understand" but does not tell you *how* you made the code easy to read and understand. By the definition in Item 7. If my code is easy to read and understand, it must be structured. I believe that statisticians call that a "type one error". i.e. given that A implies B, it is a type one error to assume that B implies A. If we accept as a given that structured programs are easy to read and understand, we cannot therefore assume that all programs that are easy to read and understand are structured programs. > >In spite of the fact that this loop exits from the middle, I would argue >that it does indeed fit the defination of a "structured" program. Whether it fits Dijkstra's definition is a matter of debate. It can be rewritten as: while (Get(N), N != 0) Process(N); Which certainly appears close to a top-exit loop. But this begs a question that I don't think Dijkstra really every answered. Must the condition in a loop be nothing but a pure condition? Or can it be a series of process steps that result in a testable condition? I prefer the latter. I think that, as long as we treat the code that prepares the looping condition (i.e. Get(N)) as atomic with the loop condition itself, then we really have a top-exit loop. Thus, after giving this some thought, I would agree with you that the code you wrote above fits the definition of "structured programming". On the other hand I disagree with your reasoning. It is not structured because it is easy to read. It is structured because it is a form of top-exit loop. Does this mean that all mid-exit loops are suddenly conformant to structured programming? I don't think so. I think that when the code leading up to the looping condition cannot be considered atomic, (i.e. it contains statements that do not impact the looping condition, or will change in ways that are independent of the looping condition) then the resultant code is not conformant to Dijkstra's rules. For example: for(;;) { Get(N); if (N == 0) break; Process(N); } The above is structured because the first two statements of the loop body are part of the loop condition. However: for (;;) { char* buf = malloc(80); int n = Get(buf,80); if (n == 0) { free(buf); break; } Process(buf, n); free(buf); } [Please, no complaints about the way the heap memory is being managed.. Presume that there is some good reason why its being managed that way.] This is not a structured program because the code preceeding the loop condition is not atomic. It is not directly part of the loop condition, and has side-effect that must be dealt with later. On the other hand: for (;;) { char* buf = malloc(80); int n = Get(buf, 80); if (n != 0) { Process(buf, n); } free(buf); if (n == 0) break; } This is a structured program because it conforms to a bottom-exit looping structure. > >We've been debating whether a program that terminates a loop from the >middle, or does an early return, is really a "structured" program, but I >think this misses the point. It may miss some point somewhere, but it does not miss the point when the point is the definition of structured programming. There is another type one error we can make. If we assume that structured programming is "good", we cannot therefore assume that "good" implies structured programming. There may be many different kinds of good programs, some of them having mid loop exits. Such programs are not structured programs, but that doesn't mean that they are not good programs. > >We should instead be asking, Can I mentally reason about this program's >behavior? Am I able to write a correctness proof for this program? Am >I confident that this program works? > >That's the real meaning of "structured." I'll agree that that was Dijkstra's motivation. But if we go no further than the above statement then *every* program is structured, at least in the author's eyes. *Every* program can be reasoned about. Every program can be proven correct (given enough time), every program can be worked into a shape that inspires confidence in its correctness. Dijkstra's contribution was more than the above simple statement. Dijkstra's contribution was a *technique* for helping to create programs that are easy to reason about, easier to prove correct, easier to be confident in. >Two more lines I'd like to quote from Gries: > >"I would add to this that one should always strive for simplicity and >elegance. The simplest solution is always the easiest to understand." This is often true but, unfortunately, simplicity is often subjective. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Robert Martin @ 1998-09-09 0:00 ` Tim Ottinger 1998-09-17 0:00 ` Matthew Heaney 2 siblings, 1 reply; 510+ messages in thread From: Tim Ottinger @ 1998-09-09 0:00 UTC (permalink / raw) Matthew Heaney wrote a very fine, well-researched note here. I think it was great, except that he took "reason about..." to mean "understand...". To understand a code fragment is not the same as to reason about it. Understanding is necessary, but insufficient. From practice, we know that 'easy to understand' is desirable, but not enough. What about robustness, reentrancy, absence of race conditions, atomicity, ease of change, efficiency, etc? There is a lot more to consider than just simplicity, though we always strive to keep as much simplicity as we can stand. But this is not the point of "reasoning about" structure, either. It's about understanding the full character of the code that's written, so I'll return to the idea of 'reasoning about' structure... It's not enough to merely understand an instance of a structure of code. The goal was to do much more than this, and establish a formal or semi-formal practice... an 'engineering discipline'. When Dijkstra mentions reasoning about structures, he is talking about proofs and the like... the ability to characterize (perhaps mathematically) the structure of the code, to measure it, to draw correlations between it and other things, to prove it correct or incorrect, to apply transformations (read: optimizations) to the structure. There are patterns of structure, and there can be patterns of structure intentionally applied. I wonder if the /Nature Of Order/ won't even have us starting to drive towards some kind of formalism in code structure. I won't say that I go as far as many in the path of formalized structure, but I am increasingly appreciating the goal and the value of a more formalized way to reach it. That said, I have to plan to go restructure a little code, and catch up on reading /Structured Programming/ (Dahl, Dijkstra, Hoare, academic press "computer science classics" series, ISBN 0-12-200550-3). Bye now. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Tim Ottinger @ 1998-09-17 0:00 ` Matthew Heaney 1998-09-16 0:00 ` Tim Ottinger 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) Tim Ottinger <ottinger@oma.com> writes: > Matthew Heaney wrote a very fine, well-researched note > here. I think it was great, except that he took "reason > about..." to mean "understand...". To understand a code > fragment is not the same as to reason about it. I treat them as essentially the same. I can reason about a code fragment implemented in a real programming language, or I can reason about a code fragment using Dijkstra's abstract programming language. I can make mistakes in reasoning using either language. So formalism is great, but is not a panacea. It's just another tool that should be in every programmer's toolbox. It may be time to cite another couple of papers on this very topic: Program Verification: The Very Idea James H. Fetzer CACM, Sep 1988, Vol 31, No 9, p1048-1063 Social Processes and Proofs of Theorems and Programs Richard A. De Millo Richard J. Lipton Alan J. Perlis CACM, May 1979, Vol 22, No 5, p271-280 > That said, I have to plan to go restructure a little > code, and catch up on reading /Structured Programming/ > (Dahl, Dijkstra, Hoare, academic press "computer > science classics" series, ISBN 0-12-200550-3). I just got back from a business trip, and got about halfway through that other classic, A Discipline of Programming (Prentice-Hall, 1976). Great stuff, although I recommend that those unfamiliar with the predicate transformer technique start with David Gries' Science Of Programming. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` Matthew Heaney @ 1998-09-16 0:00 ` Tim Ottinger 0 siblings, 0 replies; 510+ messages in thread From: Tim Ottinger @ 1998-09-16 0:00 UTC (permalink / raw) Matthew Heaney wrote: > I just got back from a business trip, and got about halfway through that > other classic, A Discipline of Programming (Prentice-Hall, 1976). Great > stuff, although I recommend that those unfamiliar with the predicate > transformer technique start with David Gries' Science Of Programming. Maybe we should have a regular feature here called 'what are you reading this week'? Thanks for the recommendation. I may follow up on that one. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Ell 1998-09-05 0:00 ` Jeffrey C. Dege @ 1998-09-05 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) > Because as evidenced here, you will accept RCM's position without > facts simply because you have an ideological affinity, or other > non-valid reason to do so. Elliot. It may or may not surprise you. But there are many things that I agree with you on, and disagree with Robert. (eg I believe he tends to overstate the motivation for OO as dependency management. Whereas, for me, OO is more about conceptually modelling coherent sets of behaviours that can be assigned to a well-defined entity. Which, if I understand it right, is closer to your position than his.) But that has nothing to do with how I (and, I suspect, Patrick) deals with Robert. I believe you'll find we deal with courtesy. Just take a look at the discussion between myself and Matthew Heaney. We absolutely disagreed. But neither of us called names at each other. Loryn Jenkins PS: Who Patrick agrees or disagrees with has nothing to do with his proposed moderation duties. But when people simply name call, I hope he does return the post. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Loryn Jenkins @ 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-05 0:00 UTC (permalink / raw) Loryn Jenkins wrote in message <35F0B75E.F259FCE6@s054.aone.net.au>... >Elliot. It may or may not surprise you. But there are many things that I >agree with you on, and disagree with Robert. (eg I believe he tends to >overstate the motivation for OO as dependency management. Whereas, for >me, OO is more about conceptually modelling coherent sets of behaviours >that can be assigned to a well-defined entity. Which, if I understand it >right, is closer to your position than his.) There are two aspects to dependency management. One is to isolate those things which ought not depend upon each other. The other is to associate those things that ought to be associated. i.e. the old duo of cohesion and coupling. Your nicely worded phrase "conceptually modelling coherent sets of behaviors" is a good way of expressing the cohesion side of the equation; and I, of course, have no quarrel with it. Objects, after all, ought to consist of conceptually cohesive groupings of functions and data. Object models, on the other hand, should consist of an interelated set of such objects which have been decoupled as much as possible. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-06 0:00 UTC (permalink / raw) > There are two aspects to dependency management. One is to isolate those > things which ought not depend upon each other. The other is to associate > those things that ought to be associated. i.e. the old duo of cohesion and > coupling. Your nicely worded phrase "conceptually modelling coherent sets > of behaviors" is a good way of expressing the cohesion side of the equation; > and I, of course, have no quarrel with it. Objects, after all, ought to > consist of conceptually cohesive groupings of functions and data. Object > models, on the other hand, should consist of an interelated set of such > objects which have been decoupled as much as possible. Well ... decoupled appropriately. Perhaps this is simply a difference in emphasis. Obviously, you run into trouble when you have bidirectional dependencies everywhere. Obviously, you run into trouble if you have cyclic dependencies between clusters. This is an extremely important aspect of architecture. It just doesn't seem to me to be one of the fundamental, driving forces of OO. (OO does enable it nicely, though.) Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Loryn Jenkins @ 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-05 0:00 UTC (permalink / raw) Loryn Jenkins wrote in message <35F1B862.C1FFA000@s054.aone.net.au>... >> There are two aspects to dependency management. One is to isolate those >> things which ought not depend upon each other. The other is to associate >> those things that ought to be associated. i.e. the old duo of cohesion and >> coupling. Your nicely worded phrase "conceptually modelling coherent sets >> of behaviors" is a good way of expressing the cohesion side of the equation; >> and I, of course, have no quarrel with it. Objects, after all, ought to >> consist of conceptually cohesive groupings of functions and data. Object >> models, on the other hand, should consist of an interelated set of such >> objects which have been decoupled as much as possible. > >Well ... decoupled appropriately. Of course! >Perhaps this is simply a difference in emphasis. Obviously, you run into >trouble when you have bidirectional dependencies everywhere. Obviously, >you run into trouble if you have cyclic dependencies between clusters. Absolutely. You also run into trouble when you have high level concepts depending upon implementation details. >This is an extremely important aspect of architecture. It is probably the most important aspect of software archictecture. >It just doesn't seem to me to be one of the fundamental, driving forces >of OO. (OO does enable it nicely, though.) Agreed, it is one of the fundemental driving forces of software engineering; and there have been many different approaches to addressing that force. OO is just one such approach. It is also one of the most successful approaches. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-06 0:00 UTC (permalink / raw) > Agreed, it is one of the fundemental driving forces of software engineering; That, I'll pay. > and there have been many different approaches to addressing that force. OO > is just one such approach. It is also one of the most successful > approaches. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Doyle @ 1998-09-04 0:00 ` Robert Martin 1998-09-05 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-04 0:00 UTC (permalink / raw) Ell wrote in message <35ef7dff.24318728@news.erols.com>... >"Robert Martin" <rmartin@oma.com> wrote: > >> >>Ell wrote in message <35f23ce2.7649859@news.erols.com>... >> >>> >>>Think "avoid unstructured control flow", and not "avoid [creating code >>>which has multiple exits]". > >>You had best define 'unstructured' in this context. Dijkstra's definition >>of 'unstructured control flow' is control flow that does not conform >>precisely to the four standard sequencing elements {sequence, selection, top >>exit loop, bottom exit loop}, all of which have a single entry and a single >>exit. > >Where is this documented? Where has Dijkstra stated that flow control >must conform precisely to the 4 specific elements you mention? Elliott, I've already answered this question several times. I can only assume that you reason you keep asking this is that you don't want to look it up for yourself on the off chance that you might find it to be true. Let me assure you, if you read the citings I have given you so many times you *will* find that Dijkstra recommended four, and only four, control elements. >Please refer to relevant citations to back up this assertion. I have >seen nothing that Dijkstra refers to explicitly about se/se on other >than what you quoted about flowcharts. And this everyone knows is how >to create flowcharts on a page - one entry point, one exit. Then clearly you have not read much of Dijkstra. The citation you want is the citation I have given you many many times. Go look it up Elliott. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan > >Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Robert Martin @ 1998-09-05 0:00 ` Loryn Jenkins 1998-09-04 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) > Then clearly you have not read much of Dijkstra. The citation you want is > the citation I have given you many many times. Go look it up Elliott. Yes, look it up. Read it. Acknowledge that that is what Dijkstra was saying. Remember, you *may* disagree with him. But it is silly not reading what he actually said. And it is fantasy arguing that he wasn't discussing se/se. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Loryn Jenkins @ 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) Loryn Jenkins <loryn@s054.aone.net.au> wrote: >> Then clearly you have not read much of Dijkstra. The citation you want is >> the citation I have given you many many times. Go look it up Elliott. >Yes, look it up. Read it. Acknowledge that that is what Dijkstra was >saying. How can I acknowledge that, if I haven't seen it? And you all can't point to that stuff on flowcharting as some kind of proof that the founders of SP said we should adhere to se/se. >Remember, you *may* disagree with him. But it is silly not reading what >he actually said. That book is out of print and RCM knows it. If RCM had *any* shred of text to prove that they explicitly advocated se/se in structured coding he would quote it. > And it is fantasy arguing that he wasn't discussing >se/se. It's a deplorable attempt at deception for RCM to state that se/se is a cornerstone of SP without a shred of evidence. It's fantastic gullibility to think RCM is right about se/se without a shred of evidence; to believe him based on faith, because I'll bet dollars to doughnuts that you can't show me any proof either. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell @ 1998-09-05 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) Ell wrote: > > Loryn Jenkins <loryn@s054.aone.net.au> wrote: > > >> Then clearly you have not read much of Dijkstra. The citation you want is > >> the citation I have given you many many times. Go look it up Elliott. > > >Yes, look it up. Read it. Acknowledge that that is what Dijkstra was > >saying. > > How can I acknowledge that, if I haven't seen it? And you all can't > point to that stuff on flowcharting as some kind of proof that the > founders of SP said we should adhere to se/se. > > >Remember, you *may* disagree with him. But it is silly not reading what > >he actually said. > > That book is out of print and RCM knows it. That's what libraries are for. > If RCM had *any* shred of > text to prove that they explicitly advocated se/se in structured > coding he would quote it. A charitable interpretation of what they have already quoted has demonstrated that. But leave that aside. Let us say that many people who have read the book have made that interpretation. It is certainly possible for you to claim that no, se/se is not what Dijkstra was going on about, he was really using se/se as a tool to demonstrate that, say, code should be provable. And it is the provability of code that is the foundation of structured programming. This may or may not be correct. But it is an acceptable line of argument. But an even better line of argument may in fact be, yes, Dijkstra does believe in se/se. But what he should have been concentrating on was, say, provability. > > > And it is fantasy arguing that he wasn't discussing > >se/se. > > It's a deplorable attempt at deception for RCM to state that se/se is > a cornerstone of SP without a shred of evidence. How about, 'a cornerstone of SP as advocated by Dijkstra'. (That doesn't necessarily mean he was right; that doesn't necessarily mean that it is today, in fact, the basis for SP (as practised by the majority of practitioners.) It merely means that he advocated it. (And, I think, it would be incorrect to debate that his view has influenced many people. That is, it is an historical fact that his views have influenced many people (other than RCM ... take BM as an example) about the use of se/se. > > It's fantastic gullibility to think RCM is right about se/se without a > shred of evidence; What evidence? A quotation? Hah. That's not proof that se/se is right. That's only proof that it is an historical fact Dijkstra argued for se/se. Whether se/se is right is another matter entirely. > to believe him based on faith, because I'll bet > dollars to doughnuts that you can't show me any proof either. Like you, I don't have the book at hand. But RCM's claims of Dijkstra's position seems 'right' to me (based on triangulating what I've read of many other people who've read Dijkstra). Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Ell @ 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1 sibling, 2 replies; 510+ messages in thread From: sureshvv @ 1998-09-03 0:00 UTC (permalink / raw) In article <6skqf3$9g0$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > Knowledge of the benefits and costs of > single-entry/single-exit functions should be firmly ingrained in all > software engineers. I would like to find out the costs that are associated with the se/se structure of functions. 1. Increases level of nesting in code, making it potentially more complex. 2. Requires adding flag variables which have to be tracked, making it more complex. 3. Special conditions can become embedded in code rather than being readily apparent. suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` sureshvv @ 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille 1998-09-06 0:00 ` Charles Hixson 1998-09-03 0:00 ` Patrick Logan 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) sureshvv@hotmail.com wrote in message <6smmhv$1kp$1@nnrp1.dejanews.com>... >In article <6skqf3$9g0$1@hirame.wwa.com>, > "Robert Martin" <rmartin@oma.com> wrote: > >> Knowledge of the benefits and costs of >> single-entry/single-exit functions should be firmly ingrained in all >> software engineers. > >I would like to find out the costs that are associated with the se/se >structure of functions. > >1. Increases level of nesting in code, making it potentially more complex. >2. Requires adding flag variables which have to be tracked, making it >more complex. >3. Special conditions can become embedded in code rather than being readily >apparent. 1 and 2 are certainly costs; although perhaps overstated. I don't understand 3. As for 1, nesting level becomes explicit, whereas early returns hide the true nesting level. Consider: void f() { if (condition.1) return; if (condition.2) return; do something useful return; } This is equivalent to: void f() { if (condition.1) return; else if (condition.2) return; else do something useful; return; }; Which, in reality, is: void f() { if (condition.1) return; else{ if (condition.2) return; else { do something useful; } } }; So, early returns do not actually reduce nesting; they just appear to. The problem is that subsequent changes to the function may force you to separate the flows that multiple exits have combined. So, the benefit of multiple returns is not a reduction in nesting, but just an *apparent* reduction in nesting. The cost, on the other hand, is that the nesting will have to be unhidden later. Point 2 is certainly a cost. The creation of mutable state is always annoying. On the other hand, the loss of control flow state is also annoying. Both have their own benefits and costs. The cost of capturing state in se/se is paid once when you write the module, and once for every person who must understand it. The cost of rederiving state lost by merging control flows is paid every time the function changes in such a way that the state must be rederived. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Mike Spille 1998-09-03 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson 1 sibling, 1 reply; 510+ messages in thread From: Mike Spille @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote: > > sureshvv@hotmail.com wrote in message <6smmhv$1kp$1@nnrp1.dejanews.com>... > >In article <6skqf3$9g0$1@hirame.wwa.com>, > > "Robert Martin" <rmartin@oma.com> wrote: > > > >> Knowledge of the benefits and costs of > >> single-entry/single-exit functions should be firmly ingrained in all > >> software engineers. > > > >I would like to find out the costs that are associated with the se/se > >structure of functions. > > > >1. Increases level of nesting in code, making it potentially more complex. > >2. Requires adding flag variables which have to be tracked, making it > >more complex. > >3. Special conditions can become embedded in code rather than being readily > >apparent. > > 1 and 2 are certainly costs; although perhaps overstated. I don't > understand 3. > > As for 1, nesting level becomes explicit, whereas early returns hide the > true nesting level. Consider: > "True nesting level"? Sounds metaphysical. In a C-like language I define nesting level as "how many open braces have I got"? (oh, this works for me 'cause I always brace-ify if/do/while/for/etc statements, even for one liners). > void f() > { > if (condition.1) return; > if (condition.2) return; > do something useful > return; > } > > This is equivalent to: > > void f() > { > if (condition.1) return; > else if (condition.2) return; > else do something useful; > return; > }; > > Which, in reality, is: > > void f() > { > if (condition.1) return; > else{ > if (condition.2) return; > else { > do something useful; > } > } > }; > > So, early returns do not actually reduce nesting; they just appear to. The > problem is that subsequent changes to the function may force you to separate > the flows that multiple exits have combined. > Nesting is as nesting does. Your first example does not have any "hidden" nesting; it avoids nesting by using multiple-returns. Period. You may introduce nesting later on but that doesn't mean the nesting was hidden in the function, struggling to get out :-) I've seen the style you've shown above in example 3 in code before. It invariably was written by someone who religiously followed the 1 entrance/ 1 exit philosophy. The reality of reading such code was that the meat of function, the code that actually did "work" within the function, was buried under a pile of ifs, and forced the reader seperate the wheat from the chaff in a painful manner. In the first example above, it's immediately obvious where the "meat" is. To put it another way, example 1 puts emphasis on the "do something useful" section. Example 3 hides "do something useful", and emphasizes the condition checking instead. [snip] > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Mike Spille @ 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille ` (3 more replies) 0 siblings, 4 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Mike Spille wrote in message <35EEBA15.30C3CC76@tisny.com>... >Robert Martin wrote: > >> void f() >> { >> if (condition.1) return; >> if (condition.2) return; >> do something useful >> return; >> } >> >> This is equivalent to: >> >> void f() >> { >> if (condition.1) return; >> else if (condition.2) return; >> else do something useful; >> return; >> }; >> >> Which, in reality, is: >> >> void f() >> { >> if (condition.1) return; >> else{ >> if (condition.2) return; >> else { >> do something useful; >> } >> } >> }; >> > >Nesting is as nesting does. Your first example does not have any "hidden" >nesting; it avoids nesting by using multiple-returns. Period. You may >introduce nesting later on but that doesn't mean the nesting was hidden >in the function, struggling to get out :-) Draw the flowcharts of the three snippets above. You will find that they are identical. Now ask yourself whether or not nesting is a semantic quality, or just a comment. If nesting is a semantic quality, then how can three identical flowcharts have different nesting? On the other hand, if nesting has no semantic content, then why do we do it? Indentation is one of the ways we represent nesting. The three functions shown above use different indentation schemes. Nesting, on the other hand, occurs when control flow splits. The branches below the split are nested. >I've seen the style you've shown above in example 3 in code before. It >invariably was written by someone who religiously followed the 1 entrance/ >1 exit philosophy. All of the snippets above violate se/se; so anybody who religiously followed se/se would not use any of them. Also, I would advise that religiously following se/se, or any other paradigm, is foolish. >The reality of reading such code was that the meat of >function, the code that actually did "work" within the function, was buried under >a pile of ifs, and forced the reader seperate the wheat from the chaff in >a painful manner. In the first example above, it's immediately obvious >where the "meat" is. It seems to me that in all of the styles above, the work is buried under a pile of ifs. And the flowchart of the three shows this to be true as well. I think you are really saying that the second and third show the work to be indented to the right of a pile of ifs. Now, in a real se/se function that checks a few things before doing the real work, the real work will be the most indented part of the function. People who train themselves to know that the real work is the stuff that is most indented, have little trouble finding it. > >To put it another way, example 1 puts emphasis on the "do something useful" >section. Example 3 hides "do something useful", and emphasizes the >condition checking instead. It's odd, but that's exactly the statement I'd make about se/se. It seems to me that: if (A is right) if (B is right) if (C is right) then do the work. emphasizes the work more than: if (A is wrong) then return; if (B is wrong) then return; if (C is wrong) then return; do the work; So, I think the notion of "emphasis" is somewhat subjective. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Mike Spille 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Ray Blaak ` (2 subsequent siblings) 3 siblings, 2 replies; 510+ messages in thread From: Mike Spille @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote: > > Mike Spille wrote in message <35EEBA15.30C3CC76@tisny.com>... > >Robert Martin wrote: > > > > >> void f() > >> { > >> if (condition.1) return; > >> if (condition.2) return; > >> do something useful > >> return; > >> } > >> > >> This is equivalent to: > >> > >> void f() > >> { > >> if (condition.1) return; > >> else if (condition.2) return; > >> else do something useful; > >> return; > >> }; > >> > >> Which, in reality, is: > >> > >> void f() > >> { > >> if (condition.1) return; > >> else{ > >> if (condition.2) return; > >> else { > >> do something useful; > >> } > >> } > >> }; > >> > > > >Nesting is as nesting does. Your first example does not have any "hidden" > >nesting; it avoids nesting by using multiple-returns. Period. You may > >introduce nesting later on but that doesn't mean the nesting was hidden > >in the function, struggling to get out :-) > > Draw the flowcharts of the three snippets above. You will find that they > are identical. Now ask yourself whether or not nesting is a semantic > quality, or just a comment. If nesting is a semantic quality, then how can > three identical flowcharts have different nesting? On the other hand, if > nesting has no semantic content, then why do we do it? > Well, I can make a semantically equivalent program out of gotos - so what? I thought the point was readability and maintainability. Your second and third examples add a bunch of extra tokens a reader of the code has to scan. Turning this into single/entry, single/exit will do the same or add even more tokens. This enhanes maintainablility? > Indentation is one of the ways we represent nesting. The three functions > shown above use different indentation schemes. Nesting, on the other hand, > occurs when control flow splits. The branches below the split are nested. > > >I've seen the style you've shown above in example 3 in code before. It > >invariably was written by someone who religiously followed the 1 entrance/ > >1 exit philosophy. > > All of the snippets above violate se/se; so anybody who religiously followed > se/se would not use any of them. > Whoops - my eyes failed me on that one. Mea culpa. > Also, I would advise that religiously following se/se, or any other > paradigm, is foolish. > > >The reality of reading such code was that the meat of > >function, the code that actually did "work" within the function, was buried > under > >a pile of ifs, and forced the reader seperate the wheat from the chaff in > >a painful manner. In the first example above, it's immediately obvious > >where the "meat" is. > > It seems to me that in all of the styles above, the work is buried under a > pile of ifs. And the flowchart of the three shows this to be true as well. > I think you are really saying that the second and third show the work to be > indented to the right of a pile of ifs. > What my brain sees in case one is a bunch of constraint-type checks that "abort" if they fail. Following that is un-nested, unindented code which can rely on the guarantees made at the top of the function. The third case isn't as clear cut in my eyes. The meat of the code is physically contained within the constraint checks. In addition, if this code takes up more than a page, I have to worry about an else possibly being hung on to the end. > Now, in a real se/se function that checks a few things before doing the real > work, the real work will be the most indented part of the function. People > who train themselves to know that the real work is the stuff that is most > indented, have little trouble finding it. > I avoid syntax-level nesting (e.g. open curlies and indenting for C-based stuff) when I can, because I find nesting negatively impacts readability. This is highly subjective of course. > > > >To put it another way, example 1 puts emphasis on the "do something useful" > >section. Example 3 hides "do something useful", and emphasizes the > >condition checking instead. > > It's odd, but that's exactly the statement I'd make about se/se. > > It seems to me that: > > if (A is right) > if (B is right) > if (C is right) > then do the work. > > emphasizes the work more than: > > if (A is wrong) then return; > if (B is wrong) then return; > if (C is wrong) then return; > do the work; > > So, I think the notion of "emphasis" is somewhat subjective. > Defintely so - I find having the most important code stuck in column X (where X can vary, depending on how many checks and the nesting level) very hard to follow over large programs. Having the important stuff at the zero indentation level seems much more natural. > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Mike Spille @ 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Mike Spille wrote in message <35EEF0D1.939F1907@tisny.com>... >Robert Martin wrote: >> >> Mike Spille wrote in message <35EEBA15.30C3CC76@tisny.com>... >> >Robert Martin wrote: >> >> > >> >> void f() >> >> { >> >> if (condition.1) return; >> >> if (condition.2) return; >> >> do something useful >> >> return; >> >> } >> >> >> >> This is equivalent to: >> >> >> >> void f() >> >> { >> >> if (condition.1) return; >> >> else if (condition.2) return; >> >> else do something useful; >> >> return; >> >> }; >> >> >> >> Which, in reality, is: >> >> >> >> void f() >> >> { >> >> if (condition.1) return; >> >> else{ >> >> if (condition.2) return; >> >> else { >> >> do something useful; >> >> } >> >> } >> >> }; >> >> >> > >> >Nesting is as nesting does. Your first example does not have any "hidden" >> >nesting; it avoids nesting by using multiple-returns. Period. You may >> >introduce nesting later on but that doesn't mean the nesting was hidden >> >in the function, struggling to get out :-) >> >> Draw the flowcharts of the three snippets above. You will find that they >> are identical. Now ask yourself whether or not nesting is a semantic >> quality, or just a comment. If nesting is a semantic quality, then how can >> three identical flowcharts have different nesting? On the other hand, if >> nesting has no semantic content, then why do we do it? >> >Well, I can make a semantically equivalent program out of gotos - so what? >I thought the point was readability and maintainability. It is. And I agree with you that, for most people at least, the first snippet is more readable than the other two simply because it has fewer tokens. >Your second and third examples add a bunch of extra tokens a reader of >the code has to scan. Correct, and I do not recommend them; the added tokens serve no extra purpose. I was just demonstrating that the first example was just as nested as the others (if not as indented). >Turning this into single/entry, single/exit will >do the same or add even more tokens. This enhanes maintainablility? It can. Yes, more tokens may be added. But in an se/se structure, each added token serves a purpose. It serves to expose a control flow that would otherwise be hidden, or to separate a control flow that would otherwise have been merged. Does this benefit offset the additional tokens? That depends up the kinds of changes that the function faces in the future. My own personal view is that the cost of the extra tokens is low, whereas the cost if separating control flows in the future is high, so I usually prefer to keep the control flows separate. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Mike Spille 1998-09-03 0:00 ` Robert Martin @ 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: sureshvv @ 1998-09-04 0:00 UTC (permalink / raw) In article <35EEF0D1.939F1907@tisny.com>, Mike Spille <mspille@tisny.com> wrote: > Robert Martin wrote: > > > > > > if (A is right) > > if (B is right) > > if (C is right) > > then do the work. > > > > emphasizes the work more than: > > > > if (A is wrong) then return; > > if (B is wrong) then return; > > if (C is wrong) then return; > > do the work; > > > > So, I think the notion of "emphasis" is somewhat subjective. > > > > Defintely so - I find having the most important code stuck in column X (where > X can vary, depending on how many checks and the nesting level) very hard > to follow over large programs. Having the important stuff at the zero > indentation level seems much more natural. As I indicated in another post add the following realistic requirements 1. A log message has to be output indicating the failed condition 2. A different value has to be returned for each of the conditions and you will see how much more cumbersome the se/se structure will become. I think, a function is best partitioned as a sequence of small number of independent paragraphs (scopes) - where each paragraph can be understood in a context independent manner. I contend that this is better for readability AND maintainability. The multiple-return structure accomplishes this better than the se/se structure. The se/se strcuture often creates a monolithic paragraph, creating a scope that extends across many lines. In fact, I feel that the multiple-return structure is more in line with the "structured" organization of programs. suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` sureshvv @ 1998-09-04 0:00 ` Robert Martin 1998-09-04 0:00 ` Mike Spille 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-04 0:00 UTC (permalink / raw) sureshvv@hotmail.com wrote in message <6sp902$buj$1@nnrp1.dejanews.com>... >In article <35EEF0D1.939F1907@tisny.com>, > Mike Spille <mspille@tisny.com> wrote: >> Robert Martin wrote: >> > > >> > >> > if (A is right) >> > if (B is right) >> > if (C is right) >> > then do the work. >> > >> > emphasizes the work more than: >> > >> > if (A is wrong) then return; >> > if (B is wrong) then return; >> > if (C is wrong) then return; >> > do the work; >> > >> > So, I think the notion of "emphasis" is somewhat subjective. >> > >> >> Defintely so - I find having the most important code stuck in column X (where >> X can vary, depending on how many checks and the nesting level) very hard >> to follow over large programs. Having the important stuff at the zero >> indentation level seems much more natural. > >As I indicated in another post add the following realistic requirements > >1. A log message has to be output indicating the failed condition >2. A different value has to be returned for each of the conditions > >and you will see how much more cumbersome the se/se structure will become. int f(char* name) // returns status value { int status = 0; if (File* f = fopen(name, "r")) { if (char* buffer = malloc(80)) { DoSomethingUseful(f,buffer); free(buffer); } else // malloc failure { Log("malloc failure"); status = -2; } fclose(f); } else // fopen failure { Log("Failure to fopen"); status = -1; } return status; } Perhaps you think this is cumbersome. I don't. Cumbersome is a rather subjective term. >I think, a function is best partitioned as a sequence of small number of >independent paragraphs (scopes) - where each paragraph can be understood in a >context independent manner. I contend that this is better for readability That's nearly a quote from Dijkstra! >AND maintainability. That equates maintainability with readability; a position that I don't believe to be valid. Granted something must be readable to be maintainable; however something that is readable is not necessarily maintainable. >The multiple-return structure accomplishes this better than the se/se structure. Does it? I think that's subjective. >The se/se strcuture often creates a monolithic paragraph, Quite to the contrary, the se/se structure is defined as a structure that is recursively decomponsible into four discrete se/se control elements. The recursive decomposition goes right down to the level of single lines of code. Thus, an se/se structure cannot be monolithic (literally "one rock"). >creating a scope that extends across many lines. Lots of things creates scopes that extend accross many lines. Functions, classes, try blocks. I'll grant you that scopes should be as small as possible in order to be understood. >In fact, I feel that the multiple-return structure is more in line with the >"structured" organization of programs. You are free to feel that way, but the strict definition of SP does not support your "feeling". Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Robert Martin @ 1998-09-04 0:00 ` Mike Spille 1998-09-05 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Mike Spille @ 1998-09-04 0:00 UTC (permalink / raw) Robert Martin wrote: > > > int f(char* name) // returns status value > { > int status = 0; > if (File* f = fopen(name, "r")) > { > if (char* buffer = malloc(80)) > { > DoSomethingUseful(f,buffer); > free(buffer); > } > else // malloc failure > { > Log("malloc failure"); > status = -2; > } > fclose(f); > } > else // fopen failure > { > Log("Failure to fopen"); > status = -1; > } > return status; > } > > Perhaps you think this is cumbersome. I don't. Cumbersome is a rather > subjective term. > I find it quite cumbersome, and error prone to boot. I'd do it as: int f(char* name) // returns status value { char buf[80]; FILE* f = fopen(name, "r"); if (f == NULL) { Log("Failure to fopen"); return (-1); } DoSomethingUseful(f,buf, sizeof(buf)); fclose (f); } That is, use a stack-based buffer and pass in the size of the char array to do something useful so it doesn't walk off the end of the buffer by mistake (assuming that DoSomethingUseful is smart enough to include a size argument). My point? I focused on what the routine was supposed to do, not on a methodology, and ended up with a more efficient, less error-prone, shorter version. (And I think it's more readable :-) [snip] > >The se/se strcuture often creates a monolithic paragraph, > > Quite to the contrary, the se/se structure is defined as a structure that is > recursively decomponsible into four discrete se/se control elements. The > recursive decomposition goes right down to the level of single lines of > code. Thus, an se/se structure cannot be monolithic (literally "one rock"). > Well...putting theory aside, you wrote a poor-performing, IMHO hard to read C routine (well, C++ since some declarations happen in the middle of the routine). You did this to demonstrate the positive aspect of se/se. I ignored theory, stared at your function for awhile, figured out what it was supposed to do semantically, and then wrote it to accomplish its function. My version puts error reporting next to where it happens (yours moves error-handling away from error-checking; the fclose test and handling code are far apart), doesn't waste time malloc()ing, and is alot shorter. I didn't consciously follow any paradigm or methodology - I just used the language features as clearly and consisely as I could. > >creating a scope that extends across many lines. > > Lots of things creates scopes that extend accross many lines. Functions, > classes, try blocks. I'll grant you that scopes should be as small as > possible in order to be understood. > > >In fact, I feel that the multiple-return structure is more in line with the > >"structured" organization of programs. > > You are free to feel that way, but the strict definition of SP does not > support your "feeling". > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Mike Spille @ 1998-09-05 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-05 0:00 UTC (permalink / raw) Mike Spille <mspille@tisny.com> wrote: >Robert Martin wrote: >> >> [code elided] >> Perhaps you think this is cumbersome. I don't. Cumbersome is a rather >> subjective term. On our teams if you were out voted you'd have to change it. All code is subject to review. In other words what is cumbersome can generally be agreed upon by the majority, or plurality of any mixed skill team of professional programmers. Spille wrote: >> >In fact, I feel that the multiple-return structure is more in line with the >> >"structured" organization of programs. >> You are free to feel that way, but the strict definition of SP does not >> support your "feeling". There is absolutely nothing to support your assertion, so it can not be absolutely anything other than unadulterated "feeling" on your part. Where oh where oh where is this "strict definition of SP"? You are making a fundamental assertion here, and any sane academic in the world would say that the burden of proof that se/se is a key defining criterion of SP is clearly upon you. For shame Robert Martin, for shame! [And given the overwhelming pro-RCM, pro-craftite makeup of the moderators for the proposed comp.object.moderated group, they would suppress any questioning of your blatantly intellectually dishonest assertions. You could just slide by slippery as a snake.] [And what makes this even more bogus, and outrageous is that these moderators have been elected for life. There is no provision at all for periodic elections.] Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille @ 1998-09-04 0:00 ` Ray Blaak 1998-09-06 0:00 ` Charles Hixson 1998-09-04 0:00 ` Gerry Quinn [not found] ` <EyyLos.2nx@yc.estec.esa.nl> 3 siblings, 1 reply; 510+ messages in thread From: Ray Blaak @ 1998-09-04 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > It seems to me that: > > if (A is right) > if (B is right) > if (C is right) > then do the work. > > emphasizes the work more than: > > if (A is wrong) then return; > if (B is wrong) then return; > if (C is wrong) then return; > do the work; > A compromise that allows both positive logic and reduced nesting is to calculate a guard value, and only do the work if the guard is true: doit := (A is right); doit := doit and (B is right); doit := doit and (C is right); if doit then do the work; -- Cheers, The Rhythm is around me, The Rhythm has control. Ray Blaak The Rhythm is inside me, blaak@infomatch.com The Rhythm has my soul. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ray Blaak @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Ray Blaak wrote: ... > A compromise that allows both positive logic and reduced nesting is to > calculate a guard value, and only do the work if the guard is true: > > doit := (A is right); > doit := doit and (B is right); > doit := doit and (C is right); > if doit then do the work; > > -- > Cheers, The Rhythm is around me, > The Rhythm has control. > Ray Blaak The Rhythm is inside me, > blaak@infomatch.com The Rhythm has my soul. It may be just me, but I find this final example to be the least intelligible of the variants offered. Yes, it is structured. But it's harder to understand. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` Robert Martin 1998-09-07 0:00 ` Patrick Logan 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-06 0:00 UTC (permalink / raw) Charles Hixson wrote in message <35F24AC9.40FE817C@earthlink.net>... >Ray Blaak wrote: >... >> A compromise that allows both positive logic and reduced nesting is to >> calculate a guard value, and only do the work if the guard is true: >> >> doit := (A is right); >> doit := doit and (B is right); >> doit := doit and (C is right); >> if doit then do the work; >> >> -- >> Cheers, The Rhythm is around me, >> The Rhythm has control. >> Ray Blaak The Rhythm is inside me, >> blaak@infomatch.com The Rhythm has my soul. > >It may be just me, but I find this final example to be the least >intelligible of the variants offered. Yes, it is structured. But it's >harder to understand. Which demonstrates how subjective intelligibility is. I find the above quite clear. It can easily be rephrased as: if ((A is right) and (B is right) and (C is right)) then do the work; Which, to me, is the ultimate in clarity. Clarity, intelligibility, understandability, readablility... All these things are subjective. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin @ 1998-09-07 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-07 0:00 UTC (permalink / raw) : >> doit := (A is right); : >> doit := doit and (B is right); : >> doit := doit and (C is right); : >> if doit then do the work; This violates one of the principles I try always to follow: single assignment. Unless a variable is in a loop, being updated to reflect the state of the loop, I will never assign a second value to it. If I wanted the form above, I'd rephrase it like this: boolean a_ok := (A is right); boolean b_ok := a_ok and (b is right); boolean c_ok := b_ok and (c is right); if c_ok then do the work; But I don't like this form anyway because it makes me wonder why test for b_ok if it has already been established that a_ok is false. This is so far away from the idioms I use all the time that it makes me wonder what was one the developer's mind and what I might not be correctly understanding. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille 1998-09-04 0:00 ` Ray Blaak @ 1998-09-04 0:00 ` Gerry Quinn [not found] ` <EyyLos.2nx@yc.estec.esa.nl> 3 siblings, 0 replies; 510+ messages in thread From: Gerry Quinn @ 1998-09-04 0:00 UTC (permalink / raw) In article <6sn2lv$t6m$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > >Now, in a real se/se function that checks a few things before doing the real >work, the real work will be the most indented part of the function. People >who train themselves to know that the real work is the stuff that is most >indented, have little trouble finding it. Extra indentation is in itself a practical disadvantage (the extent of which depends on the development system), which may cause programmers to use names which are too short, and/or run statements over multiple lines, leading to a lack of clarity. (You guessed it, VC5...) - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <EyyLos.2nx@yc.estec.esa.nl>]
* Re: Software landmines (loops) [not found] ` <EyyLos.2nx@yc.estec.esa.nl> @ 1998-09-08 0:00 ` Robert Martin 1998-09-08 0:00 ` John G. Volan 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-08 0:00 UTC (permalink / raw) duncan@yc.estec.esa.nlx wrote in message ... [re large se/se functions] >Even with an indent level of only 2 spaces, the code would >regularly march off the right of the screen and wrap around, >making readability, maintenance and reformatting in the event >of a change an absolute nightmare. [re modularization of above large functions.] > >However, the system already had serious performance problems without >adding several function calls and associated context switching... In this extreme situation it seems clear that you'd want to use multiple exits. The cost of the se/se solution in this context probably outweighs any benefits that might be derived. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) [not found] ` <EyyLos.2nx@yc.estec.esa.nl> 1998-09-08 0:00 ` Robert Martin @ 1998-09-08 0:00 ` John G. Volan 1998-09-08 0:00 ` duncan 1 sibling, 1 reply; 510+ messages in thread From: John G. Volan @ 1998-09-08 0:00 UTC (permalink / raw) duncan@yc.estec.esa.nlx wrote: > > int doSomething(Tree *pTop) > { > int errorCode; > > if (pTop != NULL) > { > if (pTop->pChild != NULL) > { > if (pTop->pChild->pChild != NULL) > { > /* lots of nesting omitted */ > > if (pTop->pChild...->pChild != NULL) > { > errorCode = reallyDoSomething(pTop->pChild...->pChild); > } else > { > errorCode = ERRORX; > } else > { > errorCode = ERROR3; > } > } else > { > errorCode = ERROR2; > } > } else > { > errorCode = ERROR1; > } > return(errorCode); > } For what it's worth, the above could be transformed into: int doSomething(Tree *pTop) { int errorCode; if (pTop == NULL) { errorCode = ERROR1; } else if (pTop->pChild == NULL) { errorCode = ERROR2; } else if (pTop->pChild->pChild == NULL) { errorCode = ERROR3; } ... /* lots of nesting omitted */ ... else if (pTop->pChild...->pChild == NULL) { errorCode = ERRORX; } else { errorCode = reallyDoSomething(pTop->pChild...->pChild); } return(errorCode); } As you can see, the nesting has been considerably reduced, yet this function is still single entry/single exit. It also shares with the early-return version the advantage of showing the choice of error-code close to the test that determines the error. Best of both worlds? :-) > int compareThings(Thing *pLeft, Thing *pRight) > { > assert(pLeft != NULL && pRight != NULL); > > if (pLeft->x != pRight->x) > { > if (pLeft->x < pRight->x) > { > return(-1); > } else > { > return(+1); > } > } > if (pLeft->y != pRight->y) > { > /* similar logic */ > } > /* other members */ > return(0); > } Again, the above can be transformed to: int compareThings(Thing *pLeft, Thing *pRight) { assert(pLeft != NULL && pRight != NULL); int result = 0; if (pLeft->x < pRight->x) { result = -1; } else if (pLeft->x > pRight->x) { result = +1; } else if (pLeft->y < pRight->y) { result = -1; } else if (pLeft->y > pRight->y) { result = +1; } /* other members */ else { result = 0; } return result; } -- indexing description: "Signatures for John G. Volan" self_plug: "Ex Ada guru", "Java 1.1 Certified", "Eiffelist wannabe" two_cents: "Java would be even cooler with Eiffel's assertions/DBC, % %generics, true MI, feature adaptation, uniform access, % %selective export, expanded types, etc., etc..." class JOHN_VOLAN_SIGNATURE inherit SIGNATURE invariant disclaimer: not (opinion implies employer.opinion) end -- class JOHN_VOLAN_SIGNATURE ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` John G. Volan @ 1998-09-08 0:00 ` duncan 1998-09-08 0:00 ` Patrick Doyle 0 siblings, 1 reply; 510+ messages in thread From: duncan @ 1998-09-08 0:00 UTC (permalink / raw) In article <35F534F6.D3CCE360@sprintmail.com>, John G. Volan <johnvolan@sprintmail.com> wrote: > > [... transformed heavily indented nested if's to single level of > indentation by effectively NOTing the test condition and adjusting > the formatting ...] > >As you can see, the nesting has been considerably reduced, yet this >function is still single entry/single exit. It also shares with the >early-return version the advantage of showing the choice of error-code >close to the test that determines the error. > >Best of both worlds? :-) Yes, but this was my point. Many people rail against early returns as being "problematic" for whatever reason or purpose. To my mind, provided you restrict early returns to 'pre-condition checking', the logic can still be preserved, and can be just as "readable" (or indeed "unreadable") as a se/se solution. [*] If you sprinkle return statements in the middle of the inner gubbins of the routine where resources have been allocated, or modified, or waiting to be reallocated, then it is much more difficult to ensure that each early return actually leaves the system in an appropriate state. This is especially true when the maintenance/upgrade phase begins when nobody remembers all of the gotchas any more. [*] Note that sometimes the natural flow of one form of a test can make it a lot easier to understand what is going on than choosing the negative form of the test just to fit with a particular style. This can also influence which form you would use. Unfortunately no examples of this spring to mind other than: if (IsX(a)) { ProcessX(a); } else if (IsY(a)) { ProcessY(a); } else { ProcessZ(a); } as opposed to if (!IsX(a)) { if (!IsY(a)) { ProcessZ(a); } else { ProcessY(a); } } else { ProcessX(a); } And as has been already noted, what is "readable" or "unreadable" is very subjective. This is my article, not my employer's, with my opinions and my disclaimer! -- Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx To avoid junk email my quoted address is incorrect. Use nl instead of nlx. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` duncan @ 1998-09-08 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-08 0:00 UTC (permalink / raw) In article <Eyz1vB.EoC@yc.estec.esa.nl>, <duncan@yc.estec.esa.nlx> wrote: >In article <35F534F6.D3CCE360@sprintmail.com>, >John G. Volan <johnvolan@sprintmail.com> wrote: >> >>As you can see, the nesting has been considerably reduced, yet this >>function is still single entry/single exit. It also shares with the >>early-return version the advantage of showing the choice of error-code >>close to the test that determines the error. >> >>Best of both worlds? :-) > >Yes, but this was my point. Many people rail against early returns >as being "problematic" for whatever reason or purpose. To my mind, >provided you restrict early returns to 'pre-condition checking', the >logic can still be preserved, and can be just as "readable" (or indeed >"unreadable") as a se/se solution. [*] Yes but, unless I'm mistaken, that was *John's* point: His code contained no early returns, and still preserved se/se without deep nesting. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Robert Martin wrote: ... > if (condition.1) return; > else if (condition.2) return; > else do something useful; > return; > }; > > Which, in reality, is: > > void f() > { > if (condition.1) return; > else{ > if (condition.2) return; > else { > do something useful; > } > } > }; > > So, early returns do not actually reduce nesting; they just appear to. The ... > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan If you are going to use else-if's, then the early return doesn't accomplish anything, and the routine could be rephrased as: void f() { if (!condition.1 & !condition.2) { do something useful; } }; Just a transform, I know. But, actually, that's my point. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson 1998-09-09 0:00 ` sureshvv 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-06 0:00 UTC (permalink / raw) Charles Hixson wrote in message <35F2496D.7C4BDC42@earthlink.net>... >Robert Martin wrote: >... >> if (condition.1) return; >> else if (condition.2) return; >> else do something useful; >> return; >> }; >> >> Which, in reality, is: >> >> void f() >> { >> if (condition.1) return; >> else{ >> if (condition.2) return; >> else { >> do something useful; >> } >> } >> }; >> >> So, early returns do not actually reduce nesting; they just appear to. The >... >> >> Robert C. Martin | Design Consulting | Training courses offered: >> Object Mentor | rmartin@oma.com | Object Oriented Design >> 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ >> Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com >> >> "One of the great commandments of science is: >> 'Mistrust arguments from authority.'" -- Carl Sagan >If you are going to use else-if's, then the early return doesn't >accomplish anything, and the routine could be rephrased as: > void f() > { > if (!condition.1 & !condition.2) > { do something useful; > } > }; > >Just a transform, I know. But, actually, that's my point. PRECISELY! Early returns form a boolean equation which is an OR of terms: if this then return. or if that then return. or if the_other then return or do something useful. But, as you noted, we can apply Demorgan's theorem and turn this into an AND of factors if (!this AND !that AND !the_other) then do something useful Just a transformation, And one that turns a multiple exit function into an se/se function. we might then decide that long boolean equations are better split apart: if (!this) if (!that) if (!the_other) then do something useful. Which is an idiom that we can learn to read as a set of ANDS. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Charles Hixson 1998-09-09 0:00 ` sureshvv 1 sibling, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Robert Martin wrote: > ... > > But, as you noted, we can apply Demorgan's theorem and turn this into an AND > of factors > > if (!this AND !that AND !the_other) > then do something useful > > Just a transformation, And one that turns a multiple exit function into an > se/se function. > > we might then decide that long boolean equations are better split apart: > > if (!this) > if (!that) > if (!the_other) > then do something useful. > > Which is an idiom that we can learn to read as a set of ANDS. > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan However, this is only reasonably intelligible BECAUSE the "do something useful" is limited to a very few lines. I suppose that this could be an argument in favor of having small function bodies, but I generally find that the natural size of a function body is determined by local data dependencies, and that splitting off pieces that are actually connected with thick pipes makes things harder to understand. Therefore, if I can do some quick validity tests at the START of a routine, and return error codes if necessary, then that lets me express the functions real form without excessive internal checks. And yes, formally this is equivalent to wrapping the body of the routine in an if block, so that it could be mechanically transformed into a se/se form (if one had the correct software tool). But that form would be harder to understand. N.B.: One limitation that I advocate here is that the early returns from routines be performed BEFORE the routine does anything which would create any non-temporary changes. I.E., it's ok to initialize/change local variables, but not anything that is non-local, and not anything that would be remembered between calls. This limitation avoids the maintenance problems that have been described earlier as endemic to non-se/se routines. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson @ 1998-09-09 0:00 ` sureshvv 1 sibling, 0 replies; 510+ messages in thread From: sureshvv @ 1998-09-09 0:00 UTC (permalink / raw) In article <6su70s$db8$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Charles Hixson wrote in message <35F2496D.7C4BDC42@earthlink.net>... > >Robert Martin wrote: > >... > >> if (condition.1) return; > >> else if (condition.2) return; > >> else do something useful; > >> return; > >> }; > >> > >> Which, in reality, is: > >> > >> void f() > >> { > >> if (condition.1) return; > >> else{ > >> if (condition.2) return; > >> else { > >> do something useful; > >> } > >> } > >> }; > >> > >> So, early returns do not actually reduce nesting; they just appear to. But appearance is important. If we make the code appear simpler yet retaining its functionality, we have made it more readable/maintainable. I diasagree with your notion that creating placeholders in code where you might end up adding code in future is the way to make code more maintainable. On the contrary, maintainability is when the code is sufficiently decoupled that you may rip out any one piece (eg., class method), be able to totally rewrite it and rebuild the system without breaking it. > > Early returns form a boolean equation which is an OR of terms: > > if this then return. > or > if that then return. > or > if the_other then return > or > do something useful. > > But, as you noted, we can apply Demorgan's theorem and turn this into an AND > of factors > > if (!this AND !that AND !the_other) > then do something useful > > Just a transformation, And one that turns a multiple exit function into an > se/se function. > This is why I added a couple of realistic requirements, where - a different message should be logged for each input condition - a different value has to be returned for each input condition With these requirements a simple transformation will not do and the se/se solution becomes less readable. > we might then decide that long boolean equations are better split apart: > > if (!this) > if (!that) > if (!the_other) > then do something useful. > > Which is an idiom that we can learn to read as a set of ANDS. Wonderfully adaptable creatures that we are, we can learn to do almost anything :-) But why? suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Patrick Logan 1998-09-04 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object sureshvv@hotmail.com wrote: : I would like to find out the costs that are associated with the se/se : structure of functions. : 1. Increases level of nesting in code, making it potentially more complex. You should procedures or methods to make loops more abstract and smaller. : 2. Requires adding flag variables which have to be tracked, making it : more complex. A flag variable can actually make a complex condition more readable by providing it with a meaningful name. : 3. Special conditions can become embedded in code rather than being readily : apparent. I'd have to see an example of this in either style in order to understand it. Nothing should be *too* hidden if the loop text is kept to a manageable size. Size is (almost) everything. Beyond that names, comments, and good, nested, formatting should make a loop's control flow and special cases apparent. Please throw your worst one at us, so we can all refactor it to our liking! (Reminds me of the revived GOTO controversy, in what? The Communications of the ACM about ten years ago or so.) -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Patrick Logan @ 1998-09-04 0:00 ` Matthew Heaney 0 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-04 0:00 UTC (permalink / raw) Patrick Logan <plogan@user2.teleport.com> writes: > (Reminds me of the revived GOTO controversy, in what? The > Communications of the ACM about ten years ago or so.) Funny you should mention that - this thread reminded me of that too. The ACM Forum articles started with "'GOTO Considered Harmful' Considered Harmful" by Frank Rubin, CACM, vol 30, no 3, Mar 87, and continuing every issue through Dec 87. The editor concluded the Forum letters with the statement: "With this second rejoinder from Frank Rubin it seems expedient to bring to a close the publication of correspondence generated by his March 1987 Forum letter, greater response by far than with any other issue ever considered in these pages." (Even Dijkstra himself jumped in a couple of times.) I guess opinions on this subject haven't changed much in 11 years! Matt ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <6skqf3$ <35F0B5B0.8E2D0166@s054.aone.net.au>]
* Re: Software landmines (loops) [not found] ` <6skqf3$ <35F0B5B0.8E2D0166@s054.aone.net.au> @ 1998-09-06 0:00 ` Will Rose 1998-09-06 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Will Rose @ 1998-09-06 0:00 UTC (permalink / raw) Loryn Jenkins (loryn@s054.aone.net.au) wrote: : Ell wrote: : > : > Loryn Jenkins <loryn@s054.aone.net.au> wrote: : > : > >> Then clearly you have not read much of Dijkstra. The citation you want is : > >> the citation I have given you many many times. Go look it up Elliott. : > : > >Yes, look it up. Read it. Acknowledge that that is what Dijkstra was : > >saying. : > : > How can I acknowledge that, if I haven't seen it? And you all can't : > point to that stuff on flowcharting as some kind of proof that the : > founders of SP said we should adhere to se/se. : > : > >Remember, you *may* disagree with him. But it is silly not reading what : > >he actually said. : > : > That book is out of print and RCM knows it. : That's what libraries are for. : > If RCM had *any* shred of : > text to prove that they explicitly advocated se/se in structured : > coding he would quote it. : A charitable interpretation of what they have already quoted has : demonstrated that. : But leave that aside. Let us say that many people who have read the book : have made that interpretation. It is certainly possible for you to claim : that no, se/se is not what Dijkstra was going on about, he was really : using se/se as a tool to demonstrate that, say, code should be provable. : And it is the provability of code that is the foundation of structured : programming. : This may or may not be correct. But it is an acceptable line of : argument. : But an even better line of argument may in fact be, yes, Dijkstra does : believe in se/se. But what he should have been concentrating on was, : say, provability. : > : > > And it is fantasy arguing that he wasn't discussing : > >se/se. : > : > It's a deplorable attempt at deception for RCM to state that se/se is : > a cornerstone of SP without a shred of evidence. : How about, 'a cornerstone of SP as advocated by Dijkstra'. (That doesn't : necessarily mean he was right; that doesn't necessarily mean that it is : today, in fact, the basis for SP (as practised by the majority of : practitioners.) It merely means that he advocated it. (And, I think, it : would be incorrect to debate that his view has influenced many people. : That is, it is an historical fact that his views have influenced many : people (other than RCM ... take BM as an example) about the use of : se/se. : > : > It's fantastic gullibility to think RCM is right about se/se without a : > shred of evidence; : What evidence? A quotation? Hah. That's not proof that se/se is right. : That's only proof that it is an historical fact Dijkstra argued for : se/se. Whether se/se is right is another matter entirely. : > to believe him based on faith, because I'll bet : > dollars to doughnuts that you can't show me any proof either. : Like you, I don't have the book at hand. But RCM's claims of Dijkstra's : position seems 'right' to me (based on triangulating what I've read of : many other people who've read Dijkstra). I'm not sure which book started this discussion, but Dijkstra's "Notes on Structured Programming" in "Structured Programming", Dahl, Dijkstra and Hoare, say inter alia: When we now take the position that it is not only the programmer's task to produce a correct program but also to demonstrate its correctness in a convincing manner, then the above remarks [on program size and structure] have a profound influence on the programmer's activity; the object he has to produce must be usefully structured. The remaining part of this monograph will be mainly an exploration of what program structure can be used to good advantage. In what follows it will become apparent that program correctness is not my only concern, program adaptability or manageability will be another. This stress on program manageability is my deliberate choice, a choice that, therefore, I should like to justify. ...[description of flowcharts which] "share the property that they have a single entry at the top and single exit at the bottom"... ...Alternatively: restricting ourselves to the three mentioned types of decomposition leads to flowcharts of restricted topology compared with the flowcharts one can make when arrows can be drawn from one block leading to any other. Compared with that greater freedom, to restrict oneself to the clauses presents itself as a sequenceing discipline. Why do I propose to adhere to this sequencing discipline? The justfication for this decision can be presented in many ways... Will cwr@crash.cts.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Will Rose @ 1998-09-06 0:00 ` Ell 1998-09-06 0:00 ` Jeffrey C. Dege 0 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-06 0:00 UTC (permalink / raw) In comp.object Will Rose <cwr@cts.com> wrote: : I'm not sure which book started this discussion, but Dijkstra's : "Notes on Structured Programming" in "Structured Programming", : Dahl, Dijkstra and Hoare, say inter alia: : "When we now take the position that it is not only the programmer's : task to produce a correct program but also to demonstrate its : correctness in a convincing manner, then the above remarks [on program : size and structure] have a profound influence on the programmer's : activity; the object he has to produce must be usefully structured." : : "The remaining part of this monograph will be mainly an exploration of : what program structure can be used to good advantage. In what follows : it will become apparent that program correctness is not my only concern, : program adaptability or manageability will be another. This stress on : program manageability is my deliberate choice, a choice that, therefore, : ..." Yes *this* is the overall *spirit* we should be working in. And quite often restricting a loop, or procedure to se/se makes things less maintainable in the judgement of a plurality or majority of project programmers. Multiple exits to enhance maintenance can work while preserving the ability to prove program correctness. This happens if multiple exits exist in a program which uses procedure calls and returns to calling procedures 99.5% of the time as I see it. : ...[description of flowcharts which] "share the property that they : have a single entry at the top and single exit at the bottom"... OK, the single entry at the top and single exit at the bottom of the flowchart, as a means of helping to prove correctness, and as they say of improving maintainability. As I see it they made no specification that when going through a physical coding structure coding that represents for example a diamond decision that we must have only a single exit out. In fact the graphical depiction of the decision diamond itself has *2* paths out it! 'Yes' and 'No', 'Greater', or 'Lesser', etc. : ...Alternatively: restricting ourselves to the three mentioned types : of decomposition leads to flowcharts of restricted topology compared : with the flowcharts one can make when arrows can be drawn from one : block leading to any other. ["Blocks" here certainly should be taken as procedures/functions/routines nowadays because I'm sure they would frown on going from one unencapsulated tagged block of code to another when we now have encapsulated procedures/functions/routines.] Certainly they aren't saying you shouldn't navigate to another "block", but that you must use discipline to get there. As you quote them: : "Compared with that greater freedom, to restrict oneself to the clauses : presents itself as a sequencing discipline." As I see it, proof and maintainability are fundamentally made easier by using procedure calls and returning to the caller, whether using multiple or single exits. Really, what better way overall is there to handle navigation in general? The se/se people in their attempt to preserve proof and maintainability are being too rigid and dogmatic. In fact many uses of se/se make proof and maintenance more difficult. The se/se people in trying to hard miss the point. The spirit and essence of what I get from Dahle and Dijkstra on structured programming is: 1) Use procedure calls and return to procedures 2) Design procedures as abstractions (Dijkstra in "Art of Literate Programming" by Knuth) Navigation should be from one highly coherent, loosely coupled task abstraction procedure to another. Navigation should not be from one isolated loop, branch, or process structure to another, but between complete task abstraction procedures/functions/routines. [Dijkstra also mentions creating a hierarchy of abstractions - a layered design.] Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Ell @ 1998-09-06 0:00 ` Jeffrey C. Dege 0 siblings, 0 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-06 0:00 UTC (permalink / raw) On Sun, 06 Sep 1998 21:44:00 GMT, Ell <ell@access5.digex.net> wrote: >In comp.object Will Rose <cwr@cts.com> wrote: > >: "The remaining part of this monograph will be mainly an exploration of >: what program structure can be used to good advantage. In what follows >: it will become apparent that program correctness is not my only concern, >: program adaptability or manageability will be another. This stress on >: program manageability is my deliberate choice, a choice that, therefore, >: ..." > >Yes *this* is the overall *spirit* we should be working in. And quite >often restricting a loop, or procedure to se/se makes things less >maintainable in the judgement of a plurality or majority of project >programmers. I absolutely agree. In fact, so do most of the software engineering texts I've seen. Stephen Schach, who provided the definition of of structured programming that I quoted in an earlier post, explicitly recommends that the classical definition be loosened enough to allow breaks and gotos in the forward direction, particularly as a method of handling exceptional errors. >Multiple exits to enhance maintenance can work while preserving the >ability to prove program correctness. This happens if multiple exits >exist in a program which uses procedure calls and returns to calling >procedures 99.5% of the time as I see it. I've heard people talk about how breaks and multiple returns confuse code, and I'll have to admit, if a function or loop is lengthy, it can difficult to identify embedded returns or breaks. In these longer constructs, enforcing se/se makes them clearer. In a fairly short function or a short loop, identifying multiple returns or breaks is quite easy. So we might say that it is perfectly OK to use multiple returns in a short function or loop. But I think that's the wrong answer, entirely. We should say that it's _not_ OK to have long functions or loops. Breaking from the middle of a 20-line loop is perfectly understandable. Breaking from the middle of a 400-line loop is not. The answer is not to never break from a 400-line loop, but rather not to have 400-line loops. -- When cryptography is outlawed, bayl bhgynjf jvyy unir cevinpl. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerry Quinn @ 1998-09-01 0:00 ` Mike Spille 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` mfinney 1998-09-02 0:00 ` Gene Gajewski 3 siblings, 1 reply; 510+ messages in thread From: Mike Spille @ 1998-09-01 0:00 UTC (permalink / raw) Robert Martin wrote: > > Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... > > >Multiple exits to a single destination are not spaghetti. > > Spaghetti is not a well defined term. > > However, multiple exits to a single destination represent a problem. The > two exits come from two different states within the algorithm. If the > single destination must do some work that depends upon that state (or if in > the future, that single destination must be modified to do work that depends > upon that state), then the code in the single destination is going to get > pretty ugly. > OK, what if the state does not change? For example, typical "search" functions check for validity of arguments, valid internal state, etc before continuing. These checks do not affect state, and if a check fails, there's no point in continuing. Why complicate matters with extra variables and nesting? I think the problem with this argument is people are trying to fit one solution to many problems. Not all functions aqcuire resources. And on the flip side, not all functions are stateless. Should you write your functions in such a way that you're ignorant of how it affects state?!?! Should you add over-head to functions that do not affect state, and by design, never will? NO! And if my function _does_ affect state, then it is unlikely I'll have multiple exits. If I do, they'll be in checks at the top asserting correctness, and returning null (or error, or whatever) at the top. So what do you do when the function "grows"? Well, first off, most functions (in my programs at least) don't grow. The majority are dinky 8 or 9 liners that don't change over time. The minority that _do_ change over time, tend to change alot. They're complex. Knowing "This code only has one exit point" does not add to my understanding of the code at all. And if I can't understand it, I _can't_ modify it. If it grows significantly, I split it into multiple functions. > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Mike Spille @ 1998-09-01 0:00 ` Robert Martin [not found] ` <gio+van+no+ni+8-0309982212300001@dialup62.tlh.talstar.com> 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-01 0:00 UTC (permalink / raw) Mike Spille wrote in message <35EC1B94.CAC23CB3@tisny.com>... >Robert Martin wrote: >> >> Gerry Quinn wrote in message <6sgror$je8$3@news.indigo.ie>... >> >> >Multiple exits to a single destination are not spaghetti. >> >> Spaghetti is not a well defined term. >> >> However, multiple exits to a single destination represent a problem. The >> two exits come from two different states within the algorithm. If the >> single destination must do some work that depends upon that state (or if in >> the future, that single destination must be modified to do work that depends >> upon that state), then the code in the single destination is going to get >> pretty ugly. >> > >OK, what if the state does not change? For example, typical "search" >functions check for validity of arguments, valid internal state, etc >before continuing. These checks do not affect state, and if a check >fails, there's no point in continuing. Why complicate matters with >extra variables and nesting? Granted. If you are realy sure, then use the early return. I do it sometimes too. But I remain aware of the cost and the risk. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0309982212300001@dialup62.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0309982212300001@dialup62.tlh.talstar.com> @ 1998-09-04 0:00 ` Robert I. Eachus [not found] ` <gio+van+no+ni+8-0809981840170001@dialup75.tlh.talstar.com> 0 siblings, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-04 0:00 UTC (permalink / raw) In article <gio+van+no+ni+8-0309982212300001@dialup62.tlh.talstar.com> gio+van+no+ni+8@tal+star+spam.com (Giovanni 8) writes: > I've run across this, too. Back before interactive debuggers > it was common to use gotos to reach a "normal" return, that, > with debugging turned on in the pre-compiler, would generate > a sort of trace log. But even there, it has the disadvantage > of covering up the "actual" point from which one is returning. > Why not deal with error handling right there, where the most > information is available? I think we are geting to the point of violent agreement. The "structured" code: <<Bad1>> loop Get(Next); if Next /= null; [lots of normal case code] else exit; end if; end loop; or <<Bad2>> Get(Next); while Next /= done loop [lots of normal case code] Get(Next); end loop; should be regarded as broken while the equivalents: <<Good1>> loop Get(Next); if Next = null then exit; else [lots of normal case code] end if; end loop; or <<Good2>> loop Get(Next); exit when Next = null; [lots of normal case code] end loop; or <<Good3>> while Get(Next) loop; [lots of normal case code] end loop; are winners. The chief reason the first examples should be regarded as broken is that they result in one conceptual action being split often across several pages. Either the maintainer has to find two widely separated calls to Get that are really the same call, or you have to flip through several pages of code to find out where the then part of the if ends. Either can lead to errors. Among those marked as good, we can argue all year as to which is best, but in reality who cares. If maintaining that code, we will all be looking elsewhere for problems. I happen to prefer Good2 and those with a strong C background, or programming in C or C++ will probably prefer Good3. (In Ada you have to add a level of indirection so that the (now function) Get can modify its argument, and the new value is a side effect while the function actually returns a boolean. For Ada programmers this idiom is somewhat distateful, but in C it is almost standard.) Other languages favor other styles. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0809981840170001@dialup75.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0809981840170001@dialup75.tlh.talstar.com> @ 1998-09-09 0:00 ` Nick Leaton [not found] ` <gio+van+no+ni+8-1609980026290001@dialup26.tlh.talstar.com> 0 siblings, 1 reply; 510+ messages in thread From: Nick Leaton @ 1998-09-09 0:00 UTC (permalink / raw) Giovanni 8 wrote: > > > Robert I. Eachus wrote: > >> Giovanni 8 wrote: > >> I've run across this, too. Back before interactive debuggers > >> it was common to use gotos to reach a "normal" return, that, > >> with debugging turned on in the pre-compiler, would generate > >> a sort of trace log. But even there, it has the disadvantage > >> of covering up the "actual" point from which one is returning. > >> Why not deal with error handling right there, where the most > >> information is available? > > > I think we are geting to the point of violent agreement. > > The "structured" code: > > > > <<Bad1>> > > > > loop > > Get(Next); > > if Next /= null; > > [lots of normal case code] > > else exit; > > end if; > > end loop; > >... > > should be regarded as broken while the equivalents: > > > > <<Good1>> > > > > loop > > Get(Next); > > if Next = null > > then exit; > > else > > [lots of normal case code] > > end if; > > end loop; > > > or > > <<Good2>> > > > > loop > > Get(Next); > > exit when Next = null; > > [lots of normal case code] > > end loop; > > > or > > <<Good3>> > > > > while Get(Next) loop; > > [lots of normal case code] > > end loop; > > Great, if the "Get" knows what abnormal conditions to handle > for this particular context (module, function, whatever), & > then one would work in other "normal" conditions, as well. > > This reminds me of reading Wirth's _Systematic Programming_. > He presented these pat examples, to which few common problems > could be made to conform. (Even his "proof" of a GCD > algorithm just kind of brushed past a crucial point.) > > It's more like > loop > { > Get(Next); > if (thiscondition) then > { > do this; > return; > } > else if (thatcondition) then > { > do that; > return; > } > else if (theother) then > { > do goodstuff; > } > else if (yetanother) then > { > do othergoodstuff; > } > else > do unforeseencondition; > endif > do morestuff > } > endloop when(x); > do aftertheloopstuff > return; > > Yes, it's defensive programming. Enlighten me. So lets say the loop calculates a square root. What should 'do this' and 'do that' do? What if it is in an aircraft, in a simulation? Do you want to rewrite square root for each case? -- Nick ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-1609980026290001@dialup26.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-1609980026290001@dialup26.tlh.talstar.com> @ 1998-09-16 0:00 ` Nick Leaton 0 siblings, 0 replies; 510+ messages in thread From: Nick Leaton @ 1998-09-16 0:00 UTC (permalink / raw) Giovanni 8 wrote: > > > nickle wrote: > > So lets say the loop calculates a square root. What should > > "do this" and "do that" do?... Do you want to rewrite square > > root for each case? > > Try for a less simplistic example, please. > > Part of my point is that the called function (Get, in the > example I was following-up to) does its job well, has one > or 2 different kinds of error values, & n "successful" return > values. Get, however, "knows" little of the environment, the > context, from which it is called. That's fine, but it means > that there are things it cannot handle with an eye to that > context. The instant routine, which calls Get, does "know" > that context, and needs to do a number of different things > depending on the results of the Get, some having to do with > error conditions of one sort or another, and others having > to do with "normal" conditions, all to be dealt with in > the context of the current context, in the current function, > in the current loop. But again what if I don't want to know all of the different things? The Get routine assumes that you do want to know all. Design by contract and command query separation makes life much simpler. First, any query doesn't modify the external view of an object. The procedure in your 'get' feature is modifying the object, its doing some work. Splitting it into a procedure to do the work, and a set of queries to examine the results makes life simple. Then you can add preconditions, such as not less than zero in the square root case to make sure that the caller behaves. If they don't then behaviour is undefined, but would raise an exception. Its a bug after all. Sounds hard, but would you expect your program to fix itself? Nick -- Nick ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerry Quinn 1998-09-01 0:00 ` Mike Spille @ 1998-09-02 0:00 ` mfinney 1998-09-02 0:00 ` Ell ` (3 more replies) 1998-09-02 0:00 ` Gene Gajewski 3 siblings, 4 replies; 510+ messages in thread From: mfinney @ 1998-09-02 0:00 UTC (permalink / raw) In <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: >However, multiple exits to a single destination represent a problem. The >two exits come from two different states within the algorithm. If the >single destination must do some work that depends upon that state (or if in >the future, that single destination must be modified to do work that depends >upon that state), then the code in the single destination is going to get >pretty ugly. I have been following this thread for a while (or at least part of the thread), and it seems to me that the basic argument is between the use of structured programming which requires a single entry and single exit and of tree- structured programming which allows multiple-level breaks/continues, but not arbitrary jumps into blocks. It turns out that tree-structured programming covers almost all of the flow graphs actually encountered by compilers which are not undecomposable and provides the necessary flow graph assurances for optimization (I do have a reference on that, but have just finished moving and everything is in boxes, so regrettably I can't provide it at this time). Multiple exits from a block do require the compiler to add extra control flow paths to a single exit point for some algorithms, but that is trivial control flow transformation by the compiler -- but not for the programmer because modern languages do not generally provide adequate control structures (other than goto) to represent the extra control flow paths. I personally feel that structured programming is a very good idea, but like most things is an extreme which is better with a little compromise. I see tree-structured programming as that compromise. It is true that multiple exits arrive from different states -- but presumably they all satisify the exit postcondition, and that is what should be used for subsequent programming (assuming that the exit postcondition is clearly stated). In a routine such as the one being used for an example, it seems clear that multiple exits do not harm and actually improve code readability. It has been suggested that the need for maintenance is a reason to twist the code unnaturally -- but that is where using a multiple level exit instead of returns would solve the problem (true, C/C++ does not directly provide multiple level exits, but they can be "faked"). It has been suggested that mid-loop exits (which can still be considered structured code because they have a single entry and a single exit, even if the exit is not at the top or bottom of the loop) are not good because the loop is not executed an integral number of times. On the contrary, that is the best possible reason to use a mid-loop exit because many programs do not naturally map to an integral number of iterations. It is always better to allow the control structure map as closely as possible to the problem. So "twisting" a mid-loop exit to make it a top or bottom exit, and possibly duplicating code will make code readability harder. It has also been stated that when multiple exits are allowed, it is necessary for the programmer to actually *read* the code to be able to understand it! Well surprise -- do you really want somebody modifying your code *without* reading it? Sorry, but I don't think so! It also seems to me that this argument has no resolution. Those who are strictly in favor of the orginal, unadulterated structured programming aren't going to give ground to those who favor a more relaxed view of structured programming. And, as far as maintainability is concerned, I strictly use tree-structured programming and have *never* found it to be a maintenance problem. Sure, sometimes code transformations are required during maintenance, but they are sometimes required during coding. So what? There is no way to write code that never requires code transformations during maintenance, and trying to do so just makes the code harder to understand and ultimately increases maintenance cost. Far better is to endevour to reach 0 bugs so that maintenance is never required. Not easy, perhaps, but it is getting closer and closer every day. I personally am running somewhere around 0.0001 and 0.0002 errors per line of code -- prior to quality assurance getting the code. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` mfinney @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Oliver ` (2 more replies) 1998-09-02 0:00 ` Ell ` (2 subsequent siblings) 3 siblings, 3 replies; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) On Wed, 02 Sep 1998 05:01:34 GMT, mfinney@lynchburg.net wrote: >In <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: > >>However, multiple exits to a single destination represent a problem. The >>two exits come from two different states within the algorithm. If the >>single destination must do some work that depends upon that state (or if in >>the future, that single destination must be modified to do work that depends >>upon that state), then the code in the single destination is going to get >>pretty ugly. >I have been following this thread for a while (or at least part of the thread), >and it seems to me that the basic argument is between the use of structured >programming which requires a single entry and single exit The assertion that "single entry, single exit" is a required, or even desirable, maxim of structured programming is a myth. No one (including RCM) can show that this maxim is in fact a coding heuristic put forward by any of the founders of the structured paradigm. [Check past posts in this thread.] Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` john-clonts ` (2 more replies) 1998-09-05 0:00 ` Ray Gardner [not found] ` <m31zpq4pim.fsf@mheaney.ni.ne <m3af36wtwh.fsf@mheaney.ni.net> 2 siblings, 3 replies; 510+ messages in thread From: Robert Oliver @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote: > The assertion that "single entry, single exit" is a required, or even > desirable, maxim of structured programming is a myth. > > No one (including RCM) can show that this maxim is in fact a coding > heuristic put forward by any of the founders of the structured > paradigm. [Check past posts in this thread.] Edward Yourdan, in his book Techniques of Program Structure and Design discusses this article: C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages with Only two Formation Rules", Communications of the ACM, May 1996, pages 366-371. (Is this not *the* foundational article for structured programming?) Yourdan says: "According to Bohm and Jacopini, we need three basic building blocks in order to construct a program: 1. A process box. 2. A generalized loop mechanism. 3. A binary-decision mechanism. The process box, shown in Fig. 4.1, may be thought of as a single computational statement (or machine language instruction) *or as any other proper conputational sequence with only one entry and one exit* - such as a subtoutine." The emphasis between *...* above is his (shown in italics) not mine. In the next paragraph he says: "Note that the constructs shown in Fig. 4.2(a) and 4.2(b) {the decision and loop control structures} can themselves be thought of as a process box since they have only one entry and one exit. Thus we can define a transformation from a looping operation to a process box ..." I added the part between braces {}. I do not have the Bohm and Jacopini article. All I have is Yourdans description of it. However, it seems clear from his description that the "single entry - single exit" principle is fundamental to structured programming. Yourdan goes on to discuss some practical implementations such as various loop constructs and the case statement. During this discussion, he uses the "single entry - single exit" principle repeatedly and refers to it as part of the "black-box principle". Bob Oliver ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Oliver @ 1998-09-02 0:00 ` john-clonts 1998-09-02 0:00 ` Darren New 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Matthew Heaney 2 siblings, 2 replies; 510+ messages in thread From: john-clonts @ 1998-09-02 0:00 UTC (permalink / raw) In article <35ED7082.1889@hfl.tc.faa.gov>, Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: > Ell wrote: > > > The assertion that "single entry, single exit" is a required, or even > > desirable, maxim of structured programming is a myth. > > > > No one (including RCM) can show that this maxim is in fact a coding > > heuristic put forward by any of the founders of the structured > > paradigm. [Check past posts in this thread.] > > Edward Yourdan, in his book Techniques of Program Structure and Design > discusses this article: > > C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages > with Only two Formation Rules", Communications of the ACM, May 1996, > pages 366-371. > > (Is this not *the* foundational article for structured programming?) > > Yourdan says: > > "According to Bohm and Jacopini, we need three basic building blocks in > order to construct a program: > > 1. A process box. > 2. A generalized loop mechanism. > 3. A binary-decision mechanism. > > The process box, shown in Fig. 4.1, may be thought of as a single > computational statement (or machine language instruction) *or as any > other proper conputational sequence with only one entry and one exit* - > such as a subtoutine." > > The emphasis between *...* above is his (shown in italics) not mine. > > In the next paragraph he says: > > "Note that the constructs shown in Fig. 4.2(a) and 4.2(b) {the decision > and > loop control structures} can themselves be thought of as a process box > since they have only one entry and one exit. Thus we can define a > transformation from a looping operation to a process box ..." > > I added the part between braces {}. > > I do not have the Bohm and Jacopini article. All I have is Yourdans > description of it. > > However, it seems clear from his description that the "single entry - > single exit" principle is fundamental to structured programming. > Yourdan > goes on to discuss some practical implementations such as various loop > constructs and the case statement. During this discussion, he uses the > "single entry - single exit" principle repeatedly and refers to it as > part of the "black-box principle". > > Bob Oliver > But wait: ... statementA; statementB; subroutine1(); statementC; Doesn't subroutine1() here qualify as having a single entrance/exit *regardless* how many "return" statements happen to be coded within it? Or does it even bear upon the discussion? John -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` john-clonts @ 1998-09-02 0:00 ` Darren New 1998-09-02 0:00 ` Robert Martin 1 sibling, 0 replies; 510+ messages in thread From: Darren New @ 1998-09-02 0:00 UTC (permalink / raw) john-clonts@hlp.com wrote: > Doesn't subroutine1() here qualify as having a single entrance/exit > *regardless* how many "return" statements happen to be coded within it? Yes, but if there's two return statements inside Subroutine1, then at least one structure will have multiple exits. (Or you have a wad of dead code after the return.) I.e., if S1 is bool subroutine1() { yadda; hither; if (test) { yon; return true; } gabba; return false; } then the "if" has two exits. -- Darren New / Senior Software Architect / First Virtual Holdings Inc http://www.fv.com or info@fv.com -=|=- PGP Key: ftp://ftp.fv.com/pub/fv Fingerprint: 61 7D AF 9E 00 CC C2 ED / D8 4C D7 AA E4 C2 A0 73 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` john-clonts 1998-09-02 0:00 ` Darren New @ 1998-09-02 0:00 ` Robert Martin 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) john-clonts@hlp.com wrote in message <6sken3$jv0$1@nnrp1.dejanews.com>... >In article <35ED7082.1889@hfl.tc.faa.gov>, >But wait: > >... > statementA; > statementB; > subroutine1(); > statementC; > >Doesn't subroutine1() here qualify as having a single entrance/exit >*regardless* how many "return" statements happen to be coded within it? The caller can be "structured" since he sees only one entry and one exit. But the function itself is not "structured". Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` john-clonts @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` Matthew Heaney 2 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: : Ell wrote: :> The assertion that "single entry, single exit" is a required, or even :> desirable, maxim of structured programming is a myth. :> :> No one (including RCM) can show that this maxim is in fact a coding :> heuristic put forward by any of the founders of the structured :> paradigm. [Check past posts in this thread.] : Edward Yourdan, in his book Techniques of Program Structure and Design : discusses this article: : C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages : with Only two Formation Rules", Communications of the ACM, May 1996, : pages 366-371. : (Is this not *the* foundational article for structured programming?) How can an artile written in '96 be *the* foundational article for the structured programming paradigm which gained currency in the late '70's? : Yourdan says: : "According to Bohm and Jacopini, we need three basic building blocks in : order to construct a program: : 1. A process box. : 2. A generalized loop mechanism. : 3. A binary-decision mechanism. : The process box, shown in Fig. 4.1, may be thought of as a single : computational statement (or machine language instruction) *or as any : other proper conputational sequence with only one entry and one exit* - : such as a subtoutine." Where is the proof that this underlays the structured paradigm and an assertion that something is "proper" doesn't make it so. What structured programming avoided was unstructured flow control. It encouraged the use of procedure/routine calls over 'goto'. Along with entry into a procedure via a call, the use of 'return' is structured flow control; 'return' can only go back to the calling procedure, unlike 'goto' which can branch to a label anywhere. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Ell 0 siblings, 2 replies; 510+ messages in thread From: Robert Oliver @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote: > > In comp.object Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: > : Ell wrote: > > :> The assertion that "single entry, single exit" is a required, or even > :> desirable, maxim of structured programming is a myth. > :> > :> No one (including RCM) can show that this maxim is in fact a coding > :> heuristic put forward by any of the founders of the structured > :> paradigm. [Check past posts in this thread.] > > : Edward Yourdan, in his book Techniques of Program Structure and Design > : discusses this article: > > : C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages > : with Only two Formation Rules", Communications of the ACM, May 1996, > : pages 366-371. > > : (Is this not *the* foundational article for structured programming?) > > How can an artile written in '96 be *the* foundational article for > the structured programming paradigm which gained currency in the late > '70's? Clearly it can't be. It should have read 1966. My typo. > > : Yourdan says: > > : "According to Bohm and Jacopini, we need three basic building blocks in > : order to construct a program: > > : 1. A process box. > : 2. A generalized loop mechanism. > : 3. A binary-decision mechanism. > > : The process box, shown in Fig. 4.1, may be thought of as a single > : computational statement (or machine language instruction) *or as any > : other proper conputational sequence with only one entry and one exit* - > : such as a subtoutine." > > Where is the proof that this underlays the structured paradigm and an > assertion that something is "proper" doesn't make it so. What structured > programming avoided was unstructured flow control. It encouraged the use > of procedure/routine calls over 'goto'. Yes, but there is more to it. Unstructured flow control was replaced by one or more of the previously mentioned programming constructs, process, loop, or decision. This was to be accomplished at all levels of code from main() to individual instructions. Bohm and Jacopini proved that one could write any realistic (proper) program using only these constructs. Sequences of instructions (or other process boxes) could be transformed into a process box with a single entry and single exit. Loops and decision mechanisms could be similarly transformed. In fact, using only these constructs ones code must be decomposable into blocks with only a single entry and exit. So, the point I wanted to make is that early on (Yourdon's book was published in 1975) was known as a common characteristic of structured programming. > Along with entry into a procedure > via a call, the use of 'return' is structured flow control; 'return' can > only go back to the calling procedure, unlike 'goto' which can branch to a > label anywhere. It's interesting that you use the fact that return always returns the program to a single exit point (the calling procedure) as an argument that this technique is structured. Indeed, it is at the procedure level. (Just, curious. Would you allow goto's if they could not leave the scope of the procedure? Probably not.) I am not arguing against all use of multiple returns in a procedure or function. I often write a function like this: void AFunction(...) { if (SomeCondition) return; if (AnotherCondition) return; if (AThirdCondition) return; // now do the real work... return; } I think this makes sense when AFunction is called from many places and the conditions need to be tested each time. I can look at the beginning of the function and know that there will be nothing done in these three circumstances. It's not without danger as RCM has pointed out, but I often choose to live with the risk. Of course, it could also be written as: void AFunction(...) { if not (SomeCondition) and not (AnotherCondition) and not (AThirdCondition) then // now do the real work... endif return; } Bob Oliver ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Oliver @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` sureshvv 1998-09-06 0:00 ` Charles Hixson 1998-09-03 0:00 ` Ell 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Robert Oliver wrote in message <35EDAC92.538A@hfl.tc.faa.gov>... > >I am not arguing against all use of multiple returns in a procedure or >function. I often write a function like this: > >void AFunction(...) >{ > if (SomeCondition) return; > if (AnotherCondition) return; > if (AThirdCondition) return; > > // now do the real work... > > return; >} > >I think this makes sense when AFunction is called from many places and >the >conditions need to be tested each time. I can look at the beginning of >the >function and know that there will be nothing done in these three >circumstances. >It's not without danger as RCM has pointed out, but I often choose to >live >with the risk. *Deciding* to live with the risk is perfectly legitimate. There is no way to eliminate all risk. Thus we must choose the risks we live with. But it is important that the risks be understood. > >Of course, it could also be written as: > >void AFunction(...) >{ > if not (SomeCondition) and > not (AnotherCondition) and > not (AThirdCondition) then > > // now do the real work... > > endif > return; >} Which is usually how I would choose to write it. (Active voice instead of passive voice. ;^) Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Patrick Logan 1998-09-06 0:00 ` Charles Hixson 1 sibling, 1 reply; 510+ messages in thread From: sureshvv @ 1998-09-03 0:00 UTC (permalink / raw) In article <6sknla$7so$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Robert Oliver wrote in message <35EDAC92.538A@hfl.tc.faa.gov>... > > > > >I am not arguing against all use of multiple returns in a procedure or > >function. I often write a function like this: > > > >void AFunction(...) > >{ > > if (SomeCondition) return; > > if (AnotherCondition) return; > > if (AThirdCondition) return; > > > > // now do the real work... > > > > return; > >} > > <portions elided> > > > >Of course, it could also be written as: > > > >void AFunction(...) > >{ > > if not (SomeCondition) and > > not (AnotherCondition) and > > not (AThirdCondition) then > > > > // now do the real work... > > > > endif > > return; > >} > > Which is usually how I would choose to write it. (Active voice instead of > passive voice. ;^) > Note that this has added a level of nesting to the real work (tm). Now also consider the case where you might have to return different error conditions to the calling routine. And/Or you have to output some message to a log file for each of the conditions. Will the answer still be the same? suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` sureshvv @ 1998-09-03 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object sureshvv@hotmail.com wrote: : > >void AFunction(...) : > >{ : > > if not (SomeCondition) and : > > not (AnotherCondition) and : > > not (AThirdCondition) then : > > : > > // now do the real work... : > > : > > endif : > > return; : > >} : Note that this has added a level of nesting to the real work (tm). Now also : consider the case where you might have to return different error conditions : to the calling routine. And/Or you have to output some message to a log file : for each of the conditions. If I have to do something like this, I usually put the body in its own method that does not have these checks at all, something like this... void AFunction(...) { if (someCondition) { throw ... } else if (anotherCondition) { throw ... } else if (aThirdCondition) { throw ... } else if (...) { throw ... } else { AFunctionWithGoodStanding(...) } } void AFunctionWithGoodStanding(...) { ...do the real stuff... } Then it is clear the first function's purpose is to get all the issues out of the way and the second function's purpose is to do the work. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` sureshvv @ 1998-09-06 0:00 ` Charles Hixson 1998-09-07 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) I feel it important to call attention to the fact that the returns are occuring BEFORE and non-temporary effects happen. There are different things that multiple returns can be. I feel this form to be BENEFICIAL, and analogous to the pre-conditions of Eiffel. OTOH, a return from within the body of "now do the real work" would be an ill-structured added return. The problem is that we are calling different program structures by the same name. And our languages don't support the early-return with a different syntax, so it is very easy to confuse them. Robert Martin wrote: > > Robert Oliver wrote in message <35EDAC92.538A@hfl.tc.faa.gov>... > > > > >I am not arguing against all use of multiple returns in a procedure or > >function. I often write a function like this: > > > >void AFunction(...) > >{ > > if (SomeCondition) return; > > if (AnotherCondition) return; > > if (AThirdCondition) return; > > > > // now do the real work... > > > > return; > >} > > > >I think this makes sense when AFunction is called from many places and > >the > >conditions need to be tested each time. I can look at the beginning of > >the > >function and know that there will be nothing done in these three > >circumstances. > >It's not without danger as RCM has pointed out, but I often choose to > >live > >with the risk. > > *Deciding* to live with the risk is perfectly legitimate. There is no way > to eliminate all risk. Thus we must choose the risks we live with. But it > is important that the risks be understood. > > > >Of course, it could also be written as: > > > >void AFunction(...) > >{ > > if not (SomeCondition) and > > not (AnotherCondition) and > > not (AThirdCondition) then > > > > // now do the real work... > > > > endif > > return; > >} > > Which is usually how I would choose to write it. (Active voice instead of > passive voice. ;^) > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-07 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-07 0:00 UTC (permalink / raw) > There are different things that multiple returns can be. I feel this > form to be BENEFICIAL, and analogous to the pre-conditions of Eiffel. Eiffel preconditions never alter the control flow. Therefore, I don't think these are analogous. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` Jeffrey C. Dege 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-03 0:00 UTC (permalink / raw) Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: >Ell wrote: >> >> Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: >> : >> : Ell wrote: >> :> >> :> The assertion that "single entry, single exit" is a required, or even >> :> desirable, maxim of structured programming is a myth. >> :> >> :> No one (including RCM) can show that this maxim is in fact a coding >> :> heuristic put forward by any of the founders of the structured >> :> paradigm. [Check past posts in this thread.] >> : Edward Yourdan, in his book Techniques of Program Structure and Design >> : discusses this article: >> >> : C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages >> : with Only two Formation Rules", Communications of the ACM, May 19[6]6, >> : pages 366-371. >> >> : (Is this not *the* foundational article for structured programming?) It was Dijkstra and Dahle who where considered to be the founders of the structured paradigm--especially Dijkstra. See "Art of Literate Programming" by Knuth (CLSC publishers) page 72 >> : "According to Bohm and Jacopini, we need three basic building blocks in >> : order to construct a program: >> >> : 1. A process box. >> : 2. A generalized loop mechanism. >> : 3. A binary-decision mechanism. >> : >> : The process box, shown in Fig. 4.1, may be thought of as a single >> : computational statement (or machine language instruction) *or as any >> : other proper conputational sequence with only one entry and one exit* - >> : such as a subtoutine." "single entry, single exit" is mentioned here, but again it was Dijkstra and Dahle who where considered to be founders of the structured paradigm--especially Dijkstra. >> Where is the proof that this underlays the structured paradigm and an >> assertion that something is "proper" doesn't make it so. What structured >> programming avoided was unstructured flow control. It encouraged the use >> of procedure/routine calls over 'goto'. "single entry and single exit" is an inflexible, inadequate attempt to express the more comprehensive idea of the structured paradigm that we should avoid unstructured flow conrrol. And that wasn't even the only key or main idea of the structured paradigm according to Dijkstra as quoted in "Art of Literate Programming". Dijkstra said the first thing he thought of when "structured programming" was mentioned was *"abstraction"*. >> Along with entry into a procedure >> via a call, the use of 'return' is structured flow control; 'return' can >> only go back to the calling procedure, unlike 'goto' which can branch to a >> label anywhere. >It's interesting that you use the fact that return always returns the >program to a single exit point (the calling procedure) as an argument that this >technique is structured. Indeed, it is at the procedure level. Right, that's the point about avoiding unstructured flow control. >curious. Would you allow goto's if they could not leave the scope of >the procedure? Probably not.) In a post a month ago, I said that I would probably never use 'goto' to go out of a procedure (if that's possible in Basic, or C) Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ell @ 1998-09-03 0:00 ` Jeffrey C. Dege 0 siblings, 0 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-03 0:00 UTC (permalink / raw) On Thu, 03 Sep 1998 01:32:21 GMT, Ell <ell@access.digex.net> wrote: >Robert Oliver <oliverb@hfl.tc.faa.gov> wrote: > >>> : Edward Yourdan, in his book Techniques of Program Structure and Design >>> : discusses this article: >>> >>> : C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages >>> : with Only two Formation Rules", Communications of the ACM, May 19[6]6, >>> : pages 366-371. >>> >>> : (Is this not *the* foundational article for structured programming?) > >It was Dijkstra and Dahle who where considered to be the founders of >the structured paradigm--especially Dijkstra. See "Art of Literate >Programming" by Knuth (CLSC publishers) page 72 Dijkstra and Dahle may have introduced the the formalism of structured programming, but it is widely recognized that they were inspired by Bohm and Jacopini's research. Dijkstra's 1968 letter to the ACM, "GO TO Statements Considered Harmful", has only two references: 1. Wirth, Niklaus, and Hoare C. A. R. A contribution to the development of ALGOL. Comm. ACM 9 (June 1966), 413-432. 2. Bohm, Corrado, and Jacopini Guiseppe. Flow diagrams, Turing machines and languages with only two formation rules. Comm. ACM 9 (May 1966), 366-371. -- The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence. -- Edsger W. Dijkstra, SIGPLAN Notices, Volume 17, Number 5 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` john-clonts 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Matthew Heaney 2 siblings, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) Robert Oliver <oliverb@hfl.tc.faa.gov> writes: > Edward Yourdan, in his book Techniques of Program Structure and Design > discusses this article: > > C. Bohm and G. Jacopini, "Flow Diagrams, Turing Machines, and Languages > with Only two Formation Rules", Communications of the ACM, May 1996, > pages 366-371. The year was 1966. > (Is this not *the* foundational article for structured programming?) Be aware that Bohm and Jacopini showed only what the minimal set of control flow primitive are. But don't take this to mean that those are the only control flow statements you should use. Control flow constructs in a language should be chosen for their expressive power. What's the most natural way to do the iteration for a certain class of problems? Ed Yourdon edited a pair of books that have all the major papers on the goto issue, including those by George Miller, Bohm & Jacopini, and Knuth. Classics in Software Engineering Writings of the Revolution ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Oliver @ 1998-09-05 0:00 ` Ray Gardner 1998-09-05 0:00 ` Matthew Heaney [not found] ` <m31zpq4pim.fsf@mheaney.ni.ne <m3af36wtwh.fsf@mheaney.ni.net> 2 siblings, 1 reply; 510+ messages in thread From: Ray Gardner @ 1998-09-05 0:00 UTC (permalink / raw) Ell wrote: > >>For example, there's a pernicious myth that exiting (or returning) from > >>the middle of a loop is bad, and that the only proper way to write a > >>loop is to state the termination condition explicitly, as a predicate > >>appearing at the top of the loop. > > >Yes. That pernicious myth is called "structured programming". > > Please cite even just a single structured programming text, or founder > where what you say here was asserted. And later Ell wrote: > The assertion that "single entry, single exit" is a required, or even > desirable, maxim of structured programming is a myth. > > No one (including RCM) can show that this maxim is in fact a coding > heuristic put forward by any of the founders of the structured > paradigm. [Check past posts in this thread.] RCM had responded with a direct quote from Dijkstra, but Ell rejected it without understanding it. And rejected it again after RCM explained it. To recap, in Dijkstra's Notes on Structured Programming in the classic _Structured Programming_ (1972), EWD referred to the single-entry/single-exit property of the flowcharts of the if- then-else, case-of, while-do, and repeat-until control structures. Ell apparently thought EWD was talking about how flowcharts should be represented on a page. EWD was actually using the flowcharts as a graphical aid to make a point about program topology. To support this interpretation, I'll just quote this from the same source, p. 20: "... restricting ourselves to the three mentioned types of decomposition lead to flowcharts of a restricted topology compared with the flowcharts one can make when arrows can be drawn from any block leading into any other." EWD then goes on at length to explain why such a topology is desireable. Ell, you might consider this: in the entire monograph EWD never mentions goto, exit, break, return or any other change in the flow of control outside of the selection and repetition statements mentioned above. And he certainly had no such other modes of flow control in mind when he wrote his "GOTO considered harmful" letter; he was accustomed to Algol, which has no exit/break/return or similar statements. (Also consider that goto-less programming in Pascal has the same restriction, since Pascal lacks exit/break/return etc.) Ell, remember that you asked for a cite from "even a single structured programming text, or founder" to support single- entry/single-exit. Okay. Hard to say who you can consider "a" founder other than "the" founder, EWD. But consider Niklaus Wirth: "For the intellectual manageability, it is crucial that the constituent operations at each level of abstraction are connected according to sufficiently simple, well understood _program schemas_, and that each operation is described as a piece of program with _one starting point_ and a _single terminating point_." [Emphases were italics in the original.] "On the Composition of Well-Structured Programs", N. Wirth, in ACM Computing Surveys, December 1974 (Special Issue on Programming), p.249. How about this: "A _proper program_ is a program with a control structure that (1.) has a single entry line and a single exit line, and (2.) for each node, has a path through that node from the entry line to the exit line." _Structured Programming: Theory and Practice, R.C. Linger, H.D. Mills, B.I. Witt, Addison- Wesley, 1979, p. 94. (Ell has already commented on a similar use of the word "proper". Ell, you should understand that the word is being used here in a technical fashion as part of a *definition*, similar to the use of "well-formed formula" in mathematical logic. And, anticipating that you'll claim that this has nothing to do with structured programming per se, I'll point out that the entire book is about programming via the use of "proper programs" as defined above.) Since you mentioned structured COBOL, I'll mention this: "GO TO statements are not allowed. The rationale here is to force programmers to think ahead and use _only_ 1-in, 1-out control structures." ... "STOP RUN may only occur as the last statement of the main procedure of a program. EXIT PROGRAM may only occur as the last paragraph of the main procedure of a subprogram. The rationale here is to make the logical exit of a program identical to the lexical end of its main procedure." _COBOL With Style (Programming Proverbs)_, L.J. Chmura, H.F. Ledgard, Hayden, 1976. A book on structured programming in COBOL. Many other writers have discussed structured programming in terms of single-entry/single-exit control structures, often without using those terms explicitly. But what else could they mean when they develop a programming style that uses only sequence, if-then-else, while-do, repeat-until, and sometimes case-of, without ever mentioning or using goto, return, break, exit, continue, or any other discontinuity of control? For an even heavier dose of Dijkstra, try his _A Discipline of Programming_ (Prentice-Hall, 1976) where he develops a fairly complete theory of proof-oriented _nondeterministic_ procedural programming semantics using only assignment and "guarded commands" for conditional and repetitive (if ... fi and do ... od) statements. He never explicitly mentions "single- entry/single-exit", but it's clear from his exposition that there is no other form of flow control in his system. You mentioned (twice) page 72 of Knuth's _Literate Programming_ (not _The Art of ... as you've twice mis-cited it, and the publisher is CSLI, not CLSC or CLCS as you've twice misnamed them). This page is part of a reprint of Knuth's classic paper "Structured Programming with go to Statements", originally in ACM Computing Surveys, December 1974. You might consider what Knuth said on p. 18 of your book: "It is impossible to read the recent book _Structured Programming_ [Dahl (not Dahle), Dijkstra, and Hoare] without having it change your life." And then take RCM's advice and read the book. Perhaps that's what it'll take to get you to believe that Dijkstra was advocating exactly what RCM said he was. (You won't do it because you might find RCM is right.) BTW, while it's true that Dijkstra considered abstraction to be central to his notion of structured programming, page 72 of Knuth's book nowhere says "It was Dijkstra who thinks of *abstraction* when someone mentions 'structured programming'." It does quote Dijkstra as saying that when he's dealing with one level of abstraction, it occupies 90% of his attention while the rest is kept in mind in the background. Yes, abstraction is key to Dijkstra's notion of structured programming. But so is the use of the limited set of control structures mentioned above, and so is his oft-mentioned "separation of concerns". I've been doing this long enough (30 years) to remember when this stuff was new, and I have many of the original books and papers in my library. I also had the personal experience of bringing structured programming into a COBOL spaghetti shop in 1974. So I do know a little about this stuff. I'm not saying structured programming is only about control structures. And I'm not saying that no one has tried "enhancing" the original idea of structured programming with additional control structures. Wulf, Zahn, Dahl, Knuth and others have suggested other forms of loops. But the original idea, as expounded by Dijkstra, Mills, Wirth, Ledgard, and others does indeed restrict you to single- entry/single-exit control structures, and they don't exit loops in the middle. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Ray Gardner @ 1998-09-05 0:00 ` Matthew Heaney 1998-09-07 0:00 ` Ray Gardner 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-05 0:00 UTC (permalink / raw) rgardner@nyx.net (Ray Gardner) writes: > RCM had responded with a direct quote from Dijkstra, but Ell But the > original idea, as expounded by Dijkstra, Mills, Wirth, Ledgard, and > others does indeed restrict you to single- entry/single-exit control > structures, and they don't exit loops in the middle. Oh! You were doing well up to that last line. Read about the dowhiledo structure, in section 3.3.3, Iteration Structures, of Structured Programming, by Linger, Mills, and Witt. A list of prime programs also appears on p115, and the one at the bottom is a dowhiledo loop. He explicates the meaning of that loop structure on p116-7. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Matthew Heaney @ 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Ell 1998-10-09 0:00 ` Matthew Heaney 0 siblings, 2 replies; 510+ messages in thread From: Ray Gardner @ 1998-09-07 0:00 UTC (permalink / raw) Matthew Heaney <matthew_heaney@acm.org> wrote: > rgardner@nyx.net (Ray Gardner) writes: > > > RCM had responded with a direct quote from Dijkstra, but Ell But the > > original idea, as expounded by Dijkstra, Mills, Wirth, Ledgard, and > > others does indeed restrict you to single- entry/single-exit control > > structures, and they don't exit loops in the middle. > > Oh! You were doing well up to that last line. Read about the > dowhiledo structure, in section 3.3.3, Iteration Structures, of > Structured Programming, by Linger, Mills, and Witt. > > A list of prime programs also appears on p115, and the one at the bottom > is a dowhiledo loop. He explicates the meaning of that loop structure > on p116-7. Thanks for the correction, Matt. Of course my main point was that the founder(s) of SP did limit the control structures to single-entry / single-exit structures, and that still stands. The middle-exit loop (with single exit) is still such a structure whether Dijkstra used it or not. (He didn't). I realize this subthread about what SP is or isn't started with your post supporting a middle-exit loop and citing the Soloway et al. study from CACM 11/83. I was mainly replying to Ell's disbelief that SP concerns se/se structures only. The Soloway study was interesting. RCM asked you about the study so I assume he doesn't have it ready at hand, so I'll answer a couple of his questions about it. The study was a based on a trivial programming assignment given to students. 116 were novices in their first Pascal class, 112 were "intermediates" in their second programming class, and 52 were "advanced" (juniors and seniors in systems programming and programming methodology classes). The assigment was to write a Pascal program to read a list of numbers terminated with a sentinel value of 99999 and compute the average (excluding the sentinel value). Programs were considered correct even if they didn't check against division by 0 (i.e. only a sentinel value was read), so a correct program could be written about 15 or 16 lines of code. Syntax errors were ignored. Half the subjects had to use standard Pascal (but without goto apparently) and the others used a modified Pascal (Pascal-L) with a loop...leave...again structure in lieu of all other loop constructs. Before writing any code (and before being told about the modified Pascal) all subjects were asked to write a "plan" in any language other than a programming language. The plans were studied to see if they "naturally" specified a "process/read" strategy or a "read/process" strategy. Most, including advanced, wrote a "read/process" approach, though a third of the advanced chose "process/read" (I'd guess because they expected to write in a Pascal style), and about 2/3 of the novices had plans too vague to be classified. Here, process/read means the loop processes data before reading the next data item, meaning there is a "priming" read before entering the loop. This is seen as appropriate for straight Pascal. read/process means the loop reads, tests for sentinel, and then processes the data. Straight Pascal needs to use flags, duplicate conditions, etc. to get the correct behavior, but read/process is considered appropriate for Pascal-L because it can be done with no duplication of the read statement. Interestingly, the few novices who chose process/read with straight Pascal all got the program right, none of the read/process novices did. Of the novices who chose read/process for Pascal-L (all but 1), only about half got it right. In the intermediate group on straight Pascal, 18 chose process/read and 16 of those got it right, while 21 chose read/process and only 3 got it right. On Pascal-L, 43 chose read/process and 34 were correct, while 7 tried process/read but only 2 got it right. The advanced Pascal group showed 16 out of 18 correct with process/read, with only 5 trying read/process and only 2 of those getting it right. With Pascal-L, 23 out of 24 choosing read/process were correct, as were the only 2 who used process/read. Soloway et al. conclude from these numbers that the mid-exit loop strategy leads to more correct results. I'm no statistician, but I'm not entirely convinced. The first paragraph of the paper suggests they were really interested in making programming easier for non-programmers. It's true that more subjects got it right in each category with Pascal-L than with straight Pascal. But I also note that more advanced subjects were more likely to choose the "appropriate" strategy for the language. I figure they'd learned (in class or on their own) about the "priming read" approach, which is key to getting it right without a mid-exit loop structure. I wonder how much better all the Pascal groups would have done if they'd been properly instructed on this. (I assume they weren't, or more of the novices and intermediates would have chosen the process/read approach for Pascal.) What's really appalling is how many students got this simple thing wrong. The novices were 3/4 through their first programming course and "had been taught about and had experience with the while loop and the other two looping constructs"; the intermediates were 2/3 through their second course. I'm not sure if this says more about the students or the school, though I'd guess many of the novices and intermediates included those lacked the aptitude for the work and later quit programming. The article mentions another "series of studies by Sheppard et al." regarding the readability effects of mid-exit loops on professional programmers. It's in Computer, Dec. 1979. Unfortunately I only joined IEEE-CS in 1984, so I don't have that one at hand. Perhaps someone in these newsgroups who does have it can summarize? It might be more interesting than the Soloway article. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ray Gardner @ 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Patrick Doyle ` (3 more replies) 1998-10-09 0:00 ` Matthew Heaney 1 sibling, 4 replies; 510+ messages in thread From: Ell @ 1998-09-07 0:00 UTC (permalink / raw) rgardner@nyx.net (Ray Gardner) wrote: >.... Of course my main point was >that the founder(s) of SP did limit the control structures to >single-entry / single-exit structures, and that still stands. And your proof is what? Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell @ 1998-09-07 0:00 ` Patrick Doyle 1998-09-07 0:00 ` dewarr 1998-09-07 0:00 ` Ell ` (2 subsequent siblings) 3 siblings, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-09-07 0:00 UTC (permalink / raw) In article <35f34bbd.7903825@news.erols.com>, Ell <ell@access.digex.net> wrote: >rgardner@nyx.net (Ray Gardner) wrote: > >>.... Of course my main point was >>that the founder(s) of SP did limit the control structures to >>single-entry / single-exit structures, and that still stands. > >And your proof is what? Can you prove they recommended using other structures? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Patrick Doyle @ 1998-09-07 0:00 ` dewarr 0 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-07 0:00 UTC (permalink / raw) In article <Eyx023.IC8@ecf.toronto.edu>, doylep@ecf.toronto.edu (Patrick Doyle) wrote: > In article <35f34bbd.7903825@news.erols.com>, Ell <ell@access.digex.net> wrote: > >rgardner@nyx.net (Ray Gardner) wrote: > > > >>.... Of course my main point was > >>that the founder(s) of SP did limit the control structures to > >>single-entry / single-exit structures, and that still stands. > > > >And your proof is what? > > Can you prove they recommended using other structures? > > -PD > Well it is not clear who you think "they" are (the "founders" of structured programming). Certainly Wirth is happy to use a goto in Pascal where it makes sense (see the code for example for heap sort in his algorithms book). Similarly Knuth has pointed out the value of midloop exits in some cases ... Actually I think the real point here is that the "founders" tend to be a lot less dogmatic than their followers :-) > -- > -- > Patrick Doyle > doylep@ecf.toronto.edu > -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Patrick Doyle @ 1998-09-07 0:00 ` Ell 1998-09-09 0:00 ` Adrian P. Morgan 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` dewarr 3 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-07 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >rgardner@nyx.net (Ray Gardner) wrote: > >>.... Of course my main point was >>that the founder(s) of SP did limit the control structures to >>single-entry / single-exit structures, and that still stands. >And your proof is what? And either way I agree with an earlier writer and point of view that whatever Dijkstra, Dahle and Hoare may or may not have said about exits, it isn't gospel. Intelligent people can and should latch on to the spirit and essence of what they were saying. As I and many others see it the use of multiple exits is can be consistent with the structured programming goal of being able to prove, and improve the maintainability of, code. In fact multiple exits, in the opinion of many if not most programmers, makes some code even more maintainable than using a single exit. And apparently Donald Knuth concurs that provability is not in conflict with multiple exits. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell @ 1998-09-09 0:00 ` Adrian P. Morgan 1998-09-09 0:00 ` Charles Hixson 0 siblings, 1 reply; 510+ messages in thread From: Adrian P. Morgan @ 1998-09-09 0:00 UTC (permalink / raw) Ell wrote: ^ | And either way I agree with an earlier writer and point of view that | whatever Dijkstra, Dahle and Hoare may or may not have said about | exits, it isn't gospel. Intelligent people can and should latch on to | the spirit and essence of what they were saying. v Couldn't we say, perhaps, that "structuredness" is a continuum, a measure of the tightness of control over jumps in a program, ranging from totally uncivilised garbage at the "Not Structured" level, all the way up to strict SE/SE at the "Very Structured" level? The unqualified term "Structured" not only *is* but *should* be somewhat ambiguous (since oversimplifying these issues doesn't help anyone). That way, everyone could be right. Which would be nice. -- Here and there I like to preserve a few islands of sanity within the vast sea of absurdity which is my mind. After all, you can't survive as an eight foot tall flesh eating dragon if you've got no concept of reality. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Adrian P. Morgan @ 1998-09-09 0:00 ` Charles Hixson 1998-09-10 0:00 ` mfinney 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-09 0:00 UTC (permalink / raw) Adrian P. Morgan wrote: ... > Couldn't we say, perhaps, that "structuredness" is a > continuum, a measure of the tightness of control over > jumps in a program, ranging from totally uncivilised > garbage at the "Not Structured" level, all the way up to > strict SE/SE at the "Very Structured" level? The > unqualified term "Structured" not only *is* but *should* > be somewhat ambiguous (since oversimplifying these issues > doesn't help anyone). > > That way, everyone could be right. Which would be nice. > > -- > Here and there I like to preserve a few islands of sanity > within the vast sea of absurdity which is my mind. > After all, you can't survive as an eight foot tall > flesh eating dragon if you've got no concept of reality. The problem is that with the limited range of structures comes a limited range of errors that can occur. The se/se school is limiting a particular set of errors: If you use their approach you WILL NOT make the errors that they have excluded. On the other hand, advocates of, e.g., early returns, feel that by testing for errors early you can remove complications from the code, and thus remove a DIFFERENT source of errors. The two are incompatible. You can choose which you consider more important, but you only get to pick one. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Charles Hixson @ 1998-09-10 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-1609981736190001@dialup47.tlh.talstar.com> 0 siblings, 1 reply; 510+ messages in thread From: mfinney @ 1998-09-10 0:00 UTC (permalink / raw) In <35F70F41.67AC4347@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> writes: >The problem is that with the limited range of structures comes a limited >range of errors that can occur. The se/se school is limiting a >particular set of errors: If you use their approach you WILL NOT make >the errors that they have excluded. On the other hand, advocates of, >e.g., early returns, feel that by testing for errors early you can >remove complications from the code, and thus remove a DIFFERENT source >of errors. The two are incompatible. You can choose which you consider >more important, but you only get to pick one. The use of non se-se control structures to match the problem's "structure" is really an important concept. The use se-se did originate to reduce the number of errors, and as a first attempt, was a very good thing. The problem is that the first attempt at anything is almost never the "correct" answer. I believe that what we need to do is to study many, many programs and find out what the "natural" structure of the programs are (in the small scale). Then we need to design control structures to match each of the patterns that we find. There are, of course, an infinite number of patterns but we can limit ourselves to those which we find repeated on a somewhat regular basis. Many authors have looked at control structure variations such as the n 1/2 loop problem. There are others such as exit from a binary tree insert which has three different exit conditions with different actions occuring at each exit (add left, found it, add right). Knuth introduced situation labels to assist with problems like this. I have made a study of many control structures for years as a hobby and virtually all of them are tree-structured, but they are not structured. It is clear that many people feel that the original se-se structures are just too limiting, but they still want "structure". When considering control structure improvements, the right place to put the line seems to be tree- structured instead of structured. It gives just the right amount of flexability and still maintains a regular program structure. As far as "provability" is concerned, any of the "regular" control structures can be constructed from the se-se control structures with the possible addition of extra flags and tests. That means that if se-se is provable then these additional control structures are also provable -- and probably in a much more direct manner. In a different post, I have a minimum set of control structures from which all tree-structured code can be built. I'm sure that nice properties for those can be found which assist proving program correctness. However, proving program correctness is kind of a moot point at the moment because nobody can do it for any kind of a sizeable program. I have hopes that the advances in theorem proving combined with OO built using preconditions/invariants/postconditions from the ground up could give major advances in proving program correctness. The use of program transformations which start with a predicate and then use transformations which provably retain correctness to convert the predicate, step by step, to an executable program can also assist in that area. I feel that combining all of these things together (better control structures, OO grounded with invariants and program transformations) can result in large programs which are provably correct -- but not by hand. As always, the tedious details are where computers are useful. Even Robert agrees that the use of a particular se-se control structure should be based on costs and benefits. Of course, the major problem with that is that nobody knows what the costs and benefits really are when compared to slight variations such as exit from the middle of a loop. We all believe that there are significant benefits from the use of structured programming compared to the original unstructured programming. But there is no evidence that I have seen that the original structured programming is better or even as good as some of the "improvements" in control structures that have been invented over the last 20 years or so. I personally believe that these control structures *do* improve things by reducing errors both in coding and in maintenance because they improve the programmer's ability to reason about the program in a "natural" manner. However, that is just my opinion and is only backed up by my experience (which is around 28 years or so, perhaps not quite as long as Robert's, but hopefully just as good <g>). I do know that I apply the principles above as much as possible (and would do a lot more if I had the computer support I need) and the results have been very good -- but perhaps the results would be just as good anyway. There you get the question of the programmer vs the process. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-1609981736190001@dialup47.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-1609981736190001@dialup47.tlh.talstar.com> @ 1998-09-17 0:00 ` mfinney 0 siblings, 0 replies; 510+ messages in thread From: mfinney @ 1998-09-17 0:00 UTC (permalink / raw) In <gio+van+no+ni+8-1609981736190001@dialup47.tlh.talstar.com>, gio+van+no+ni+8@tal+star+spam.com (Giovanni 8) writes: >> Michael Lee Finney wrote: >> I have made a study of many control structures for years >> as a hobby and virtually all of them are tree-structured, >> but they are not structured. > >Virtually all of them are tree-structured but not structured? > >Virtually all of them are 4-wheeled vehicles but not wheeled >vehicles? > >Since tree-structures are a sub-set of all possible structures, >then they must be structures. You misunderstand. You are applying general analogy to the situation, but it is invalid because these terms have specific technical meanings. Code which is structured only allows a single entry, single exit with some possible argument as to exactly which control structures are valid. Traditionalists will argue, for example, that a mid-loop exit is not acceptable and others will disagree. Code which is tree-structured essentially allows any control structure which does not contain a jump into the middle of a block. Or, another way of expressing the concept, you may exit or repeat any block any number of times at any depth of block nesting. Neither structured code nor tree-structured code allows unrestricted use of the GOTO statement. Under these definitions, all structured code is tree-structured, but not vice- versa. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Patrick Doyle 1998-09-07 0:00 ` Ell @ 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` dewarr 3 siblings, 1 reply; 510+ messages in thread From: Ray Gardner @ 1998-09-07 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: > rgardner@nyx.net (Ray Gardner) wrote: > > >.... Of course my main point was > >that the founder(s) of SP did limit the control structures to > >single-entry / single-exit structures, and that still stands. > > And your proof is what? > > Elliott Ell, the "proof" is in my post of 5 Sept 1998, more-or-less directed to you personally, which was the result of more than a couple of hours of research for *your* benefit. Not that I expected any thanks. But since you seem to have missed it, I'll waste a little bandwidth and repost. (I could just give you a pointer to DejaNews, but you seem to never look up any cites people give you. Consider that you asked for a quote from a founder, RCM gives you a direct quote from *the* primary source, and you complain that it's out of print and "RCM knows it". Did you expect a primary source from 25 years ago to be in print? As another poster mentioned, that's what libraries are for. I don't know if you live near any major metropolitan areas, but a quick check shows two copies on the shelf in Denver and one in Boulder in libraries where they can be browsed by anyone.) So once more: [Repost of my message <905028596.876380@iris.nyx.net>] Ell wrote: > >>For example, there's a pernicious myth that exiting (or returning) from > >>the middle of a loop is bad, and that the only proper way to write a > >>loop is to state the termination condition explicitly, as a predicate > >>appearing at the top of the loop. > > >Yes. That pernicious myth is called "structured programming". > > Please cite even just a single structured programming text, or founder > where what you say here was asserted. And later Ell wrote: > The assertion that "single entry, single exit" is a required, or even > desirable, maxim of structured programming is a myth. > > No one (including RCM) can show that this maxim is in fact a coding > heuristic put forward by any of the founders of the structured > paradigm. [Check past posts in this thread.] RCM had responded with a direct quote from Dijkstra, but Ell rejected it without understanding it. And rejected it again after RCM explained it. To recap, in Dijkstra's Notes on Structured Programming in the classic _Structured Programming_ (1972), EWD referred to the single-entry/single-exit property of the flowcharts of the if- then-else, case-of, while-do, and repeat-until control structures. Ell apparently thought EWD was talking about how flowcharts should be represented on a page. EWD was actually using the flowcharts as a graphical aid to make a point about program topology. To support this interpretation, I'll just quote this from the same source, p. 20: "... restricting ourselves to the three mentioned types of decomposition lead to flowcharts of a restricted topology compared with the flowcharts one can make when arrows can be drawn from any block leading into any other." EWD then goes on at length to explain why such a topology is desireable. Ell, you might consider this: in the entire monograph EWD never mentions goto, exit, break, return or any other change in the flow of control outside of the selection and repetition statements mentioned above. And he certainly had no such other modes of flow control in mind when he wrote his "GOTO considered harmful" letter; he was accustomed to Algol, which has no exit/break/return or similar statements. (Also consider that goto-less programming in Pascal has the same restriction, since Pascal lacks exit/break/return etc.) Ell, remember that you asked for a cite from "even a single structured programming text, or founder" to support single- entry/single-exit. Okay. Hard to say who you can consider "a" founder other than "the" founder, EWD. But consider Niklaus Wirth: "For the intellectual manageability, it is crucial that the constituent operations at each level of abstraction are connected according to sufficiently simple, well understood _program schemas_, and that each operation is described as a piece of program with _one starting point_ and a _single terminating point_." [Emphases were italics in the original.] "On the Composition of Well-Structured Programs", N. Wirth, in ACM Computing Surveys, December 1974 (Special Issue on Programming), p.249. How about this: "A _proper program_ is a program with a control structure that (1.) has a single entry line and a single exit line, and (2.) for each node, has a path through that node from the entry line to the exit line." _Structured Programming: Theory and Practice, R.C. Linger, H.D. Mills, B.I. Witt, Addison- Wesley, 1979, p. 94. (Ell has already commented on a similar use of the word "proper". Ell, you should understand that the word is being used here in a technical fashion as part of a *definition*, similar to the use of "well-formed formula" in mathematical logic. And, anticipating that you'll claim that this has nothing to do with structured programming per se, I'll point out that the entire book is about programming via the use of "proper programs" as defined above.) Since you mentioned structured COBOL, I'll mention this: "GO TO statements are not allowed. The rationale here is to force programmers to think ahead and use _only_ 1-in, 1-out control structures." ... "STOP RUN may only occur as the last statement of the main procedure of a program. EXIT PROGRAM may only occur as the last paragraph of the main procedure of a subprogram. The rationale here is to make the logical exit of a program identical to the lexical end of its main procedure." _COBOL With Style (Programming Proverbs)_, L.J. Chmura, H.F. Ledgard, Hayden, 1976. A book on structured programming in COBOL. Many other writers have discussed structured programming in terms of single-entry/single-exit control structures, often without using those terms explicitly. But what else could they mean when they develop a programming style that uses only sequence, if-then-else, while-do, repeat-until, and sometimes case-of, without ever mentioning or using goto, return, break, exit, continue, or any other discontinuity of control? For an even heavier dose of Dijkstra, try his _A Discipline of Programming_ (Prentice-Hall, 1976) where he develops a fairly complete theory of proof-oriented _nondeterministic_ procedural programming semantics using only assignment and "guarded commands" for conditional and repetitive (if ... fi and do ... od) statements. He never explicitly mentions "single- entry/single-exit", but it's clear from his exposition that there is no other form of flow control in his system. You mentioned (twice) page 72 of Knuth's _Literate Programming_ (not _The Art of ... as you've twice mis-cited it, and the publisher is CSLI, not CLSC or CLCS as you've twice misnamed them). This page is part of a reprint of Knuth's classic paper "Structured Programming with go to Statements", originally in ACM Computing Surveys, December 1974. You might consider what Knuth said on p. 18 of your book: "It is impossible to read the recent book _Structured Programming_ [Dahl (not Dahle), Dijkstra, and Hoare] without having it change your life." And then take RCM's advice and read the book. Perhaps that's what it'll take to get you to believe that Dijkstra was advocating exactly what RCM said he was. (You won't do it because you might find RCM is right.) BTW, while it's true that Dijkstra considered abstraction to be central to his notion of structured programming, page 72 of Knuth's book nowhere says "It was Dijkstra who thinks of *abstraction* when someone mentions 'structured programming'." It does quote Dijkstra as saying that when he's dealing with one level of abstraction, it occupies 90% of his attention while the rest is kept in mind in the background. Yes, abstraction is key to Dijkstra's notion of structured programming. But so is the use of the limited set of control structures mentioned above, and so is his oft-mentioned "separation of concerns". I've been doing this long enough (30 years) to remember when this stuff was new, and I have many of the original books and papers in my library. I also had the personal experience of bringing structured programming into a COBOL spaghetti shop in 1974. So I do know a little about this stuff. I'm not saying structured programming is only about control structures. And I'm not saying that no one has tried "enhancing" the original idea of structured programming with additional control structures. Wulf, Zahn, Dahl, Knuth and others have suggested other forms of loops. But the original idea, as expounded by Dijkstra, Mills, Wirth, Ledgard, and others does indeed restrict you to single- entry/single-exit control structures, and they don't exit loops in the middle. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ray Gardner @ 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Ell 1998-09-09 0:00 ` Ray Gardner 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-09-07 0:00 UTC (permalink / raw) rgardner@nyx.net (Ray Gardner) wrote: [stuff elided] As I said that stuff is not proof to me they advocated se/se. To me their point was to encourage use disciplined navigation for proof and maintainability. Multiple returns can be disciplined navigation. But either way, I'm not a dogmatist. I'll unite with the spirit of maintainability and not rigid adherence to a practice when it clearly contradicts that. The main things I get from all of the structured writers is: a) Use procedure calls (with consequent return) b) Use procedural task abstraction (not isolated structures) Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell @ 1998-09-07 0:00 ` Ell 1998-09-09 0:00 ` Ray Gardner 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-09-07 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: >The main things I get from all of the structured writers is: > a) Use procedure calls (with consequent return) More generally: a) Use discipline in navigation (which has many forms) > b) Use procedural task abstraction (not isolated structures) > >Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Ell @ 1998-09-09 0:00 ` Ray Gardner 1 sibling, 0 replies; 510+ messages in thread From: Ray Gardner @ 1998-09-09 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) wrote: > rgardner@nyx.net (Ray Gardner) wrote: > > [stuff elided] > > As I said that stuff is not proof to me they advocated se/se. To me > their point was to encourage use disciplined navigation for proof and > maintainability. Multiple returns can be disciplined navigation. Ell, you have an interesting notion of rational discourse. You ask for a single cite of a structured programming text, or founder, asserting that loops should be single-entry / single- exit. You are then given not one but four or five cites by various posters. Now you say "that stuff is not proof to me they advocated se/se." I ask you: what you would consider "proof" to be, if not the direct quotes you asked for. Unfortunately, I don't think we can get Prof. Dijkstra to come on the NG and tell you himself. If he did, would you say that wasn't "proof to me" either? So really, what would be "proof" that they did? And why do you ask for cites when you know in advance that you aren't going to accept any? Why do you engage in discourse at all when you seem entirely impervious to reasoned persuasion/discussion/argument? Let me ask you this: Have you ever, in any newsgroup discussions, ever, ever had the good grace to say: "Hey, you're right and I was wrong."? If not, is it only because you were never wrong? Do you sometimes get the feeling that the entire world (or at least a newsgroup) is against you? Do you ever wonder why? Do you care? Do you like it that way? Why is your tone so often antagonistic, e.g. "And your proof is what?" For cat's sake, I posted because I thought you really wanted to know what the original writings on SP said. For all my effort digging up quotes, you blow me off with "As I said that stuff is not proof to me...". I've wondered sometimes at the antagonism between you and other posters. Now I've tasted it myself, I can understand why people find you a bit difficult to deal with. What are you like to work with? Do you get along better with your co-workers than you do with your newsgroup "colleagues", or do you take that sort of tone with them? "And your proof is what?" Why not "Sorry, I must have missed that post. Could you fill me in?" > But either way, I'm not a dogmatist. I'll unite with the spirit of > maintainability and not rigid adherence to a practice when it clearly > contradicts that. How pragmatic of you. :-) I've used break statements and multiple exits on occasion myself. (Even a slew of goto statements in a Duff's Device-like piece of data decompression code.) But the issue you originally disputed was what the original writings on SP said, and that's not a matter of opinion. Those writings exist, they've been quoted to you, and you adamantly discount that. Why? > The main things I get from all of the structured writers is: > a) Use procedure calls (with consequent return) > b) Use procedural task abstraction (not isolated structures) > > Elliott Which of the "structured writers" have you read? Dijkstra? Wirth? Hoare? Mills? Ledgard? Yourdon? Anybody (other than Knuth; we know you've got _Literate Programming_, including "SP with go to Statements")? Any book titles at hand? ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ell ` (2 preceding siblings ...) 1998-09-07 0:00 ` Ray Gardner @ 1998-09-07 0:00 ` dewarr 1998-09-09 0:00 ` Ray Gardner 3 siblings, 1 reply; 510+ messages in thread From: dewarr @ 1998-09-07 0:00 UTC (permalink / raw) In article <35f34bbd.7903825@news.erols.com>, ell@access.digex.net wrote: > rgardner@nyx.net (Ray Gardner) wrote: > > >.... Of course my main point was > >that the founder(s) of SP did limit the control structures to > >single-entry / single-exit structures, and that still stands. > > And your proof is what? > > Elliott > There is no "founder" of structured programming. The idea of structured programming is an old one, well known to anyone writing Algol-60 from very early on. Various people have produced specific rules concerning their idea of how to adapt this principle to particular programming languages (e.g. the "structured period" for ANSI-74 COBOL), but I would not say it is reasonable to regard anyone as "founding" structured programming. EWD's letter on gotos to the ACM was simply noting a general principle well known to any student algol-60 programmer for years. it is true that Fortran had made it much more difficult, though not impossible, for people to understand the basic idea of writing code that has a clear control flow structure. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` dewarr @ 1998-09-09 0:00 ` Ray Gardner 1998-09-11 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 510+ messages in thread From: Ray Gardner @ 1998-09-09 0:00 UTC (permalink / raw) dewarr@my-dejanews.com wrote: > In article <35f34bbd.7903825@news.erols.com>, > ell@access.digex.net wrote: > > rgardner@nyx.net (Ray Gardner) wrote: > > > > >.... Of course my main point was > > >that the founder(s) of SP did limit the control structures to > > >single-entry / single-exit structures, and that still stands. > > > > And your proof is what? > > > > Elliott > > > > There is no "founder" of structured programming. The > idea of structured programming is an old one, well known > to anyone writing Algol-60 from very early on. Various > people have produced specific rules concerning their > idea of how to adapt this principle to particular > programming languages (e.g. the "structured period" > for ANSI-74 COBOL), but I would not say it is reasonable > to regard anyone as "founding" structured programming. > > EWD's letter on gotos to the ACM was simply noting a > general principle well known to any student algol-60 > programmer for years. it is true that Fortran had > made it much more difficult, though not impossible, > for people to understand the basic idea of writing > code that has a clear control flow structure. Nice to get a response from you, Professor Dewar. (I assume that's you of Indirect Threaded Code / Spitbol / GNAT fame. Say, did Chuck Moore come up with ITC on his own or get it from your paper?) You're certainly better able than I to say what was or wasn't "well known to any student algol-60 programmer" for years before 1968. My collection of literature barely reaches back that far, so I don't have ready access to, say, the algorithms published in CACM in the mid-1960s. (I recall you lamenting the passing of that.) I do have one item at hand: the book _Programming Languages_ edited by F Genuys (Academic Press, 1968) edited by F Genuys, containing some material presented at the 1966 NATO Summer School in Programming. It includes the classic EWD paper on "Co-operating Sequential Processes" and a lengthy set of notes on "Compiler Writing Techniques" (L. Bolliet), and both contain a fair amount of Algol code, replete with plenty of goto statements. Given that EWD and Bolliet were well beyond the "student programmer" stage, I wonder if some of the ideas of SP were not as well-known as you recall. It is certainly true that EWD was not the first to advocate avoidance of goto statements; he said as much in his famous letter. Knuth (in Structured Programming with go to Statements) notes that EWD was "experimenting" with a goto-less Algol in the mid-60s, and quotes him saying that avoiding goto was "difficult ... we are so familiar with the jump that it requires some effort to forget it!". Knuth also finds Naur (editor of the Algol-60 report) questioning the goto in 1963, the earliest printed reference to avoiding goto Knuth found. I'm sure many good Algol (and other language) programmers used good judgment in refining and structuring their code in the 1960s. Does that mean they practiced SP? Or that SP had no founder? Seems to me that depends on how you define SP. Knuth says that Dijkstra's paper "Structured Programming" in _Software Engineering Techniques_ (Report on the 1969 Rome conference, NATO Science Committee) gave SP its name. Of course EWD's more widely known 1972 "Notes on Structured Programming" in the little black book is generally accepted as having really kicked off the SP "revolution". After that, there was a veritable flood of papers, letters, books and courses on SP. So maybe not all the ideas were EWD's alone or original with him; the emphasis on the limited use of control structures was not new, but what about the explicitness of the motivation for it? EWD was interested in developing programs that he could convince himself and others were correct. Maybe others had the same idea but didn't express it explicitly and convincingly. I think that if you agree that there is any such thing as SP, you really have to credit EWD with naming it and describing it. In fact, I would argue that those two papers _are_ the definition of SP. If ideas are just sort of "in the wind" for a few years, and then someone pulls them together and starts a whole field of people thinking about them, you don't consider him the founder? I do. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Ray Gardner @ 1998-09-11 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-09-11 0:00 UTC (permalink / raw) Robert Dewar said: > There is no "founder" of structured programming. The > idea of structured programming is an old one, well known > to anyone writing Algol-60 from very early on. Various > people have produced specific rules concerning their > idea of how to adapt this principle to particular > programming languages (e.g. the "structured period" > for ANSI-74 COBOL), but I would not say it is reasonable > to regard anyone as "founding" structured programming. Anecdotal, but worth noting. In the mid-sixties when the Algol-60 standard was being reviewed, Wirth came up with a "clean" proposal known as Algol-W. This lost to the very complex language which became Algol-68. But along the way there was an implementation of Algol-W created for the IBM 360 series, origianlly written I think in 1967. Much later 1976? I used this compiler to create a parser for a programming languages course. I found it extremely frustrating that the compiler printed a warning message "Is this goto really necessary?" for each of five gotos which implemented "panic mode" error recovery in the (recursive descent) parser. Today, of course I could use exceptions and appropriately located handlers to do the same thing. I think that the warning message was original equipment on the compiler, someone else may know. But more importantly, I saw this message for the first time in that parser, although I had compiled many programs using that compiler, both programs I had earlier written in Algol-60, and programs targeted to that compiler. So I know that when I programmed in Algol-60, I just plain did not use gotos. Not because I was taught that way--heck my first program was written in SOAP-IV for an IBM-650--but because Algol-60 discouraged gotos. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Ell @ 1998-10-09 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-10-09 0:00 UTC (permalink / raw) rgardner@nyx.net (Ray Gardner) writes: > Matthew Heaney <matthew_heaney@acm.org> wrote: > > rgardner@nyx.net (Ray Gardner) writes: > > > > > RCM had responded with a direct quote from Dijkstra, but Ell But the > > > original idea, as expounded by Dijkstra, Mills, Wirth, Ledgard, and > > > others does indeed restrict you to single- entry/single-exit control > > > structures, and they don't exit loops in the middle. > > > > Oh! You were doing well up to that last line. Read about the > > dowhiledo structure, in section 3.3.3, Iteration Structures, of > > Structured Programming, by Linger, Mills, and Witt. > > > Thanks for the correction, Matt. Of course my main point was > that the founder(s) of SP did limit the control structures to > single-entry / single-exit structures, and that still stands. > The middle-exit loop (with single exit) is still such a structure > whether Dijkstra used it or not. (He didn't). I still say we're splitting hairs, here. As Mills points out, the sequence of actions is: read N test N process N read N test N process N read N test N There are two ways to turn this into a loop. The most natural way (according to me, and Soloway et al) is like this: loop read N exit when N = 0 process N end loop This describes the enumerated list of actions above. The "classic" way is like this: read N while N /= 0 loop process N read N end loop I recently read Dijkstra's structured programming monograph. He explicates his philosophy in the section 7 (p. 16), titled "On Understanding Programs." His argument is that the static program text should be close to what happens dynamically, or, more simply, that programs be understandable. I argue that the middle-exit construction shown above satisfies Dijkstra's "restricted topology" in the sense that a reader of the (static) program text can easily understand what happens at run-time. His philosophy is "to make a program in such a way that its correctness [can] be proved without undue intellectual labor." [p. 39] Even though Dijkstra doesn't specifically mention the middle-exit construction in his monograph, I would argue that that construction satisfies his ultimate goal, which easy-to-understand, provably-correct programs. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <m31zpq4pim.fsf@mheaney.ni.ne <m3af36wtwh.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <m31zpq4pim.fsf@mheaney.ni.ne <m3af36wtwh.fsf@mheaney.ni.net> @ 1998-10-11 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-10-11 0:00 UTC (permalink / raw) In article <m3af36wtwh.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > >There are two ways to turn this into a loop. The most natural way >(according to me, and Soloway et al) is like this: > >loop > read N > exit when N = 0 > process N >end loop > >This describes the enumerated list of actions above. The "classic" way >is like this: > >read N > >while N /= 0 loop > process N > read N >end loop > > [...] > >I argue that the middle-exit construction shown above satisfies >Dijkstra's "restricted topology" in the sense that a reader of the >(static) program text can easily understand what happens at run-time. You make some good points. I'd just like to add that another desirable property of a loop is that all exit conditions are concentrated in one place. This, in combination with my own preference for the first form (above) rather than the second (which repeats the "read N" part), led me, a while back, to propose a loop syntax like this: until exit{end_of_file} loop read N if N = 0 then exit(end_of_file); process N end loop This has the advantages of your first method with the added benefit that the exit conditions are concentrated in one place, for easy comprehension. Clearly, this could already be done without special syntax simply by declaring a boolean flag and then, perhaps, relying on the compiler to optimize it away. However, it would be nice to be able to express to the compiler that you don't want a flag; you are simply trying to describe the flow of control through the loop. Another point is that it is important for the program to be able to discern the reason for loop termination. You should be able to say "if end_of_file" after executing the loop. However, again, this should not be translated into a boolean flag test. Again it's just describing the flow of control. What I'm trying to say is that we should be guaranteed that the compiler will turn this: loop A; if B then exit(condition1); C; until exit{condition1} or condition2 end loop if condition1 then D; end if E; ...into something like this: top: A if !B then goto after D goto bottom after: C if !condition2 then goto top bottom: E See what I'm getting at? The source code is not trying to express how the loop should be implemented. It's trying to express the flow control in a human-friendly form, and the programmer should be confident that it will be implemented in a machine-friendly form. After all, isn't that the point of a compiled language? :-) I know that most compilers do simple optimizations like this anyway. I'm just trying to differentiate between my mental image of exit conditions and simple boolean flags. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` mfinney 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` john-clonts 3 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) On Wed, 02 Sep 1998 05:01:34 GMT, mfinney@lynchburg.net wrote: >It is true that multiple exits arrive from different states Not at least significantly in this case. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` mfinney 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell ` (6 more replies) 1998-09-02 0:00 ` john-clonts 3 siblings, 7 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) mfinney@lynchburg.net wrote in message ... >And, as far as maintainability is concerned, I strictly use tree-structured >programming and have *never* found it to be a maintenance problem. >Sure, sometimes code transformations are required during maintenance, >but they are sometimes required during coding. So what? There is no >way to write code that never requires code transformations during >maintenance, and trying to do so just makes the code harder to >understand and ultimately increases maintenance cost. Far better is >to endevour to reach 0 bugs so that maintenance is never required. >Not easy, perhaps, but it is getting closer and closer every day. I >personally am running somewhere around 0.0001 and 0.0002 errors >per line of code -- prior to quality assurance getting the code. Reaching zero bugs may not have that big an impact on maintenance, since much of maintenance has to do with changes to the requirements. In any case, I note that in this thread nearly every article that advocates multiple exits evokes either readability, complexity, or naturalness as the justification. I contend that these are highly subjective things, that are not shared by all programmers alike. Indeed, what is readable, natural and simple to me, may be opaque and convoluted to you. I also contend that these issues are somewhat emotional, as evidenced by the terms such as "twist", "warp", "bend", "religious argument", etc. that have also been used in this thread. Finally, I contend that the factors in favor of using a single-entry/single-exit style are, on the other hand, quite concrete and demonstrable. It has been shown that adhering to a structured style facilitates both resource management and error processing. It has also been shown that a multiple exit style is vulnerable to redundant code, and code for recovery of state. So, it seems what we have here is "gut feelings" warring against empirical data. I can understand why the gut reaction is so strong; multiple exits are *eaiser* to write; and are, for some, easier to read. But those are not the only, or even the most important, criteria for evaluating the quality of a design. Maintainability is an issue too, and sometimes an overriding one. In the end, the decision to use a structured style is a tradeoff. There are benefits, and there are costs. And there are certainly situations in which the costs outweight the benefits (e.g. quick an dirty programs that have short lifetimes and require little maintenance during their life). It is also true, however, that for a very large set of circumstances, the benefits outweigh the costs. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` adam ` (3 more replies) 1998-09-02 0:00 ` adam ` (5 subsequent siblings) 6 siblings, 4 replies; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) On Wed, 2 Sep 1998 00:44:08 -0500, "Robert Martin" <rmartin@oma.com> wrote: >In any case, I note that in this thread nearly every article that advocates >multiple exits evokes either readability, complexity, or naturalness as the >justification. I contend that these are highly subjective things, This may be true, though I don't thinks so, but adherence to the dogma you made up about "single entry and single exit" doesn't make things clearer as most see it in this case. >Finally, I contend that the factors in favor of using a >single-entry/single-exit style are, on the other hand, quite concrete and >demonstrable. It has been shown that adhering to a structured style You have not shown at all that "single entry, single exit" is a general coding maxim of structured programming. And you should be ashamed of yourself for asserting that it is when after recently being challenged on it, you failed to prove that it was a general coding heuristic of structured programming. Why do you think you have a right to lie, and make false assertions contrary ti the facts? >facilitates both resource management and error processing. It has also >been shown that a multiple exit style is vulnerable to redundant code, >code for recovery of state. Not at all. It has been shown that in this and many other cases the difference in state at each exit point matters little. >So, it seems what we have here is "gut feelings" warring against empirical >data. It seems we have a masochistic task master adhering to his own unnecessary dogma trying to make others suffer as well by palming his dogma off as some kind of officialdom. Further, he can't prove it as officialdom and it wouldn't matter if it was because the appropriateness of all heuristics depends on specific concrete circumstances. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Patrick Doyle ` (2 subsequent siblings) 3 siblings, 0 replies; 510+ messages in thread From: adam @ 1998-09-02 0:00 UTC (permalink / raw) In article <35eeea9b.2174586@news.erols.com>, ell@access.digex.net wrote: > > This may be true, though I don't thinks so, but adherence to the dogma > you made up about "single entry and single exit" doesn't make things > clearer as most see it in this case. This is not a comment about whether "single entry and single exit" is desirable or not, but . . . the theory about single-entry and single-exit is something I've heard about since the early 1980's or so, which was *long* before I ever heard of Robert Martin. So I seriously doubt this is something he "made up". -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` adam @ 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Rick Smith 1998-09-02 0:00 ` Robert Martin 3 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-02 0:00 UTC (permalink / raw) In article <35eeea9b.2174586@news.erols.com>, Ell <ell@access.digex.net> wrote: > >You have not shown at all that "single entry, single exit" is a >general coding maxim of structured programming. So what do you think structured programming is? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Patrick Doyle @ 1998-09-02 0:00 ` Rick Smith 1998-09-02 0:00 ` Robert I. Eachus 1998-09-02 0:00 ` Robert Martin 3 siblings, 1 reply; 510+ messages in thread From: Rick Smith @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote in message <35eeea9b.2174586@news.erols.com>... >On Wed, 2 Sep 1998 00:44:08 -0500, "Robert Martin" <rmartin@oma.com> >wrote: > > >>In any case, I note that in this thread nearly every article that advocates >>multiple exits evokes either readability, complexity, or naturalness as the >>justification. I contend that these are highly subjective things, > >This may be true, though I don't thinks so, but adherence to the dogma >you made up about "single entry and single exit" doesn't make things >clearer as most see it in this case. > >>Finally, I contend that the factors in favor of using a >>single-entry/single-exit style are, on the other hand, quite concrete and >>demonstrable. It has been shown that adhering to a structured style > >You have not shown at all that "single entry, single exit" is a >general coding maxim of structured programming. > Edward Yourdon, "Techniques of Program Structure and Design", Prentice-Hall, 1975, pg 145. "In order to test the entire program, it is important to be able to define the behavior of submodules at the k-th level independently of the context in which they occur. This allows us to prove the correctness of the submodules at the (k + 1)th level independent of their context in the k-th step. This in turn strongly suggests that each submodule should be designed with a single entry point and a single exit; in turn, the entire program can be described as a set of nested modules, each of which has one entry and one exit." -----------, pg 148. "The theoretical basis of structured programming lends itself to implementation in many of the current programming languages. The rules are quite simple: All processing in the program must consist of straight-line statements (e.g., ordinary computational statements) or one of the following three control statements: " 1. Procedure calls, subroutine calls, function invocation -- any legal call to a closed subroutine with one entry and one exit. ... " 2. IF-THEN-ELSE statements nested to any depth. " 3. Some looping constructs. ..." ------------------------------- Rick Smith e-mail: < ricksmith@aiservices.com > ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Rick Smith @ 1998-09-02 0:00 ` Robert I. Eachus 1998-09-02 0:00 ` Patrick Logan 0 siblings, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-02 0:00 UTC (permalink / raw) In article <VFaH1.226$I%.386253@news1.atlantic.net> "Rick Smith" <ricksmith@aiservices.com> writes: > Edward Yourdon, "Techniques of Program Structure and Design", > Prentice-Hall, 1975, pg 145. > "In order to test the entire program... This in turn strongly > suggests that each submodule should be > designed with a single entry point and a single exit; in turn, the entire > program can be described as a set of nested modules, each of which > has one entry and one exit." ... > " 1. Procedure calls, subroutine calls, function invocation -- any legal > call to a closed subroutine with one entry and one exit. ... Nice quotes, but you have to understand them. In the sense of these quotes it is not possible to have multiple entries or exits to subroutines in most modern languages. The multiple exits in this sense are what you get with longjumps in C--the subroutine returns to a place other than the one it was called from. The multiple entries were common in PL/I, where depending on the name in the call you would enter the same code at different points. Typical in fact was to have multiple profiles where the procedure had three or four different parameter profiles, and you called the correct one for the parameters you wanted to supply. All subprograms in most modern languages are closed subroutines in the sense of this quote--they have a single entry, and the returns all go to the same place. (Absent exceptions, Unix signals, and the like.) To put it more bluntly, "You young whipersnappers have no idea what programming was like in the old days. The languages we used had no concept of a subroutine, we had to simulate it with gotos. And some idiots would write subroutines that didn't return to the place they were called from. Made debugging almost impossible, I tell you." Seriously, at the time that Yourdon wrote those words, there were languages that had call stacks and closed subroutines, but a lot of code was still written in versions of Fortran and Cobol where reentrant subroutines were not supported. In really was a very different world back then. In fact significantly more than half of the new code that year was written in assembler of one form or another, but mostly for the IBM 360. The most modern language use (extensively) in this country was PL/I, and that allowed multiple entry, multiple exit subroutines. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert I. Eachus @ 1998-09-02 0:00 ` Patrick Logan 1998-09-03 0:00 ` Robert I. Eachus 0 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert I. Eachus <eachus@spectre.mitre.org> wrote: : Nice quotes, but you have to understand them. In the sense of : these quotes it is not possible to have multiple entries or exits to : subroutines in most modern languages. The multiple exits in this : sense are what you get with longjumps in C--the subroutine returns to : a place other than the one it was called from. The C, C++, Java, Smalltalk, and Common Lisp languages all allow a form of a "return" statement to appear anywhere within a block of statements. Some of these languages have a form of GOTO that allow multiple exits from loops. I would think these languages make up "most modern languages". : The multiple entries were common in PL/I, where depending on the : name in the call you would enter the same code at different points. : Typical in fact was to have multiple profiles where the procedure : had three or four different parameter profiles, and you called the : correct one for the parameters you wanted to supply. I remember some FORTRAN code to do printed circuit board layout implementing all of its loops using GOTOs. Some of these loops had GOTOs at the top that jumped into the middle of the "loop"! : All subprograms in most modern languages are closed subroutines in : the sense of this quote--they have a single entry, and the returns all : go to the same place. (Absent exceptions, Unix signals, and the like.) This may or may not be the case. I'd have to read the entire text to judge for myself. In any case, I'd say the principle applies to subroutine exits as well as loop entrances and exits. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan @ 1998-09-03 0:00 ` Robert I. Eachus 0 siblings, 0 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-09-03 0:00 UTC (permalink / raw) In article <xChH1.6534$f01.4705828@news.teleport.com> Patrick Logan <plogan@user2.teleport.com> writes: > The C, C++, Java, Smalltalk, and Common Lisp languages all allow a > form of a "return" statement to appear anywhere within a block of > statements. Some of these languages have a form of GOTO that allow > multiple exits from loops. I would think these languages make up > "most modern languages". I could add more to the list, but you are missing the point. All of these languages have exceptional ways of returning to some other point in the code, but the return statements all go to the point of the call (unless you fiddle with the stack). In ancient days the return stack was under programmer control, so you often saw code that changed the return address. (I remember once wanting to throw one of those 4" thick binders of listings across the room because I finally tracked down an obscure bug to a pair of lines that read: RETURN = IS TBD C SET RETURN VALUE (Yes, FORTRAN 66 didn't hiccup. The careful leading I made that TBD an integer, and once I found it, that blasted comment gave no clue as to what that value should be changed to! Oh, yes, the space was non-significant, so that variable was named ISTBD.) > I remember some FORTRAN code to do printed circuit board layout > implementing all of its loops using GOTOs. Some of these loops had > GOTOs at the top that jumped into the middle of the "loop"! Of course, that was the "normal" way to do an N and a half loop in FORTRAN. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell ` (2 preceding siblings ...) 1998-09-02 0:00 ` Rick Smith @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Ell 3 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote in message <35eeea9b.2174586@news.erols.com>... >On Wed, 2 Sep 1998 00:44:08 -0500, "Robert Martin" <rmartin@oma.com> >wrote: > > >>In any case, I note that in this thread nearly every article that advocates >>multiple exits evokes either readability, complexity, or naturalness as the >>justification. I contend that these are highly subjective things, > >This may be true, though I don't thinks so, but adherence to the dogma >you made up about "single entry and single exit" doesn't make things >clearer as most see it in this case. "clearer", again, is subjective IMHO. In any case, I have not been recommending aherence to dogma. Rather I have been describing a cost/benfit trade-off. On at least two occasions, in this thread, I have said that there is a time and place for multiple returns; but that such times and places need to be chosen well based on a real assesment of the costs; an not a subjective evaluation of what "feels good". > >>Finally, I contend that the factors in favor of using a >>single-entry/single-exit style are, on the other hand, quite concrete and >>demonstrable. It has been shown that adhering to a structured style > >You have not shown at all that "single entry, single exit" is a >general coding maxim of structured programming. Well, that's your opinion. But I have cited the section of Dijkstra's book "Structured Programming" that talks about this; and have quoted the page where it is elaborated; and have summarized the discussion. It's quite difficult for me to understand how anyone could read the cited section and not agree that single-entry/single-exit is a core concept of structured programming. I also note that no one else has challenged that assertion. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-02 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: >Ell wrote in message <35eeea9b.2174586@news.erols.com>... >> >>"Robert Martin" <rmartin@oma.com> wrote: >>> >>>In any case, I note that in this thread nearly every article that >>>advocates >>>multiple exits evokes either readability, complexity, or naturalness as >>>the >>>justification. I contend that these are highly subjective things, >>This may be true, though I don't think[] so, but adherence to the dogma >>you made up about "single entry and single exit" doesn't make things >>clearer as most see it in this case. >"clearer", again, is subjective IMHO. Quite often the majority or a plurality of programmers is quite capable of agreeing on what is readable and more easily maintained. That isn't some kind of wild, unsubstantiated idea. Programmers have agreed on that for years. Geez, loosen up. >In any case, I have not been >recommending aherence to dogma. Yes you have. You have been citing your imaginary heuristic of structured programming - single entry, single exit - more than a call girl shouts for Johns at night. And as I said: [You've been palming your "single entry, single exit"] >dogma off as some kind of officialdom. Further, he can't prove it as >officialdom and it wouldn't matter if it was because the >appropriateness of all heuristics depends on specific concrete >circumstances. >Rather I have been describing a cost/benfit trade-off. And you haven't made your case on this as I see it. >On at least two occasions, in this thread, I have said that >there is a time and place for multiple returns; but that such times and >places need to be chosen well based on a real assesment of the costs; an not >a subjective evaluation of what "feels good". In that you haven't proven your cost/benefit assertions, what you say is what's "gut", and "feels good" to you. >>>Finally, I contend that the factors in favor of using a >>>single-entry/single-exit style are, on the other hand, quite concrete and >>>demonstrable. It has been shown that adhering to a structured style >> >>You have not shown at all that "single entry, single exit" is a >>general coding maxim of structured programming. > >Well, that's your opinion. But I have cited the section of Dijkstra's book >"Structured Programming" that talks about this; and have quoted the page >where it is elaborated; and have summarized the discussion. It's quite >difficult for me to understand how anyone could read the cited section and >not agree that single-entry/single-exit is a core concept of structured >programming. I also note that no one else has challenged that assertion. > > >Robert C. Martin | Design Consulting | Training courses offered: >Object Mentor | rmartin@oma.com | Object Oriented Design >14619 N Somerset Cr | Tel: (800) 338-6716 | C++ >Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > >"One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan > > ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-03 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Ole-Hjalmar Kristensen @ 1998-09-03 0:00 UTC (permalink / raw) ell@access.digex.net (Ell) writes: > "Robert Martin" <rmartin@oma.com> wrote: > > >Ell wrote in message <35eeea9b.2174586@news.erols.com>... > >> > >>"Robert Martin" <rmartin@oma.com> wrote: > >>> > >>>In any case, I note that in this thread nearly every article that > >>>advocates > >>>multiple exits evokes either readability, complexity, or naturalness as > >>>the > >>>justification. I contend that these are highly subjective things, > > >>This may be true, though I don't think[] so, but adherence to the dogma > >>you made up about "single entry and single exit" doesn't make things > >>clearer as most see it in this case. > > >"clearer", again, is subjective IMHO. > > Quite often the majority or a plurality of programmers is quite > capable of agreeing on what is readable and more easily maintained. > That isn't some kind of wild, unsubstantiated idea. Programmers have > agreed on that for years. Geez, loosen up. > > >In any case, I have not been > >recommending aherence to dogma. > > Yes you have. You have been citing your imaginary heuristic of > structured programming - single entry, single exit - more than a call > girl shouts for Johns at night. And as I said: > > [You've been palming your "single entry, single exit"] > >dogma off as some kind of officialdom. Further, he can't prove it as > >officialdom and it wouldn't matter if it was because the > >appropriateness of all heuristics depends on specific concrete > >circumstances. > > >Rather I have been describing a cost/benfit trade-off. > > And you haven't made your case on this as I see it. > > >On at least two occasions, in this thread, I have said that > >there is a time and place for multiple returns; but that such times and > >places need to be chosen well based on a real assesment of the costs; an not > >a subjective evaluation of what "feels good". > > In that you haven't proven your cost/benefit assertions, what you say > is what's "gut", and "feels good" to you. > > >>>Finally, I contend that the factors in favor of using a > >>>single-entry/single-exit style are, on the other hand, quite concrete and > >>>demonstrable. It has been shown that adhering to a structured style > >> > >>You have not shown at all that "single entry, single exit" is a > >>general coding maxim of structured programming. > > > >Well, that's your opinion. But I have cited the section of Dijkstra's book > >"Structured Programming" that talks about this; and have quoted the page > >where it is elaborated; and have summarized the discussion. It's quite > >difficult for me to understand how anyone could read the cited section and > >not agree that single-entry/single-exit is a core concept of structured > >programming. I also note that no one else has challenged that assertion. > > > > > >Robert C. Martin | Design Consulting | Training courses offered: > >Object Mentor | rmartin@oma.com | Object Oriented Design > >14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > >Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > > >"One of the great commandments of science is: > > 'Mistrust arguments from authority.'" -- Carl Sagan > > > > Please cool off! According to Dijkstra (not RCM) single-entry/single-exit IS a core concept of structured programming. Whether you agree that it is good idea, is another thing. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ole-Hjalmar Kristensen @ 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Patrick Doyle 0 siblings, 2 replies; 510+ messages in thread From: Ell @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Ole-Hjalmar Kristensen <ohk@tfdt-o.nta.no> wrote: : Please cool off! According to Dijkstra (not RCM) : single-entry/single-exit IS a core concept of structured programming. : Whether you agree that it is good idea, is another thing. I suppose you have heard that from his mouth, or you can cite his writings? Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ell @ 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Patrick Doyle 1 sibling, 0 replies; 510+ messages in thread From: Martin Tom Brown @ 1998-09-03 0:00 UTC (permalink / raw) On Thursday, in article <e8wH1.1153$H8.146210891@newsreader.digex.net> ell@access5.digex.net "Ell" wrote: > In comp.object Ole-Hjalmar Kristensen <ohk@tfdt-o.nta.no> wrote: > > : Please cool off! According to Dijkstra (not RCM) > : single-entry/single-exit IS a core concept of structured programming. > : Whether you agree that it is good idea, is another thing. > > I suppose you have heard that from his mouth, or you can cite his > writings? Off hand no, but the emphasis on "maintainence of functional domain" and subsequent development of the box diagram N-S or Chapin charts which prevented the fundamental maxims of structured programming from ever being violated would lend support to his argument. That this could lead to logical contortions and inefficiency if applied too dogmatically was an argument Knuth used in about '75. ISTR nested loop escapes were used as the counter example then. Regards, -- Martin Brown <martin@nezumi.demon.co.uk> __ CIS: 71651,470 Scientific Software Consultancy /^,,)__/ ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` Martin Tom Brown @ 1998-09-03 0:00 ` Patrick Doyle 1 sibling, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <e8wH1.1153$H8.146210891@newsreader.digex.net>, Ell <ell@access5.digex.net> wrote: > >I suppose you have heard that from his mouth, or you can cite his >writings? Have you been reading this thread? His writings have been cited. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin ` (2 more replies) 1 sibling, 3 replies; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) On Wed, 2 Sep 1998 08:52:36 -0500, "Robert Martin" <rmartin@oma.com> wrote: > >Ell wrote in message <35eeea9b.2174586@news.erols.com>... >> >>You have not shown at all that "single entry, single exit" is a >>general coding maxim of structured programming. >Well, that's your opinion. It's a *fact*! >But I have cited the section of Dijkstra's book >"Structured Programming" that talks about this; >and have quoted the page where it is elaborated; That single fragment of a sentence, or at most single sentence, about *flowcharting* in no way made the case that *coding* in the structured paradigm should generally adhere to "single entry and single exit". You are being ultra disengenuous to support your fantasies about structured programming. >I also note that no one else has challenged that assertion. Because no one else is confident enough to challenge you on the point doesn't ipso factso mean that you are right. What kind of logic is that? Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin [not found] ` <6sjnlu$83l$1@hirame.wwa.c <35EE5F67.80D@gecm.com> 2 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote in message <35f055a5.1431187@news.erols.com>... > >You are being ultra disengenuous to support your fantasies about >structured programming. HITLER! (Thread over, I lose...) Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Ell wrote in message <35f055a5.1431187@news.erols.com>... :> :>You are being ultra disengenuous to support your fantasies about :>structured programming. : HITLER! : (Thread over, I lose...) "HITLERITE!" is the unnecessary pain adhering to your fantasy dogma would cause us. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell ` (2 more replies) [not found] ` <6sjnlu$83l$1@hirame.wwa.c <35EE5F67.80D@gecm.com> 2 siblings, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote in message <35f055a5.1431187@news.erols.com>... >On Wed, 2 Sep 1998 08:52:36 -0500, "Robert Martin" <rmartin@oma.com> >wrote: > >> >>Ell wrote in message <35eeea9b.2174586@news.erols.com>... >>> >>>You have not shown at all that "single entry, single exit" is a >>>general coding maxim of structured programming. > >>Well, that's your opinion. > >It's a *fact*! You are entitled to that opinion. > >>But I have cited the section of Dijkstra's book >>"Structured Programming" that talks about this; >>and have quoted the page where it is elaborated; > >That single fragment of a sentence, or at most single sentence, about >*flowcharting* in no way made the case that *coding* in the structured >paradigm should generally adhere to "single entry and single exit". The point of the citing, and the quotation, was to guide you to read it for yourself. I'm not going to reproduce two or three pages of text for your benfit. The cited section is very unambiguous in its recommendation of single-entry and single-exit. The section was not about *flowcharting*, rather it used four different generic flowcharts (all with single entry and single exit) to describe the fundemental building blocks of structured programming. Elliott, you really ought to read the book. I've given you enough pointers. Do your homework. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Malcolm Steel [not found] ` <o1fH1.543$495.1 <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net> 2 siblings, 1 reply; 510+ messages in thread From: Ell @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Ell wrote in message <35f055a5.1431187@news.erols.com>... :>On Wed, 2 Sep 1998 08:52:36 -0500, "Robert Martin" <rmartin@oma.com> :>wrote: :> :>> :>>Ell wrote in message <35eeea9b.2174586@news.erols.com>... :>>> :>>>You have not shown at all that "single entry, single exit" is a :>>>general coding maxim of structured programming. :> :>>Well, that's your opinion. :> :>It's a *fact*! : You are entitled to that opinion. :> :>>But I have cited the section of Dijkstra's book :>>"Structured Programming" that talks about this; :>>and have quoted the page where it is elaborated; :> :>That single fragment of a sentence, or at most single sentence, about :>*flowcharting* in no way made the case that *coding* in the structured :>paradigm should generally adhere to "single entry and single exit". : The point of the citing, and the quotation, was to guide you to read it for : yourself. I'm not going to reproduce two or three pages of text for your : benfit. The cited section is very unambiguous in its recommendation of : single-entry and single-exit. The section was not about *flowcharting*, : rather it used four different generic flowcharts (all with single entry and : single exit) to describe the fundemental building blocks of structured : programming. : Elliott, you really ought to read the book. I've given you enough pointers. : Do your homework. If you had quotes showing that "single entry single exit" was supposed to be a key maxim of the structured paradigm you would quote it. At lesast you should. Because all you've shown is Flowcahrt 101, that of course a flowchart should have only one entry and one exit point on the *page*! I've taken 4 formally named "Structured COBOL" courses so I've already done my homework. It's your assertion which is groundless fanatasy. Rules about laying out flowcharts on page, as some kind of proof about the nature of structured *coding*. Indeed! Gives us a darn break would 'ya?! Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Joe Gwinn 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Ell wrote in message ... >If you had quotes showing that "single entry single exit" was supposed to >be a key maxim of the structured paradigm you would quote it. At lesast >you should. Elliott, if Dijkstra had provided a nice one liner, I'd be glad to give it to you. And, after all, maybe he did and I just haven't found it. So what? The chapter is only a few pages long, the book is certain to be available at a nearby library or bookstore, so look it up. >Because all you've shown is Flowcahrt 101, that of course a flowchart >should have only one entry and one exit point on the *page*! I have no idea how you could have drawn that interpretation. First, I've never heard of such a convention. Second, it has nothing to do with the discussion in the cited chapter. The chapter is about structuring the flow of control. Dijkstra is making the point that unrestricted flow of control (i.e. goto) is harmful. He then shows four flowcharts that demonstrate the cannonical forms of flow control in structured programming. They are, sequence, decision, top exit iteration, and bottom exit iteration. He then goes on to recommend that all software be constructed of assemblages of these four control forms; and nothing but these four control forms. He then describes the four forms as having a single entry and a single exit. I strongly recommend that before you respond further to this thread, you read Dijkstra's material. >I've taken 4 formally named "Structured COBOL" courses so I've already >done my homework. Twenty-three years ago I was *teaching* "Structured COBOL" courses. Fortunately, we are not discussing the contents of structured COBOL courses. We are discussing the contents of Dijkstra's book "Structured Programming". If your courses failed to teach you about single-entry/single-exit, then I suggest you ask for your money back, because you got reamed. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Joe Gwinn 1998-09-03 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson 0 siblings, 2 replies; 510+ messages in thread From: Joe Gwinn @ 1998-09-03 0:00 UTC (permalink / raw) It seems to me that there is an unspoken assumption in the long debate about GOTOs and spaghetti code: It doesn't follow that presence of GOTOs makes code spaghetti, or that code without GOTOs is always clear and easy to understand, write, and maintain. The issues are in my experience quite independent. I have seen lots of spaghetti code with nary a GOTO, and perfectly clear code with many GOTOs. I would submit that good programmers write clear, simple code, regardless of the nature of the language or language constructs used. (With the possible exception of APL, which was known as the write-only language.) I have seen the same effect in the design of digital hardware. The key issue is clarity of thought; lost-puppy engineers will do the oddest things, at length. It can be painful to watch, and hard on the engineer. So, the whole 1970s debate about structured programming (and thus GOTOs) reduced to the fond hope that if we tied the hands of those lost-puppy programmers, they would no longer be lost, and would then think ahead and write good code. By that same token, if we take a hard-to-use tool away from a rough carpenter, he will suddenly become a cabinetmaker. Joe Gwinn ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Joe Gwinn @ 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Ell 1998-09-06 0:00 ` Charles Hixson 1 sibling, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Joe Gwinn wrote in message ... >I would submit that good programmers write clear, simple code, regardless >of the nature of the language or language constructs used. (With the >possible exception of APL, which was known as the write-only language.) I >have seen the same effect in the design of digital hardware. The key >issue is clarity of thought; lost-puppy engineers will do the oddest >things, at length. It can be painful to watch, and hard on the engineer. Hardware engineers have their own intresting set of principles that they need to adhere to. Woe to the hardware engineer who does not use bypass capacitors. Woe to the hardware engineer who runs HF digital lines next to analog feedback lines. etc, etc.. In other words, there are things that the experienced hardware engineer knows that "you just don't do". >So, the whole 1970s debate about structured programming (and thus GOTOs) >reduced to the fond hope that if we tied the hands of those lost-puppy >programmers, they would no longer be lost, and would then think ahead and >write good code. Negative. That is not the point, nor ever was the point. The point of structured programming was not the elimination of GOTO. Indeed, you can write perfectly structured programs with GOTO. The point of structured programming was to recusively form the structure of an algorithm using units that have a single-entry and a single exit. And this structure has some concrete and well understood benefits. Even now, any programming standard that forces engineers to follow this scheme is probably broken. It is more important the engineer understand the costs and benefits of structured programming; then force them to blindly follow it. It was not Dijkstra's hope that we could tie the hands of the young puppies and thereby make good engineers out of them. Rather, I think it was his hope that experienced engineers would understand his suggestions and find that they had value in at least some contexts. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Ell 1 sibling, 0 replies; 510+ messages in thread From: sureshvv @ 1998-09-04 0:00 UTC (permalink / raw) In article <6snpvb$e6f$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > The point of structured > programming was to recusively form the structure of an algorithm using units > that have a single-entry and a single exit. And this structure has some > concrete and well understood benefits. I agree. The question is if a function (or a loop) should necessarily be a single monolithic block or is it better constituted with smaller blocks, where under clearly stated conditions only a sub-sequence of the blocks are executed. suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv @ 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Robert Martin 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Joe Gwinn wrote in message ... :> :>So, the whole 1970s debate about structured programming (and thus GOTOs) :>reduced to the fond hope that if we tied the hands of those lost-puppy :>programmers, they would no longer be lost, and would then think ahead and :>write good code. : Negative. That is not the point, nor ever was the point. The point of : structured programming was not the elimination of GOTO. Indeed, you can : write perfectly structured programs with GOTO. The point of structured : programming was to recusively form the structure of an algorithm using units : that have a single-entry and a single exit. Please show us a quote by Dahle and Dijkstra which states that se/se is *the* key concept of structured programming. And that would mean something other than the quote about the heuristics of creating a flowchart on a page (which itself never says se/se is *the* key concept of structured programming). Please stop the fantasy and "gut wishes". Also please explain why the concept of "abstraction" is never involved in how you define the structured paradigm although Dijkstra said it was the first thing he thought of? Again, please stop the fantasy and "gut wishes". Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell @ 1998-09-04 0:00 ` Robert Martin 1998-09-04 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-04 0:00 UTC (permalink / raw) Ell wrote in message <42OH1.2$vl.24707107@newsreader.digex.net>... >In comp.object Robert Martin <rmartin@oma.com> wrote: > >: Joe Gwinn wrote in message ... >:> >:>So, the whole 1970s debate about structured programming (and thus GOTOs) >:>reduced to the fond hope that if we tied the hands of those lost-puppy >:>programmers, they would no longer be lost, and would then think ahead and >:>write good code. > >: Negative. That is not the point, nor ever was the point. The point of >: structured programming was not the elimination of GOTO. Indeed, you can >: write perfectly structured programs with GOTO. The point of structured >: programming was to recusively form the structure of an algorithm using units >: that have a single-entry and a single exit. > >Please show us a quote by Dahle and Dijkstra which states that se/se is >*the* key concept of structured programming. Elliott, I can't help it if you are too lazy to go look up the references I've given you; and I've given you plenty. It seems clear that you know very little about structured programming, and that you have no interested in learning more. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Robert Martin @ 1998-09-04 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: > >Ell wrote in message <42OH1.2$vl.24707107@newsreader.digex.net>... >>In comp.object Robert Martin <rmartin@oma.com> wrote: >> >>: Joe Gwinn wrote in message ... >>:> >>:>So, the whole 1970s debate about structured programming (and thus GOTOs) >>:>reduced to the fond hope that if we tied the hands of those lost-puppy >>:>programmers, they would no longer be lost, and would then think ahead and >>:>write good code. >> >>: Negative. That is not the point, nor ever was the point. The point of >>: structured programming was not the elimination of GOTO. Indeed, you can >>: write perfectly structured programs with GOTO. The point of structured >>: programming was to recusively form the structure of an algorithm using >units >>: that have a single-entry and a single exit. >> >>Please show us a quote by Dahle and Dijkstra which states that se/se is >>*the* key concept of structured programming. >Elliott, I can't help it if you are too lazy to go look up the references >I've given you; and I've given you plenty. You haven't given us anything but more references to flowchart rules. >It seems clear that you know >very little about structured programming, and that you have no interested in >learning more. Martin you have not shown us one *shred* of evidence that se/se is a defining feature of the structured paradigm. The stuff about flowcharts is just that, stuff about flowcharts nothing more and nothing less. Please stop trying to insult our intelligence. In fact it is you who are making it clear to all that you are more interested in upholding your inappropriately, rigid fantasy as opposed to dealing with the facts. You should be ashamed of yourself. Again here you are standing in public with no clothes on, while shrilly proclaiming yourself well dressed. Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Joe Gwinn 1998-09-03 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney ` (2 more replies) 1 sibling, 3 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Joe Gwinn wrote: > > It seems to me that there is an unspoken assumption in the long debate > about GOTOs and spaghetti code: It doesn't follow that presence of GOTOs > makes code spaghetti, or that code without GOTOs is always clear and easy > to understand, write, and maintain. > > The issues are in my experience quite independent. I have seen lots of > spaghetti code with nary a GOTO, and perfectly clear code with many GOTOs. > ... > Joe Gwinn I suppose that it is possible to write spaghetti code without using goto's, I've never tried. I do know that with goto's INSTEAD OF while, until, elsif, begin...end, etc. it was very difficult NOT to write spaghetti code, and since there was originally the theory said that the best code economized on the number of CPU cycles, rather than optimized intelligibility, there was every reason TO write code that took short-cuts. Actually, there was a second optimization which said that code should use the minimum amount of core memory, so sometimes instructions would modify other instructions, so that blocks of code wouldn't need to be repeated with only slight changes. Spaghetti code didn't mean multiple return statements to the same location in the first 10 lines of the routine. O my no. I used to use several different colors of pen so that I could keep track of which direction the flow of control was going on the current branch. And seven levels wasn't unusual. My usual code was blue for down, green for up, red for a branch to an error exit, and black for a format statement reference. I BELIEVE in structured programming. I'm just not sure that se/se actually captures what it's really about. And I'm sorry, but even if Dijkstra did invent it, I don't feel that he necessarily understood what he was inventing. So quotes about what he said strike me as beside the point. YES, it was VERY important for him to say it. YES, he made great improvements in the art of programming. YES, he is one of the founders of what modern programming IS. This doesn't make him perfect and omniscient and omnipotent. Early returns from routines frequently make them easier to understand. And maintain. Se/se is something that is worth moderate efforts. It is, however, related to something else. Something that I don't yet have words to wrap around, but lots of other people on this list seem to also feel it. Code should be easy to understand AND to maintain. Both need to be optimized. Somehow. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` Matthew Heaney 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Robert Martin 1998-09-08 0:00 ` adam 2 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-06 0:00 UTC (permalink / raw) Charles Hixson <charleshixsn@earthlink.net> writes: > Early returns from routines frequently make them easier to understand. > And maintain. Se/se is something that is worth moderate efforts. It > is, however, related to something else. Something that I don't yet have > words to wrap around, but lots of other people on this list seem to also > feel it. As Bob Eachus pointed out, we can't even agree on what "single exit" means. According to him, you could interpret that to mean that the subprogram has a single point of return - to the point of call. According to that interpretation, multiple returns from a subprogram do indeed have a single exit, and thus fall under the rubric of "structured programming." I argue against using only a single return statement, because it often means that you have to do work to do ... nothing. Once I determine my answer (or satisfy the conditions for loop termination), then I'd rather return immediately, instead of having to figure out how to navigate my way to the end of the subprogram. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Matthew Heaney @ 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Ell 1998-09-11 0:00 ` Robert I. Eachus 0 siblings, 2 replies; 510+ messages in thread From: Robert Martin @ 1998-09-06 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >As Bob Eachus pointed out, we can't even agree on what "single exit" >means. According to him, you could interpret that to mean that the >subprogram has a single point of return - to the point of call. Dijkstra was quite specific about it. He drew dotted boxes around the flow charts that depicted the four possible control structures, and showed one line crossing through the top into the control structure, and another leaving the control structure and crossing the dotted line at the bottom. > >I argue against using only a single return statement, because it often >means that you have to do work to do ... nothing. Once I determine my >answer (or satisfy the conditions for loop termination), then I'd rather >return immediately, instead of having to figure out how to navigate my >way to the end of the subprogram. This is effective iff returning immediately is, and always will be, the right thing to do. But if there is a reasonable chance that you will have to do some error handling at some time in the future, then maintaining an se/se style provides place holders for that future code. BTW, that is nothing more than a benefit. One could still make a realistic and valid decision to forego that benefit. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Ell 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-11 0:00 ` Robert I. Eachus 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-06 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Matthew Heaney wrote in message ... :>As Bob Eachus pointed out, we can't even agree on what "single exit" :>means. According to him, you could interpret that to mean that the :>subprogram has a single point of return - to the point of call. : Dijkstra was quite specific about it. He drew dotted boxes around the flow : charts that depicted the four possible control structures, and showed one : line crossing through the top into the control structure, and another : leaving the control structure and crossing the dotted line at the bottom. But a control stucture can be viewed as a logical whole. Control flow passes through what the structure represents logically, not every phyiscal aspect. For example how can control flow go through both physical exit paths of branch structure? It's impossible. :>I argue against using only a single return statement, because it often :>means that you have to do work to do ... nothing. Once I determine my :>answer (or satisfy the conditions for loop termination), then I'd rather :>return immediately, instead of having to figure out how to navigate my :>way to the end of the subprogram. : This is effective iff returning immediately is, and always will be, the : right thing to do. But if there is a reasonable chance that you will have : to do some error handling at some time in the future, then maintaining an : se/se style provides place holders for that future code. : : BTW, that is nothing more than a benefit. One could still make a realistic : and valid decision to forego that benefit. And one could attempt to achieve other possibly more useful benfits given specific circumstances. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Ell @ 1998-09-06 0:00 ` Jeffrey C. Dege 0 siblings, 0 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-06 0:00 UTC (permalink / raw) On Sun, 06 Sep 1998 22:09:41 GMT, Ell <ell@access5.digex.net> wrote: >In comp.object Robert Martin <rmartin@oma.com> wrote: > >: Matthew Heaney wrote in message ... > >:>I argue against using only a single return statement, because it often >:>means that you have to do work to do ... nothing. Once I determine my >:>answer (or satisfy the conditions for loop termination), then I'd rather >:>return immediately, instead of having to figure out how to navigate my >:>way to the end of the subprogram. > >: This is effective iff returning immediately is, and always will be, the >: right thing to do. But if there is a reasonable chance that you will have >: to do some error handling at some time in the future, then maintaining an >: se/se style provides place holders for that future code. >: >: BTW, that is nothing more than a benefit. One could still make a realistic >: and valid decision to forego that benefit. > >And one could attempt to achieve other possibly more useful benfits given >specific circumstances. Ye gads, you're agreeing with each other... -- For every problem there is one solution which is simple, neat, and wrong. -- H. L. Mencken ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Ell @ 1998-09-11 0:00 ` Robert I. Eachus 1998-09-12 0:00 ` Patrick Logan 1 sibling, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-11 0:00 UTC (permalink / raw) In article <6sur5m$n9o$1@hirame.wwa.com> "Robert Martin" <rmartin@oma.com> writes: > Dijkstra was quite specific about it. He drew dotted boxes around the flow > charts that depicted the four possible control structures, and showed one > line crossing through the top into the control structure, and another > leaving the control structure and crossing the dotted line at the bottom. Exactly, and exactly what I was talking about. The evil is having two lines into the box, or two lines out. But I also contend, and I certainly never heard anything to the contrary from Dijkstra, that a procedure WHICH IMPLEMENTS A SINGLE CONTROL CONSTRUCT, is a perfect realization of Dijkstra's discipline. In fact, one of my favorite Dijkstra quotes is, "I have a small head and I must live within it." This was said in a discussion of exactly these issues. During the summer of 1980, GE and RPI sponsored a two-day symposium on software engineering. The conference was shortly after the "Green is Ada" announcement. After a session where Dijkstra presented some of his thoughts on software engineering a group including Dijkstra were discussing the control structures in Red, Blue, Green and Yellow. I don't remember exactly which control structure from which language started the discussion. But Dijkstra repeated his statement from the session and went on to explain that what he didn't like about the power of some of these constructs was that they allowed building single control constructions that had dozens of potential paths through them. One of the proposals for how to limit the complexity was to basically draw a line through the flow chart and count threads of control that were crossed. Someone said "One is perfect, two is fine, and three is spaghetti." Everyone laughed, including Dijkstra, and we went on to other topics. Early exits help avoid that definition of spaghetti, while some of the se/se proposals we have seen egregiously violate it. And I think that is a perfect summation of what structured programming is about. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-11 0:00 ` Robert I. Eachus @ 1998-09-12 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-12 0:00 UTC (permalink / raw) In comp.object Robert I. Eachus <eachus@spectre.mitre.org> wrote: : One of the proposals for how to limit the complexity was to : basically draw a line through the flow chart and count threads of : control that were crossed. Someone said "One is perfect, two is : fine, and three is spaghetti." Everyone laughed, including : Dijkstra, and we went on to other topics. : Early exits help avoid that definition of spaghetti, while some of : the se/se proposals we have seen egregiously violate it. And I : think that is a perfect summation of what structured programming is : about. Maybe you also have to draw a line from top to bottom and count the number of returns? -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney @ 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-08 0:00 ` adam 2 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-06 0:00 UTC (permalink / raw) Charles Hixson wrote in message <35F252DD.5187538@earthlink.net>... >I BELIEVE in structured programming. Stop believing in structured programming, it is not a faith. Instead, make sure that you understand what it is, and what its costs and benefits are. Then you can decide when to follow it, and when not. >I'm just not sure that se/se actually captures what it's really about. If you are saying that se/se is not the only way to attain the goals that Dijkstra was shooting at, you are almost certainly right. However, the technique defined by Dijkstra for attaining those goals is called Structured Programming. >And I'm sorry, but even if >Dijkstra did invent it, I don't feel that he necessarily understood what >he was inventing. So quotes about what he said strike me as beside the >point. They are certainly beside the point if the point is to "do things right". Even Dijkstra said his technique was unproven. But those quotes are not beside the point, if the point is describe an unambiguous definition for the term "Structured Programming". Again, we don't want to create the "Structured Programming" == "GOOD" relationship. We just want to describe what structured programming is, and understand its costs and benefits. >YES, it was VERY important for him to say it. YES, he made >great improvements in the art of programming. YES, he is one of the >founders of what modern programming IS. This doesn't make him perfect >and omniscient and omnipotent. I hope nobody thinks otherwise. >Early returns from routines frequently make them easier to understand. For some. >And maintain. Sometimes. >Se/se is something that is worth moderate efforts. In many cases. >It is, however, related to something else. Something that I don't yet have >words to wrap around, but lots of other people on this list seem to also >feel it. > >Code should be easy to understand AND to maintain. Both need to be >optimized. Somehow. And that will never happen until we all understand the costs and benefits of each technique, and abandon the practice of blindly following a technique. SP is one such technique. Using mid exit loops is another. We cannot assert that SP is *always good*. By the same token we cannot assert that mid exit loops are always good. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-06 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-06 0:00 UTC (permalink / raw) On Sun, 6 Sep 1998 09:21:11 -0500, Robert Martin <rmartin@oma.com> wrote: > >Charles Hixson wrote in message <35F252DD.5187538@earthlink.net>... > >>Code should be easy to understand AND to maintain. Both need to be >>optimized. Somehow. > >And that will never happen until we all understand the costs and benefits of >each technique, and abandon the practice of blindly following a technique. >SP is one such technique. Using mid exit loops is another. We cannot >assert that SP is *always good*. By the same token we cannot assert that >mid exit loops are always good. Be careful, your pragmatism is showing again... -- For every problem there is one solution which is simple, neat, and wrong. -- H. L. Mencken ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Jeffrey C. Dege @ 1998-09-06 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-06 0:00 UTC (permalink / raw) Jeffrey C. Dege wrote in message ... >On Sun, 6 Sep 1998 09:21:11 -0500, Robert Martin <rmartin@oma.com> wrote: >> >>Charles Hixson wrote in message <35F252DD.5187538@earthlink.net>... >> >>>Code should be easy to understand AND to maintain. Both need to be >>>optimized. Somehow. >> >>And that will never happen until we all understand the costs and benefits of >>each technique, and abandon the practice of blindly following a technique. >>SP is one such technique. Using mid exit loops is another. We cannot >>assert that SP is *always good*. By the same token we cannot assert that >>mid exit loops are always good. > >Be careful, your pragmatism is showing again... Yeah -- I'm a real dangerous fellow! Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney 1998-09-06 0:00 ` Robert Martin @ 1998-09-08 0:00 ` adam 1998-09-09 0:00 ` Gerry Quinn 2 siblings, 1 reply; 510+ messages in thread From: adam @ 1998-09-08 0:00 UTC (permalink / raw) In article <35F252DD.5187538@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: > I suppose that it is possible to write spaghetti code without using > goto's, I've never tried. Sigh . . . does anyone *try* to write spaghetti code? The thing is, someone who's inexperienced and hasn't read enough code to know whether code is readable or not, is certainly capable of writing unreadable, convoluted code without using GOTO. I can't say whether I've written any such code (because if I did, I would have been too inexperienced to recognize it...), but I do know that I've *seen* plenty of convoluted code written by people brought up in the "GOTO is evil" religion. Maybe it shouldn't be called "spaghetti code" since the control doesn't wind up over itself; maybe "rotini code" is more appropriate since although the different parts aren't entangled, they're all completely twisted within themselves. But if the goal is to write code that doesn't give a migraine to someone who tries to understand it, rather than merely to identify which form of pasta is appropriate to a particular piece of code, then Joe is absolutely right that it's possible to write code without GOTO that is just as twisted as the unstructured, GOTO-loaded code that older programmers used to write. > I do know that with goto's INSTEAD OF while, > until, elsif, begin...end, etc. it was very difficult NOT to write > spaghetti code How could it be that difficult? I found it quite easy. I used to work in COBOL in the late 1970's, before COBOL had decent control structures, and I learned that in many cases, it seemed better to *avoid* PERFORM .. WHILE, since it took important chunks of code out-of-line and made it more difficult for readers to understand. So, instead of PERFORM..WHILE, I often wrote code like START-OF-LOOP. IF some-condition THEN GOTO LOOP-END. BODY-OF-LOOP. ... do whatever GOTO START-OF-LOOP. LOOP-END. (Usually with more appropriate paragraph names.) This is well-structured, and not difficult to write, and should be easy enough to understand for anyone who has a clue what WHILE loops do in the first place. So I can't imagine what would merit calling this "spaghetti code", unless you belong to the "GOTO-Is-Evil" religion (St. Edsger's Church) and believe that spaghettiness can be determined by counting the number of GOTO's. > and since there was originally the theory said that the > best code economized on the number of CPU cycles, rather than optimized > intelligibility, there was every reason TO write code that took > short-cuts. Ummm, I don't see how this has anything to do with Joe's point. Sure, if you think GOTO's are fine *AND* one of your prime motivations is to eliminate as many cycles as possible, you're more likely to write unintelligible code; but Joe is only questioning the assumption about GOTO's, and is saying nothing whatsoever about nanosecond-squeezing code. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` adam @ 1998-09-09 0:00 ` Gerry Quinn [not found] ` <gio+van+no+ni+8-1609980034390001@dialup26.tlh.talstar.com> 0 siblings, 1 reply; 510+ messages in thread From: Gerry Quinn @ 1998-09-09 0:00 UTC (permalink / raw) In article <6t4dge$t8u$1@nnrp1.dejanews.com>, adam@irvine.com wrote: >In article <35F252DD.5187538@earthlink.net>, > Charles Hixson <charleshixsn@earthlink.net> wrote: > >> I suppose that it is possible to write spaghetti code without using >> goto's, I've never tried. > >Sigh . . . does anyone *try* to write spaghetti code? The thing is, someone >who's inexperienced and hasn't read enough code to know whether code is >readable or not, is certainly capable of writing unreadable, convoluted code >without using GOTO. I agree - in fact I would argue that if you are carrying a flag for deciding when to exit, the flag is part of the flow of control - with all the potential pasta that entails. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-1609980034390001@dialup26.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-1609980034390001@dialup26.tlh.talstar.com> @ 1998-09-16 0:00 ` Biju Thomas 1998-09-17 0:00 ` Gerry Quinn 1998-09-17 0:00 ` dewarr 0 siblings, 2 replies; 510+ messages in thread From: Biju Thomas @ 1998-09-16 0:00 UTC (permalink / raw) Giovanni 8 wrote: > > > Gerry Quinn wrote: > >> adam wrote: > >> Sigh... does anyone *try* to write spaghetti code? > >> The thing is, someone who's inexperienced and hasn't read > >> enough code to know whether code is readable or not, is > >> certainly capable of writing unreadable, convoluted code > >> without using GOTO. > > > I agree - in fact I would argue that if you are carrying a > > flag for deciding when to exit, the flag is part of the > > flow of control - with all the potential pasta that entails. > > Spaghetti code is in the eye of the beholder. > > Some people find jumps or gotos, written in their own > particular style, to be much more elegant and clear > than the so-called control structures. Others really > like flags popping up in one place & then not being > seen through vast piles of listing until, layers removed, > they are used again (even in a different context with > different conceptual significance for the values of > the flag). I've seen people, brows furrowed, puzzled > over code that was the epitome of structured design, > who could follow the jumps of assembly language with > ease. Reminds me of what Dijkstra told about the effect of COBOL and BASIC on minds: "The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offense." "It is practically impossible to teach good programming style to students that have had prior exposure to BASIC; as potential programmers they are mentally mutilated beyond hope of regeneration" Biju Thomas ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-16 0:00 ` Biju Thomas @ 1998-09-17 0:00 ` Gerry Quinn 1998-09-17 0:00 ` dewarr 1998-09-17 0:00 ` dewarr 1 sibling, 1 reply; 510+ messages in thread From: Gerry Quinn @ 1998-09-17 0:00 UTC (permalink / raw) In article <35FFE58C.5727@ibm.net>, bijuthom@ibm.net wrote: >Reminds me of what Dijkstra told about the effect of COBOL and BASIC on >minds: > >"The use of COBOL cripples the mind; its teaching should, therefore, be >regarded as a criminal offense." > >"It is practically impossible to teach good programming style to >students that have had prior exposure to BASIC; as potential programmers >they are mentally mutilated beyond hope of regeneration" > One suspects Dijkstra was a poor teacher. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` Gerry Quinn @ 1998-09-17 0:00 ` dewarr 1998-09-18 0:00 ` Gerry Quinn 0 siblings, 1 reply; 510+ messages in thread From: dewarr @ 1998-09-17 0:00 UTC (permalink / raw) In article <6tqvji$f0k$2@news.indigo.ie>, gerryq@indigo.ie (Gerry Quinn) wrote: > In article <35FFE58C.5727@ibm.net>, bijuthom@ibm.net wrote: > > >Reminds me of what Dijkstra told about the effect of COBOL and BASIC on > >minds: > > > >"The use of COBOL cripples the mind; its teaching should, therefore, be > >regarded as a criminal offense." > > > >"It is practically impossible to teach good programming style to > >students that have had prior exposure to BASIC; as potential programmers > >they are mentally mutilated beyond hope of regeneration" > > > > One suspects Dijkstra was a poor teacher. > Oh goodness, if "one" suspects that, one sure does not know what one is talking about :-) EWD is a brilliant teacher. I well remember a great evening in Amsterdam, when he met my wife for the first time, and gave a quite marvelous demonstration with her of how to teach about trans-Cantorian infinities in a clear way to a non-mathematical person. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` dewarr @ 1998-09-18 0:00 ` Gerry Quinn 1998-09-18 0:00 ` Biju Thomas 1998-09-19 0:00 ` dewarr 0 siblings, 2 replies; 510+ messages in thread From: Gerry Quinn @ 1998-09-18 0:00 UTC (permalink / raw) In article <6ts4d0$2gk$1@nnrp1.dejanews.com>, dewarr@my-dejanews.com wrote: >In article <6tqvji$f0k$2@news.indigo.ie>, > gerryq@indigo.ie (Gerry Quinn) wrote: >> In article <35FFE58C.5727@ibm.net>, bijuthom@ibm.net wrote: >> >> >Reminds me of what Dijkstra told about the effect of COBOL and BASIC on >> >minds: >> > >> >"The use of COBOL cripples the mind; its teaching should, therefore, be >> >regarded as a criminal offense." >> > >> >"It is practically impossible to teach good programming style to >> >students that have had prior exposure to BASIC; as potential programmers >> >they are mentally mutilated beyond hope of regeneration" >> > >> >> One suspects Dijkstra was a poor teacher. >Oh goodness, if "one" suspects that, one sure does not know >what one is talking about :-) > >EWD is a brilliant teacher. I well remember a great evening >in Amsterdam, when he met my wife for the first time, and >gave a quite marvelous demonstration with her of how to >teach about trans-Cantorian infinities in a clear way to >a non-mathematical person. > I don't quite understand how a non-mathematical person would understand trans-Cantorian infinities. It sounds like a non-programming person understanding Cobol. - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Gerry Quinn @ 1998-09-18 0:00 ` Biju Thomas 1998-09-18 0:00 ` Robert C. Martin ` (2 more replies) 1998-09-19 0:00 ` dewarr 1 sibling, 3 replies; 510+ messages in thread From: Biju Thomas @ 1998-09-18 0:00 UTC (permalink / raw) Gerry Quinn wrote: > > I don't quite understand how a non-mathematical person would > understand trans-Cantorian infinities. It sounds like a > non-programming person understanding Cobol. > Wasn't COBOL designed to enable no-programmer's to write programs? Biju Thomas ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Biju Thomas @ 1998-09-18 0:00 ` Robert C. Martin 1998-09-19 0:00 ` Rick Smith 1998-09-19 0:00 ` Ell 1998-09-19 0:00 ` dewarr 2 siblings, 1 reply; 510+ messages in thread From: Robert C. Martin @ 1998-09-18 0:00 UTC (permalink / raw) Biju Thomas <"Biju Thomas"> > wrote in message <3602983C.62B1@ibm.net>... >Gerry Quinn wrote: >> >> I don't quite understand how a non-mathematical person would >> understand trans-Cantorian infinities. It sounds like a >> non-programming person understanding Cobol. >> > >Wasn't COBOL designed to enable no-programmer's to write programs? > Yes, that was the idea... But it failed since, clearly, some programmers *are* writing programs in COBOL. (Snicker) Actually the idea was not to allow non-programmers to *write* the programs. It was to allow non-programmers to be able to read the programs to some extent. The programs were supposed to be self-documenting. In the end, this failed too. COBOL, like every other computer language, is loaded with arcanities which are critical for the understanding of the program. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "If you've ever left double-letters out of a person's name, then you might be a craftite." -- Tim Ottinger ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Robert C. Martin @ 1998-09-19 0:00 ` Rick Smith 0 siblings, 0 replies; 510+ messages in thread From: Rick Smith @ 1998-09-19 0:00 UTC (permalink / raw) Robert C. Martin wrote in message <6tvcf9$jqt$1@hirame.wwa.com>... > >Biju Thomas <"Biju Thomas"> > wrote in message <3602983C.62B1@ibm.net>... >>Gerry Quinn wrote: >>> >>> I don't quite understand how a non-mathematical person would >>> understand trans-Cantorian infinities. It sounds like a >>> non-programming person understanding Cobol. >>> >> >>Wasn't COBOL designed to enable no-programmer's to write programs? >> > > >Yes, that was the idea... But it failed since, clearly, some programmers >*are* writing programs in COBOL. > >(Snicker) > >Actually the idea was not to allow non-programmers to *write* the programs. >It was to allow non-programmers to be able to read the programs to some >extent. The programs were supposed to be self-documenting. In the end, >this failed too. COBOL, like every other computer language, is loaded with >arcanities which are critical for the understanding of the program. > I think the supposition that COBOL programs are "self-documenting" is folklore! Since it was not intended, it cannot have failed! In the quote below, note the subtle, yet distinct, difference between readability as documentation and program as documentation. Quote from Gerald M. Weinberg, The Psychology of Computer Programming, Van Nostrand Reinhold, 1971 "People have lost sight of the original intention of COBOL's designers. To quote one of them, Jean Sammet: The users for whom COBOL was designed were actually two subclasses of those people concerned with business data processing problems. One is the relatively inexperienced programmer for whom the naturalness of COBOL would be an asset, while the other type of user would be essentially anybody who had not written the program initially. In other words, the readability of COBOL programs would provide documentation to all who might wish to examine the programs, including the supervisory or management personnel. Little attempt was made to cater to professional programmers. ... The COBOL designers went to considerable trouble to see that these objectives were met." As I see it, the readability of COBOL allows others to examine the programs to see that they conform to other documents, such as requirements and specifications. For the individual who is changing the program, the readability of COBOL makes it easier to understand where and how to implement a change in the specification or to correct a deviation from the specification ("bug"). I do believe that the designers never intended that COBOL programs should be self-documenting; that is, existing without other documents. ------------------------------- Rick Smith e-mail: < ricksmith@aiservices.com > ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Biju Thomas 1998-09-18 0:00 ` Robert C. Martin @ 1998-09-19 0:00 ` Ell 1998-09-19 0:00 ` dewarr 2 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-19 0:00 UTC (permalink / raw) In comp.object Biju Thomas <"Biju Thomas"> wrote: : : Gerry Quinn wrote: :> :> I don't quite understand how a non-mathematical person would :> understand trans-Cantorian infinities. It sounds like a :> non-programming person understanding Cobol. :> : Wasn't COBOL designed to enable no-programmer's to write programs? Grace Hopper the creator of COBOL, who I saw once and who I've heard speak a number of times, said that she wanted to formulate a language well suited to the heavy record and regular math calculation intensive demands of large business and organizational processing. In that, I find that she succeded quite admirably. I find the "look and feel" of a COBOL program which adheres to proper structured guidelines to be a joy to behold (ie. when I look at my own COBOL code :-) I know people who are great assembler, C and C++ programmers who also excel at and enjoy COBOL programming. Elliott -- :=***=: VOTE NO TO MODERATION! ALL IDEAS SHOULD BE CRITICIZABLE! :=***=: MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Biju Thomas 1998-09-18 0:00 ` Robert C. Martin 1998-09-19 0:00 ` Ell @ 1998-09-19 0:00 ` dewarr 1998-09-21 0:00 ` Richard D Riehle 2 siblings, 1 reply; 510+ messages in thread From: dewarr @ 1998-09-19 0:00 UTC (permalink / raw) In article <3602983C.62B1@ibm.net>, bijuthom@ibm.net wrote: > Gerry Quinn wrote: > > > > I don't quite understand how a non-mathematical person would > > understand trans-Cantorian infinities. It sounds like a > > non-programming person understanding Cobol. > > > > Wasn't COBOL designed to enable no-programmer's to write programs? > > Biju Thomas No. It wasn't, and this idea is obviously absurd on the face of it (just read what you read, at the very least you must have forgotten a smiley, no?) What it was designed for was to make it easier for a non-programmer to *read* a COBOL program, and a well written COBOL program can do a good job of that (remember that the competition at the time was Fortran with 6 character identifier length limit). A sequence like IF BALANCE IS NEGATIVE THEN PERFORM SEND-BILL ELSE PERFORM REGISTER-CREDIT END-IF. Does not require a computer expert to figure out! Note here incidentally (always happy to take the chance to teach the ignorant a little bit about COBOL :-) :-) that the very light local refinement syntax is very attractive. Let's look at the above example in more detail and let's use upper/lower case as now permitted since that's more familiar. Process_Balance if balance is negative then perform Send-Bill else peform Register-Credit end-if. Send-Bill. ... Register-Credit. ... The only syntax required for a little refinement like this is the name of the procedure and a period. Furthermore, as you prefer for this kind of refinement, the definition of the procedure is AFTER the use. Many modern procedural languages don't compete well with COBOL in this respect, and the style in languages like Ada or C is instead to nest conditionals and let the code wander off to the right side of the page. COBOL programmers tend to find nested conditionals confusing (not such a suprising attitude, how many complex nested conditionals do you use in everyday speach :-) Does COBOL achieve its aim of allowing complex programs to be understood by non-programmers? Only partially, but at the time, it was definitely nearer to this goal than the competition, and it still is one of the languages in which it is possible to create the most readable code if you know what you are doing. SEND -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-19 0:00 ` dewarr @ 1998-09-21 0:00 ` Richard D Riehle 0 siblings, 0 replies; 510+ messages in thread From: Richard D Riehle @ 1998-09-21 0:00 UTC (permalink / raw) In article <6u0ck4$f08$1@nnrp1.dejanews.com>, dewarr@my-dejanews.com wrote: >In article <3602983C.62B1@ibm.net>, > bijuthom@ibm.net wrote: >> Wasn't COBOL designed to enable no-programmer's to write programs? > >No. It wasn't, and this idea is obviously absurd on the face >of it ... When considered from the viewpoint of COBOL's design objectives, Robert is correct. However, it turned out that one of COBOL's virtues was just as Mr. Biju asserts. During the 1960's and 1970's many large companies (banks, insurance companies, etc.) discovered it was easier to train accounting personnel to write programs in COBOL than it was to train programmers to understand accounting. Many of those accounting personnel went on to become real programmers. This resulted in all sorts of interesting problems, some of which are still with us today. COBOL gets a "bad rap" from those who favor other languages. The fact is that it continues to evolve and improve. The example given in Robert's posting was an illustration of changes to the language that first appeared in ANSI-85 COBOL standard. A COBOL programmer of an earlier time would not recognize the code as valid. Many COBOL shops are still using COBOL 68 and COBOL 74 quite regularly and creating successful data processing systems. The currently emerging COBOL standard is an Object COBOL in which this presumably outdated and obsolete language continues to amaze its detractors by being resilient enough to evolve to encompass the current fad in software development. Richard Riehle richard@adaworks.com www.adaworks.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Gerry Quinn 1998-09-18 0:00 ` Biju Thomas @ 1998-09-19 0:00 ` dewarr 1 sibling, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-19 0:00 UTC (permalink / raw) In article <6ttg0o$9kb$2@news.indigo.ie>, gerryq@indigo.ie (Gerry Quinn) wrote: > I don't quite understand how a non-mathematical person would > understand trans-Cantorian infinities. It sounds like a > non-programming person understanding Cobol. Well that's the point! It takes a good teacher to adjust to the right level. I certainly would expect to be able to give a non-programming person an understanding of what COBOL is all about. In fact if you act as an expert witness with a jury, you are most definitely expected to be able to do this. It is not easy, teaching like anything else is an expertise where the experts can amaze you :-) -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-16 0:00 ` Biju Thomas 1998-09-17 0:00 ` Gerry Quinn @ 1998-09-17 0:00 ` dewarr 1998-09-18 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: dewarr @ 1998-09-17 0:00 UTC (permalink / raw) In article <35FFE58C.5727@ibm.net>, bijuthom@ibm.net wrote: > Giovanni 8 wrote: > > > > > Gerry Quinn wrote: > > >> adam wrote: > > >> Sigh... does anyone *try* to write spaghetti code? > > >> The thing is, someone who's inexperienced and hasn't read > > >> enough code to know whether code is readable or not, is > > >> certainly capable of writing unreadable, convoluted code > > >> without using GOTO. > > > > > I agree - in fact I would argue that if you are carrying a > > > flag for deciding when to exit, the flag is part of the > > > flow of control - with all the potential pasta that entails. > > > > Spaghetti code is in the eye of the beholder. > > > > Some people find jumps or gotos, written in their own > > particular style, to be much more elegant and clear > > than the so-called control structures. Others really > > like flags popping up in one place & then not being > > seen through vast piles of listing until, layers removed, > > they are used again (even in a different context with > > different conceptual significance for the values of > > the flag). I've seen people, brows furrowed, puzzled > > over code that was the epitome of structured design, > > who could follow the jumps of assembly language with > > ease. > > Reminds me of what Dijkstra told about the effect of COBOL and BASIC on > minds: > > "The use of COBOL cripples the mind; its teaching should, therefore, be > regarded as a criminal offense." > > "It is practically impossible to teach good programming style to > students that have had prior exposure to BASIC; as potential programmers > they are mentally mutilated beyond hope of regeneration" > > Biju Thomas > I would be willing to be that EWD simply does not know COBOL, or that if he does know it, he knows some ancient version that bears no relationship to modern COBOL. In fact this must be the case, or he would not make a patently absurd statement like this. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` dewarr @ 1998-09-18 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-18 0:00 UTC (permalink / raw) dewarr@my-dejanews.com wrote: > Biju Thomas wrote: >> >> Reminds me of what Dijkstra told about the effect of COBOL and BASIC on >> minds: >> >> "The use of COBOL cripples the mind; its teaching should, therefore, be >> regarded as a criminal offense." >> >> "It is practically impossible to teach good programming style to >> students that have had prior exposure to BASIC; as potential >> programmers they are mentally mutilated beyond hope of regeneration" >I would be willing to be that EWD simply does not know COBOL, >or that if he does know it, he knows some ancient version >that bears no relationship to modern COBOL. In fact this >must be the case, or he would not make a patently absurd >statement like this. COBOL, modern day at least, is great for teaching modularity, hierarchically layered architecture, procedures to enhance loose coupling and high cohesion, and procedure calls to avoid pasta. Myself and many others learned BASIC and were able to develop good programming styles despite that. And then with Darmouth and True BASIC, 'goto' was discouraged and a modular, loosely coupled, and highly cohesive routine call style was supported and encouraged. While I really like Dijkstra's comment that *abstraction* is the first thing he thinks of when the term "structured programming" is mentioned*, his above statements are typical craftite, elitist comments. *[Art of Literate Programmimg, CLSC, D. Knuth, pg 72] He is the supposed all-knowing master craftsman who looks down his nose at the work and practices of any but his own and that of a small circle of cohorts. Elliott -- :=***=: VOTE NO TO MODERATION! ALL IDEAS SHOULD BE CRITICIZABLE! :=***=: MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell @ 1998-09-03 0:00 ` Malcolm Steel [not found] ` <o1fH1.543$495.1 <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net> 2 siblings, 0 replies; 510+ messages in thread From: Malcolm Steel @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote: > >>But I have cited the section of Dijkstra's book > >>"Structured Programming" that talks about this; > >>and have quoted the page where it is elaborated; > Elliott, you really ought to read the book. I've given you enough pointers. > Do your homework. I have largeley ignored this thread, however I would like to ask a general question that this dicussion demonstrates: Why are engineers with new/different ideas always shot down without consideration ? So many times I have seem new thoughts and ideas attacked without any consideration. A classic move is to quote a book. It seems books are law, even i they are not always correct (often they are not !!!). I'm not taking sides, infact I beleive that single entry/exit is best, however, before shooting down alternative thoughts they should be considered. Often dicussions become heated between engineers with new thoughts and the book bashers. Why ???? ... what ever happend to open minds ? ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <o1fH1.543$495.1 <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net>]
* Re: Software landmines (loops) [not found] ` <o1fH1.543$495.1 <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net> @ 1998-09-04 0:00 ` Samuel Mize 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 0 siblings, 2 replies; 510+ messages in thread From: Samuel Mize @ 1998-09-04 0:00 UTC (permalink / raw) In article <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net>, Joe Gwinn <gwinn@ma.ultranet.com> wrote: >The issues are in my experience quite independent. I have seen lots of >spaghetti code with nary a GOTO, and perfectly clear code with many GOTOs. > >I would submit that good programmers write clear, simple code, regardless [of language used] This is certainly true. >...The key issue is clarity of thought; Well, clarity of thought and clarity of exposition. A complex bit of code may be clear in one's mind, but be the devil to recall or decrypt for later debugging or maintenance changes. One benefit from structured programming is to make everyone use a simpler, common "language" of programming -- a set of idioms that will simplify communication with other programmers, including ourselves in later time. Humpty Dumpty had perfectly clear thoughts, but he didn't use the agreed-to language, so his thoughts weren't clear to others. ...So, the whole 1970s debate about structured programming (and thus GOTOs) >reduced to the fond hope that if we tied the hands of those lost-puppy >programmers, they would no longer be lost, and would then think ahead and >write good code. Well, I suppose that's a fair representation of the overblown claims that some people made for it. I understood it to be an attempt to codify the heuristics that better programmers use, so neophytes could learn more easily how to code clearly. It goes hand-in-glove, necessarily, with structured design, which is a similar attempt to codify how better programmers organize their thinking before they code. But I had the good fortune to have structured programming presented, not as a set of language constructs, but as one of a number of useful ways of organizing one's thinking. Others would be functional, logic, and object-oriented programming. Note that code in LISP isn't necessarily functional, and gotoless code isn't necessarily structured. The core intuition was always that the program should HAVE structure; that you should be able to easily see how it is organized, and how it organizes its activities. It shouldn't be just a stream-of-consciousness sequence of instructions. Structured programming isn't necessarily single-entry-single-exit, or gotoless programming, although those sub-flavors do exist. Further, within a project or team, you should have an agreed-to set of structures, so you can interchange code easily. It's like teaching a new carpenter how to build a standard wall with studs and sheet rock. There are a lot of other ways to build a wall, and for some walls another method is better. But it's wise to teach a student the standard methods first, and teach them how and why they work (and when and why they DON'T work), before you turn him loose on a building. Further, if he builds a weird-style wall, no matter how good a wall it is, the electricians and plumbers won't know how to work with it. I've always felt my institution (Kansas State University) did a really remarkable job of providing a sensible, pragmatic introduction to a lot of technologies. I also like how one of my professors described some of the programs he saw: apparently they gather a pack of discarded, mispunched cards left behind by other students, slap a JCL card on the front, then try to debug it. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Samuel Mize @ 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) smize@news.imagin.net (Samuel Mize) wrote: [ Much good stuff elided.] >I've always felt my institution (Kansas State University) did a really >remarkable job of providing a sensible, pragmatic introduction to a >lot of technologies. Too bad about "sensible, pragmatic". I realize the value of having your feet on the ground sometimes, but that's not the best overall way to view, approach, and live life as I see things. Why be "grounded" when there is so much to gain by going against the grain, taking risks, making big leaps over always being evolutionary, often making things unstable versus always striving for stability, etc, etc. For example rather than have classes depend on a so-called stable abstraction, it might make a lot of sense to metamorphize a heavily depended upon abstraction and to thereby metamorphize most, or some of it's inheriting children. In addition it might be best for clients that depend on services from a heavily depended upon abstraction to undergo change in order to accommodate the change in its server class set, or hierarchy. You can study history for yourself, but pragmatism rarely contributes truly great ideas, nor does it consistently provide truly _progressive_ changes in the world, or in even a single area of human endeavor. Down with pragmatism! Up with hope! Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Samuel Mize 1998-09-04 0:00 ` Ell @ 1998-09-05 0:00 ` Loryn Jenkins 1998-09-09 0:00 ` Samuel Mize 1998-09-11 0:00 ` Robert I. Eachus 1 sibling, 2 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) > Humpty Dumpty had perfectly clear thoughts, but he didn't use the > agreed-to language, so his thoughts weren't clear to others. This is dubious at best. Although many linguists in the American Chomskyist school chould agree with you (that is, their dubious claim of the division between 'competence' and 'performance'). Outside of there, few linguists would agree with this philosophical position. It is much more to the point that language is an instrument which *construes reality*. It is quite inapropriate to claim that thoughts can be organised outside of the semiotic systems that construct it. Loryn Jenkins BA, Linguistics. Macqurie University. Sydney, Australia. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Loryn Jenkins @ 1998-09-09 0:00 ` Samuel Mize 1998-09-09 0:00 ` sureshvv 1998-09-10 0:00 ` Tim Ottinger 1998-09-11 0:00 ` Robert I. Eachus 1 sibling, 2 replies; 510+ messages in thread From: Samuel Mize @ 1998-09-09 0:00 UTC (permalink / raw) In article <35F06D6A.91A3D34E@s054.aone.net.au>, Loryn Jenkins <loryn@acm.org> wrote: >> Humpty Dumpty had perfectly clear thoughts, but he didn't use the >> agreed-to language, so his thoughts weren't clear to others. > >This is dubious at best. Although many linguists in the American >Chomskyist school chould agree with you ... OK, I'll restate my point without reference to the Classics. If someone uses Tagalog or Mayan words as identifiers, he (or she, in all cases) would understand his own code easily. However, it would be hard and error-prone for others from a typical project team to understand it. This is similar to someone who understands clearly what he intends the code to do, but expresses it in a way that is not clear to a reader. An appeal to clarity of thought won't shape up that person's code; his thoughts are perfectly clear, just complex. In fact, one could argue that some obscure code comes from too MUCH clarity of thought. When one is deeply immersed in the details of an algorithm, its conditions and behavior are clear. So, code can seem clear to the writer, because it's easy to see what it's doing -- IF you already know in detail what it's doing! Another way to express that may be that the writer has "chunked" together some of the complex concepts in the algorithm. (I'm using the term loosely.) So from his point of view, he's expressing a few simple ideas in the code. But the reader, not having those "chunks" already in mind, has to interpret the full complexity of the code. >It is much more to the point that language is an instrument which >*construes reality*. It is quite inapropriate to claim that thoughts can >be organised outside of the semiotic systems that construct it. Well, I certainly can't argue with that! I can't even follow it. Let's see if my understanding is within a furlong of your intent. I think the difference is that the coder typically constructs his thoughts in one semiotic system: a combination of diagrams, native language, and code fragments. Then he expresses them in another: compilable code. The reader, to really understand the code, must then rebuild something equivalent to the original construction before the code makes as much sense to him as it did to the writer. Using a constrained set of structures simplifies understanding the code, but sometimes makes it harder to write it. This is like to using a limited, non-technical vocabulary when explaining things (like linguistics). Such a limited vocabulary would make it easier to understand an explanation, but harder to write it. But we're discussing structure. Here's a better analogy. The previous paragraph was originally all one sentence that expressed that complex idea. I clearly understood what I wanted to say, but it took me some time and effort to simplify my expression of it. One heuristic that is often helpful in improving clarity of expression is to break up a long, complex sequence into shorter, well-structured components. This is true in English and in code. That's the central intuition of "structured programming," as I understand the term, which is in a broad sense. Single entry/exit, end-exit loops, and other constraints, are specific approaches to defining the structures to be used. Best, Sam Mize -- Samuel Mize -- smize@imagin.net (home email) -- Team Ada Fight Spam: see http://www.cauce.org/ \\\ Smert Spamonam ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Samuel Mize @ 1998-09-09 0:00 ` sureshvv 1998-09-10 0:00 ` prochak 1998-09-17 0:00 ` Matthew Heaney 1998-09-10 0:00 ` Tim Ottinger 1 sibling, 2 replies; 510+ messages in thread From: sureshvv @ 1998-09-09 0:00 UTC (permalink / raw) In article <6t6b3m$30j8$1@prime.imagin.net>, smize@imagin.net (Samuel Mize) wrote: > > One heuristic that is often helpful in improving clarity of expression > is to break up a long, complex sequence into shorter, well-structured > components. This is true in English and in code. > Well said. The multi-return structure enables you to separate code in small independent blocks, each of which may be examined and understood with less interference from surrounding blocks. The se-se structure creates large blocks, requiring more context information. > That's the central intuition of "structured programming," as I > understand the term, which is in a broad sense. Single entry/exit, > end-exit loops, and other constraints, are specific approaches to > defining the structures to be used. > Agreed. In this case, se-se is a good starting point. But the tree structure (as someone referred to it; i would be interested in a reference) IMHO, is superior in capturing this intent of structured programming (irresp. of if Dijkstra would approve of it). suresh -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` sureshvv @ 1998-09-10 0:00 ` prochak 1998-09-11 0:00 ` Patrick Doyle 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: prochak @ 1998-09-10 0:00 UTC (permalink / raw) In article <6t6shq$f53$1@nnrp1.dejanews.com>, sureshvv@hotmail.com wrote: > In article <6t6b3m$30j8$1@prime.imagin.net>, > smize@imagin.net (Samuel Mize) wrote: > > > > One heuristic that is often helpful in improving clarity of expression > > is to break up a long, complex sequence into shorter, well-structured > > components. This is true in English and in code. > > > > Well said. The multi-return structure enables you to separate > code in small independent blocks, each of which may be examined > and understood with less interference from surrounding blocks. > The se-se structure creates large blocks, requiring more > context information. When followed religiously in a large block of code, the se-se rule does lead to this kind of problem. It doesn't have to if the code and language allows creating more functions/procedures to encapsulate the pieces of that large code block. But that also can go too far to where the main line of code is a sequence of procedure calls and the procedures are grotesquely short (one liners). A certain amount of this is the old maxim: everything in moderation. > > > That's the central intuition of "structured programming," as I > > understand the term, which is in a broad sense. Single entry/exit, > > end-exit loops, and other constraints, are specific approaches to > > defining the structures to be used. > > > > Agreed. In this case, se-se is a good starting point. But the tree > structure (as someone referred to it; i would be interested in a reference) > IMHO, is superior in capturing this intent of structured programming > (irresp. of if Dijkstra would approve of it). > > suresh > The tree structure can get out of hand also. If there are too many exits in the code, then I'd begin to question the design there too. I'm not sure who I agree with in this discussion. I understand the central principle of structured programming to be: predictability. Dijkstra and other theorists want se-se type code structures to be able to derive proofs about the code. Programmers (me) look at it as a way to know, when reading some code, where to look next when coming across a GOTO statement. In unstructured code, I'm forced to always do a linear search from the first line of the code listing. In structured code, I expect everything to "flow downhill" so the target must be later in the listing (except for well-defined loops, which I know exists because something labeled it so at the loop entry. ie the single entry is just as important as the single exit.) Actually, writing that last line, I realized what is perhaps a better way to state the structured programming principle: all code structures have a WELL-DEFINED entry and a WELL-DEFINED exit. So where necessary, there are early loop exits, there are multiple returns within functions, and whereever else goto's are NEEDED. But the goto's are not sprinkled thruout the code for arguements of "efficiency" or "code reuse". How do you know if it is WELL-DEFINED? That's what code reviews and walkthru's and software inspections are for. There are no absolutes. The code must fit the application, the department/company producing it, and must be maintainable as needed. That last part is where the predictability of the code structure pays off. As long as the previous coders keep the same style thruout a program, I can learn it much faster than if there is a jumble of styles (even if they all follow the se-se rule!). It is not the multiple exits that are directly harmful. In contrast, it is the well-defined structure that leads me to know how it exits so I can concentrate on the conditional clause which is application specific. I don't have to see the whole routine every time. Dijkstra may not agree with me, but goto's are not bad or good, but arbitrary use of goto's is always bad. -- Ed Prochak Magic Interface, Ltd. 440-498-3702 -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-10 0:00 ` prochak @ 1998-09-11 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-11 0:00 UTC (permalink / raw) In article <6t9d4k$tdt$1@nnrp1.dejanews.com>, <prochak@my-dejanews.com> wrote: > >A certain amount of this is the old maxim: everything in moderation. Hey, there's an argument for the "yes" vote if ever I heard one. :-) -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` sureshvv 1998-09-10 0:00 ` prochak @ 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) sureshvv@hotmail.com writes: > Well said. The multi-return structure enables you to separate > code in small independent blocks, each of which may be examined > and understood with less interference from surrounding blocks. > The se-se structure creates large blocks, requiring more > context information. Not only that, but prohibiting early returns from a subprogram means you have to figure how to navigate to the end of the subprogram without doing anything else. This is mental work that you wouldn't have to do otherwise. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Samuel Mize 1998-09-09 0:00 ` sureshvv @ 1998-09-10 0:00 ` Tim Ottinger [not found] ` <01bddccc$98b2dda0$ca3aea9e@tom> 1 sibling, 1 reply; 510+ messages in thread From: Tim Ottinger @ 1998-09-10 0:00 UTC (permalink / raw) Samuel Mize wrote: > If someone uses Tagalog or Mayan words as identifiers, he (or she, in > all cases) would understand his own code easily. However, it would be > hard and error-prone for others from a typical project team to > understand it. > > This is similar to someone who understands clearly what he intends the > code to do, but expresses it in a way that is not clear to a reader. > > An appeal to clarity of thought won't shape up that person's code; his > thoughts are perfectly clear, just complex. now, wait a minute here. Obscurity and complexity are not the same thing. I've seen simple code written in obscure ways. There is a mighty big gulf there. Now, complexity can obscure to be sure, but there are many other ways to obscure other than being complex. > In fact, one could argue that some obscure code comes from too MUCH > clarity of thought. I would never accept this argument. I would say that sometimes simple solutions are not obvious. That's when clarity of exposition takes over. But clarity of thought does not cause one to write obscure code. What does happen, by the way, is that a reader may see a problem as being unrealistically simple. In MT programs, for example, they might not understand how to solve the problems caused by race conditions and update anomalies, and may not even understand the problems. To them, the multi-threaded code seems needlessly complex and overdesigned. In reality, it's probably as simple as it can be given the requirements. The obscurity is not caused by clarity of thought on the part of the writer, but by cloudiness of thought on the part of the reader. While generalization is a valuable skill, overgeneralization is not. tim ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <01bddccc$98b2dda0$ca3aea9e@tom>]
* Re: Software landmines (loops) [not found] ` <01bddccc$98b2dda0$ca3aea9e@tom> @ 1998-09-10 0:00 ` Tim Ottinger 0 siblings, 0 replies; 510+ messages in thread From: Tim Ottinger @ 1998-09-10 0:00 UTC (permalink / raw) Nicholas Kitchener wrote: > Complexity is in the mind of the developer - a system is not complex > it just has a definition and exists. I would argue completely to the contrary. I would say that obscurity is in the mind of the developer, but that complexity is a very real thing. It involves he number of entities in a system, and the number of interconnections between them: explicit and implicit. If you were to weight the complexity of a system, I'd consider all implicit interconnections between entities (modules and data items) to be double the weight of all explicit ones, and the number of connections to be double the weight of the number of entities. Eventually we'd have to visit Brad Cox's idea of "surface area" also. It's key to the way that we reduce *apparent* complexity. Obscurity is how easy it is to understand functioning. If there is a lot of apparent complexity, then obscurity results. But obscurity can result from other causes not related to complexity. Let's try to to keep these two concerns separate. Obscurity is subjective, but complexity is objective. > One question - does the speed at which a developer can produce or > modify a system affect the developer's perceiption of how complex > the system is? It certainly may affect his idea of how simple it is. It's more familiarity than anything else, I think. Familiarity is absolutely orthogonal to complexity. A programmer may find a complex but very familiar system easy to maintain. It's complex, but easy to work with. There's more that goes into this, but complexity and familiarity are major concerns! > If the documentation, design are clearly described and the code is > commented properly then I think you'll classify the problem as less > complex than one where it's just you can uncommented code. Not true. I'd consider it to be less obscure, though. They're not the same thing at all. > A very good point- I think that many of us have come up against this > in a slightly different form too: managers and commercial bods who > believe that they understand the internals of a system and then they > speak to the client in a technical capacity. Sure. It happens. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Loryn Jenkins 1998-09-09 0:00 ` Samuel Mize @ 1998-09-11 0:00 ` Robert I. Eachus 1998-09-12 0:00 ` Loryn Jenkins 1 sibling, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-11 0:00 UTC (permalink / raw) In article <35F06D6A.91A3D34E@s054.aone.net.au> Loryn Jenkins <loryn@s054.aone.net.au> writes: > It is much more to the point that language is an instrument which > *construes reality*. It is quite inapropriate to claim that thoughts can > be organised outside of the semiotic systems that construct it. Many of the regular contributers to this group will disagree with this statement, some of us more than others. There are people who "think within the lines," and cannot possibly have a thought which cannot be expressed in their native tounge. Exceptional people can think new thoughts and extend the language to fix. This produces progress and also evolution of languages. But the reason I reacted to this statement is that compiler designers and especially language developers use techniques which allow them to use one language to manipulate another. The simplest example of this is BNF, used to define the grammars for many programming languages. During the debate in Salem over the notation to be used in Ada 9X to define classes, each side had only to use one or two slides to define their proposal, the rest of the time could be used to describe the anticipated effects of the notation on the thinking of the programmers using it. (Neither proposal was "more powerful," both could be used to create exactly the same class structures, the argument was about the impact of the chosen notation on the thinking processes of the users.) In fact, many of the debates that made it to one of the workshops were exactly in this style, such as the names of the operations in Ada.Finalization. (Result, Initialize, Adjust, Finalize.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-11 0:00 ` Robert I. Eachus @ 1998-09-12 0:00 ` Loryn Jenkins 1998-09-11 0:00 ` alan walkington 0 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-12 0:00 UTC (permalink / raw) Robert I. Eachus wrote: > > In article <35F06D6A.91A3D34E@s054.aone.net.au> Loryn Jenkins <loryn@s054.aone.net.au> writes: > > > It is much more to the point that language is an instrument which > > *construes reality*. It is quite inapropriate to claim that thoughts can > > be organised outside of the semiotic systems that construct it. > > Many of the regular contributers to this group will disagree with > this statement, some of us more than others. Grin :) We're talking at cross-purposes here. Given that I don't want to spend the time explaining my philosophical position on this (ie getting you guys up to speed with linguistics, etc.), I shouldn't have posted it. But I may say that your counter-example isn't a counter-example. One day, if you're interested, I'll try to describe something like this in terms that doesn't carry a whole lot of linguistic baggage. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-12 0:00 ` Loryn Jenkins @ 1998-09-11 0:00 ` alan walkington 1998-09-12 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: alan walkington @ 1998-09-11 0:00 UTC (permalink / raw) Loryn: Ahh, but you DID post it. (And I suppose we are now WAY off topic for this NG :-) ) >One day, if you're interested, I'll try to describe something like this >in terms that doesn't carry a whole lot of linguistic baggage. Within the context of your first post, that is not possible. > It is much more to the point that language is an instrument which > *construes reality*. It is quite inapropriate to claim that thoughts can > be organised outside of the semiotic systems that construct it. ANY terms you use will be organized withing the semiotic system which is used to construe them, and as such will carry their own inevitible linguistic baggage. Ain't this fun? Alan Walkington Sr. Software Engineer U.D.L.P. San Jose ----------------------------------------------------- home: walky@netmagic.net work: alan_walkington@udlp.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-11 0:00 ` alan walkington @ 1998-09-12 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-12 0:00 UTC (permalink / raw) > ANY terms you use will be organized withing the semiotic system which is > used to construe them, and as such will carry their own inevitible > linguistic baggage. > > Ain't this fun? Yes: That's why I studied linguistics! And I do agree with your estimation; that was my point exactly. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <6sjnlu$83l$1@hirame.wwa.c <35EE5F67.80D@gecm.com>]
* Re: Software landmines (loops) [not found] ` <6sjnlu$83l$1@hirame.wwa.c <35EE5F67.80D@gecm.com> @ 1998-09-03 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <35EE5F67.80D@gecm.com>, Malcolm Steel <malcolm.steel@gecm.com> wrote: > >I have largeley ignored this thread, however I would like to ask a >general question that this dicussion demonstrates: >Why are engineers with new/different ideas always shot down without >consideration ? So many times I have seem new thoughts and ideas >attacked without any consideration. A classic move is to quote a book. >It seems books are law, even i they are not always correct (often they >are not !!!). If you are referring to the Martin vs. Coates thing in this thread, then I'll remind you that it is Elliott that shot down Robert's statement about what SP is, and it was Elliott who *asked* for the quotes from the book. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell @ 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Phil Goodwin ` (4 subsequent siblings) 6 siblings, 0 replies; 510+ messages in thread From: adam @ 1998-09-02 0:00 UTC (permalink / raw) A further thought on this: In article <6simjo$jnh$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > In any case, I note that in this thread nearly every article that advocates > multiple exits evokes either readability, complexity, or naturalness as the > justification. I contend that these are highly subjective things, that are > not shared by all programmers alike. Indeed, what is readable, natural and > simple to me, may be opaque and convoluted to you. I agree with the truth of this, but not with the implication that this makes the arguments invalid. It makes sense to me that code that is more readable, less complex, and more natural (to me) is code that is more maintainable (by me). If this is correct, then it follows that there is no one coding style that will be the most maintainable for *all* programmers who have to read the code. So arguments about whether this or that style is better may well be pointless. If that's the case, then the only real basis for arguing is that we should program in the way that will have the best chance of being maintainable by the greatest number of programmers who might be maintaining the code. This would indicate that the only arguments that are useful are those that are based on empirical studies of what people consider more "natural"---something like an opinion poll, I guess. That would mean that all the theoretical arguments about "loss of state information" or "goto's going to an undefined place" or "fractional loop iterations" or whatever are irrelevant. However, in this thread, we've had lots of attempts at logic and theory to demonstrate why one style is better than the other, and just one reference to any empirical study. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` adam @ 1998-09-02 0:00 ` Phil Goodwin 1998-09-02 0:00 ` Matthew Heaney ` (3 subsequent siblings) 6 siblings, 0 replies; 510+ messages in thread From: Phil Goodwin @ 1998-09-02 0:00 UTC (permalink / raw) Comments interspersed... In article <6simjo$jnh$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > mfinney@lynchburg.net wrote in message ... > > >And, as far as maintainability is concerned, I strictly use tree-structured > >programming and have *never* found it to be a maintenance problem. > >Sure, sometimes code transformations are required during maintenance, > >but they are sometimes required during coding. So what? There is no > >way to write code that never requires code transformations during > >maintenance, and trying to do so just makes the code harder to > >understand and ultimately increases maintenance cost. Far better is > >to endevour to reach 0 bugs so that maintenance is never required. > >Not easy, perhaps, but it is getting closer and closer every day. I > >personally am running somewhere around 0.0001 and 0.0002 errors > >per line of code -- prior to quality assurance getting the code. Mike, I wish I'd written this... > Reaching zero bugs may not have that big an impact on maintenance, since > much of maintenance has to do with changes to the requirements. Granted. > In any case, I note that in this thread nearly every article that advocates > multiple exits evokes either readability, complexity, or naturalness as the > justification. I contend that these are highly subjective things, that are > not shared by all programmers alike. Indeed, what is readable, natural and > simple to me, may be opaque and convoluted to you. I also contend that > these issues are somewhat emotional, as evidenced by the terms such as > "twist", "warp", "bend", "religious argument", etc. that have also been used > in this thread. Emotional arguments have been made on both sides. It is unfortunate since it obfuscates the discussion. I suggest that from here on out we eschew obfuscation. > Finally, I contend that the factors in favor of using a > single-entry/single-exit style are, on the other hand, quite concrete and > demonstrable. It has been shown that adhering to a structured style > facilitates both resource management and error processing. It has also > been shown that a multiple exit style is vulnerable to redundant code, and > code for recovery of state. It has also been shown that in some circumstances SE/SE can introduce redundant code and that it also requires code for maintenance of state. In general these problems are less pronounced with SE/SE and most often the benefits outweigh the costs. Sometimes, however, it's really best to do what's easiest until you run into a compelling reason not to. > So, it seems what we have here is "gut feelings" warring against empirical > data. I can understand why the gut reaction is so strong; multiple exits > are *eaiser* to write; and are, for some, easier to read. But those are not > the only, or even the most important, criteria for evaluating the quality of > a design. Maintainability is an issue too, and sometimes an overriding one. I think that you're overstating the case. It only makes sense to design code to be amenable to a particular kind of change if there is some reason to think that changes of that kind will actually occur. > In the end, the decision to use a structured style is a tradeoff. There are > benefits, and there are costs. And there are certainly situations in which > the costs outweight the benefits (e.g. quick an dirty programs that have > short lifetimes and require little maintenance during their life). It is > also true, however, that for a very large set of circumstances, the benefits > outweigh the costs. Now, that I agree with, wholeheartedly. I just want to avoid incurring a cost for a benifit that I will never actually use. Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin ` (2 preceding siblings ...) 1998-09-02 0:00 ` Phil Goodwin @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` adam ` (2 subsequent siblings) 6 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > Finally, I contend that the factors in favor of using a > single-entry/single-exit style are, on the other hand, quite concrete > and demonstrable. I contend that the factors in favor of using multiple returns are quite concrete and demonstrable. My argument concerns the complexity of the decision table for the loop predicate. Adding a flag doubles the number of states. > It has been shown that adhering to a structured style facilitates both > resource management and error processing. It has been shown that this is a specious argument. Automatic finalization of a controlled object guarantees that resources get released, no matter how or when the subprogram or loop terminates. > It has also been shown that a multiple exit style is vulnerable to > redundant code, and code for recovery of state. Without being able to exit from the middle of a loop, I'd have to do this to terminate a read sequence: Get (N); while N /= 0 loop <process N> Get (N); end loop; So it's the structured approach which causes the redundancy, becuase Get must be called twice. Using the an exit from the middle: loop Get (N); exit when N = 0; <process N> end loop; eliminates the redundancy. > So, it seems what we have here is "gut feelings" warring against > empirical data. I can understand why the gut reaction is so strong; > multiple exits are *eaiser* to write; and are, for some, easier to > read. But those are not the only, or even the most important, > criteria for evaluating the quality of a design. Maintainability is > an issue too, and sometimes an overriding one. But Robert, this isn't just "gut reaction." Researchers empirically demonstrated that programmers using an exit from the middle produced fewer errors: Cognitive Strategies and Looping Constructs: An Empirical Study Soloway, Bonar, Ehrlich CACM, Nov 83, Vol 26, No 11, p853-860 Yes, indeed, multiple exits are easier to write, because that construct has a better cognitive fit. I don't find your maintenance argument convincing. You seem to be arguing that we should all wear six-fingered gloves, because some day we might grow another finger. I have provided examples that mitigate any resource management issues that would arise because of early termination. These are techniques you'll have to use anyway, because of unhandled exceptions. > In the end, the decision to use a structured style is a tradeoff. There are > benefits, and there are costs. And there are certainly situations in which > the costs outweight the benefits (e.g. quick an dirty programs that have > short lifetimes and require little maintenance during their life). It is > also true, however, that for a very large set of circumstances, the benefits > outweigh the costs. I am not convinced by your argument about higher maintenance costs. I am convinced by real data that shows real programmers made more real mistakes when using the approach you advocate. Here's the reference one more time: Cognitive Strategies and Looping Constructs: An Empirical Study Soloway, Bonar, Ehrlich CACM, Nov 83, Vol 26, No 11, p853-860 ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >Without being able to exit from the middle of a loop, I'd have to do >this to terminate a read sequence: > > Get (N); > > while N /= 0 loop > > <process N> > > Get (N); > > end loop; > >So it's the structured approach which causes the redundancy, becuase Get >must be called twice. Consider: do { Get(N); if (N) <process N> } while (N); Structured programming allows the loop condition to be either at the top or the bottom. > >But Robert, this isn't just "gut reaction." Researchers empirically >demonstrated that programmers using an exit from the middle produced >fewer errors: > >Cognitive Strategies and Looping Constructs: An Empirical Study >Soloway, Bonar, Ehrlich >CACM, Nov 83, Vol 26, No 11, p853-860 Granted. I accept that as input to the cost side. However, as far as I know the study does not take into account the long term benefits of structured programming; which has been the major thrust of my argument. Indeed, my argument has taken as given the assertion that multiple exits are easier to write and read (for some). My argument says that there are other concerns, such as maintenance, that also must be taken into account. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` dennison 1998-09-02 0:00 ` Dan Higdon 2 siblings, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-02 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > >So it's the structured approach which causes the redundancy, becuase Get > >must be called twice. > > Consider: > > do { > Get(N); > if (N) > <process N> > } while (N); > > Structured programming allows the loop condition to be either at the top or > the bottom. The thing I dislike about the above code fragment is that N gets tested twice. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Patrick Logan 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-02 0:00 ` Robert Martin 1 sibling, 2 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: : "Robert Martin" <rmartin@oma.com> writes: : > >So it's the structured approach which causes the redundancy, becuase Get : > >must be called twice. : > : > Consider: : > : > do { : > Get(N); : > if (N) : > <process N> : > } while (N); : > : > Structured programming allows the loop condition to be either at the top or : > the bottom. : The thing I dislike about the above code fragment is that N gets tested : twice. If you memoize the result of the first test, then the second test is about as fast as can be... boolean test; ... do { ... test = N; if (test) ... } while (test); This does not add a new state to a decision table. It provides a mnemonic for the test condition. The redundant test is minimal compared to the other work in the loop, not to mention the rest of the application. If you are writing small methods anyway, then it is very clear what is occurring. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan @ 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Patrick Logan 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1 sibling, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) Patrick Logan <plogan@user2.teleport.com> writes: > If you memoize the result of the first test, then the second test is > about as fast as can be... > > boolean test; > ... > do { > ... > test = N; > if (test) > ... > } while (test); > > This does not add a new state to a decision table. It provides a > mnemonic for the test condition. The redundant test is minimal > compared to the other work in the loop, not to mention the rest of the > application. If you are writing small methods anyway, then it is very > clear what is occurring. The thing I dislike about this code fragment is that it creates an extra variable. I still prefer to do this: for (;;) { Get (N); if (N == 0) break; <process N> } No extra variable is required. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: : Patrick Logan <plogan@user2.teleport.com> writes: : > If you memoize the result of the first test, then the second test is : > about as fast as can be... : > : > boolean test; : > ... : > do { : > ... : > test = N; : > if (test) : > ... : > } while (test); : > : > This does not add a new state to a decision table. It provides a : > mnemonic for the test condition. The redundant test is minimal : > compared to the other work in the loop, not to mention the rest of the : > application. If you are writing small methods anyway, then it is very : > clear what is occurring. : The thing I dislike about this code fragment is that it creates an extra : variable. : I still prefer to do this: : for (;;) { : Get (N); : if (N == 0) break; : <process N> : } : No extra variable is required. I am not going to argue *strongly* for or against either style. Just keep the loop to ten lines, as in these examples, and I can see easily what it does. If you instead have a longer loop with more conditionals, etc. then I need to spend more effort examining the loop to see if there is more than one place the "infinite" loop actually terminates. So I can sum up my position is that size *does* matter! -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-03 0:00 ` Patrick Logan 1 sibling, 1 reply; 510+ messages in thread From: Ole-Hjalmar Kristensen @ 1998-09-03 0:00 UTC (permalink / raw) Patrick Logan <plogan@user2.teleport.com> writes: > In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: > : "Robert Martin" <rmartin@oma.com> writes: > > : > >So it's the structured approach which causes the redundancy, becuase Get > : > >must be called twice. > : > > : > Consider: > : > > : > do { > : > Get(N); > : > if (N) > : > <process N> > : > } while (N); > : > > : > Structured programming allows the loop condition to be either at the top or > : > the bottom. > > : The thing I dislike about the above code fragment is that N gets tested > : twice. > > If you memoize the result of the first test, then the second test is > about as fast as can be... > > boolean test; > ... > do { > ... > test = N; > if (test) > ... > } while (test); > > This does not add a new state to a decision table. It provides a > mnemonic for the test condition. The redundant test is minimal > compared to the other work in the loop, not to mention the rest of the > application. If you are writing small methods anyway, then it is very > clear what is occurring. > > -- > Patrick Logan (H) mailto:plogan@teleport.com > (W) mailto:patrickl@gemstone.com > http://www.gemstone.com If you believe that this assingnment makes the second test faster in the general case, you are very wrong. It may even make the loop slower, depending on the optimizer. I've had this happen to me more than once. I have to side with the middle exit guys in this case. One of the reasons why I like the Ada loop construct. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Ole-Hjalmar Kristensen @ 1998-09-03 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Ole-Hjalmar Kristensen <ohk@tfdt-o.nta.no> wrote: : If you believe that this assingnment makes the second test faster in : the general case, you are very wrong. It may even make the loop : slower, depending on the optimizer. I've had this happen to me more : than once. I have to side with the middle exit guys in this : case. One of the reasons why I like the Ada loop construct. More than that, I believe it is readable and maintainable and fast enough. I'd wait for a profiler to tell me this is where I should spend any more effort on performance. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Patrick Logan @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: > >> >So it's the structured approach which causes the redundancy, becuase Get >> >must be called twice. >> >> Consider: >> >> do { >> Get(N); >> if (N) >> <process N> >> } while (N); >> >> Structured programming allows the loop condition to be either at the top or >> the bottom. > >The thing I dislike about the above code fragment is that N gets tested >twice. For good reason. There are two independent program states that depend upon N. One is whether or not we call process, and the other is whether or not the loop exits. Now, we could combine them as: for(;;) { Get(N); if (N) <process N> else break; } This is certainly more efficient; and if efficiency is what you need then you'd better do this. However, the efficiency costs us something. It couples the two independent program states. This increased coupling makes it difficult to make changes that are independent of N. For example, suppose I need to flush some buffers at the end of each iteration. I do this by calling 'flush'. I must write this as: for(;;) { Get(N); if (N) <process N> flush(); } else { break; flush(); } } Whereas if I had lived with the double test: do { Get(N); if (N) { <process N> } flush(); } while (N); Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin ` (2 more replies) 0 siblings, 3 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> writes: > For good reason. There are two independent program states that depend upon > N. One is whether or not we call process, and the other is whether or not > the loop exits. > > Now, we could combine them as: > > for(;;) > { > Get(N); > if (N) > <process N> > else > break; > } > > This is certainly more efficient; and if efficiency is what you need then > you'd better do this. Boy oh boy, Robert, we must come from different programming schools! The dangerous thing about the code fragment above is that the else part can get lost, especially if <process N> is long-ish. My philosophy is, handle the simple case first, then bail out: for (;;) { Get (N); if (!N) break; <process N> } When we fetch N, we're looking for that one special value, 0, that signals end of input. I prefer the organization above, because it emphasizes the special case. I don't like how you did it, because it treats the break case and the <process N> case as equals - but they are not. Your organization is telling me that N is always an integer. Process the integer one way if it's 0, and process it another way if it's positive. I feel that this is very misleading. When you <process N>, N really is a (positive) integer. But when N has the value 0, it's an end-of-input indicator (which just happens to be represented as an integer). This point is perhaps made more clear by using an end-of-input indicator that's not an integer: begin loop Get (N); <process N>; end loop; exception when End_Error => null; end; When the user presses CNTL-D, the OS delivers <EOF> to the application, which Ada.Text_IO turns into an End_Error exception. Note how similar it is to loop Get (N); exit when N = 0; <process N>; end loop; > For example, suppose I need to flush some buffers at the end of each > iteration. I do this by calling 'flush'. I must write this as: > > for(;;) > { > Get(N); > if (N) > > <process N> > flush(); > } > else { > break; > flush(); > } > } I'm confused by your example. How does flush() get called in the else part, if it's immediately preceeded by a break? Shouldn't it be just for(;;) { Get(N); if (N) <process N> flush(); } else { break; } } If we handle the special case specially: for(;;) { Get(N); if (!N) break; <process N> flush(); } Flush gets called following <process N>, just as it does in your original fragment. > Whereas if I had lived with the double test: > > do { > Get(N); > if (N) { > <process N> > } > flush(); > } while (N); This is not the same as your original fragment, because flush gets called even if N is 0. Which behavior did you intend? ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Biju Thomas ` (2 more replies) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 2 siblings, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >"Robert Martin" <rmartin@oma.com> writes: >> for(;;) >> { >> Get(N); >> if (N) >> <process N> >> else >> break; >> } >> > >Boy oh boy, Robert, we must come from different programming schools! And that's part of the point I'm trying to make. There is no single readability standard. We all come from different schools in some way or another. So what you think is readable, will not be as readable to me, or to someone else. > >The dangerous thing about the code fragment above is that the else part >can get lost, especially if <process N> is long-ish. > >My philosophy is, handle the simple case first, then bail out: > > for (;;) > { > Get (N); > > if (!N) break; > > <process N> > } Ask yourself why 'break' is the most important concept of this function? Why is it more important to get the exceptional conditions out of the way first rather than to get right into the actual purppose of the function. I prefer a style that moves into the real action of the function as quickly as possible, while deferring the exceptional conditions to the end. Consider this, would you prefer that catch statements *precede* try blocks? catch(memerr) { } catch(fileerr) { } try { } Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Biju Thomas 1998-09-03 0:00 ` Phil Goodwin 1998-09-04 0:00 ` Ell 2 siblings, 0 replies; 510+ messages in thread From: Biju Thomas @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote: > > Matthew Heaney wrote in message ... > >"Robert Martin" <rmartin@oma.com> writes: > > >> for(;;) > >> { > >> Get(N); > >> if (N) > >> <process N> > >> else > >> break; > >> } > > > >My philosophy is, handle the simple case first, then bail out: > > > > for (;;) > > { > > Get (N); > > > > if (!N) break; > > > > <process N> > > } > > Why is it more important to get the exceptional conditions out of the way > first rather than to get right into the actual purppose of the function. Don't you feel more secure when you code like this? When I take care of the exceptional condition first and proceed to the actual process after ensuring that everything is well, I don't have to worry about exceptional and special cases anymore. This may be an illusion, but helps to keep the mind focussed on the actual purpose of the function. This is somewhat similar to ensuring pre-conditions in a function. > I prefer a style that moves into the real action of the function as quickly > as possible, while deferring the exceptional conditions to the end. > > Consider this, would you prefer that catch statements *precede* try blocks? > > catch(memerr) > { > } > catch(fileerr) > { > } > try > { > } This is a different situation. Here, you don't know that the exceptional condition has occured, whereas in the previous case, you know that it occured, and postpone the appropriate actions to a different place in the code. So, these cases are not comparable. Biju Thomas ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Biju Thomas @ 1998-09-03 0:00 ` Phil Goodwin 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Ell 2 siblings, 1 reply; 510+ messages in thread From: Phil Goodwin @ 1998-09-03 0:00 UTC (permalink / raw) In article <6sm6md$3fh$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Matthew Heaney wrote in message ... > >My philosophy is, handle the simple case first, then bail out: > > > > for (;;) > > { > > Get (N); > > > > if (!N) break; > > > > <process N> > > } > > Ask yourself why 'break' is the most important concept of this function? > Why is it more important to get the exceptional conditions out of the way > first rather than to get right into the actual purpose of the function. You are absolutely right about readability Robert, I read this as "!N is a precondition of <process N>. It IS important to know what the preconditions of the function are before you get into the actual purpose of the function. > I prefer a style that moves into the real action of the function as quickly > as possible, while deferring the exceptional conditions to the end. > > Consider this, would you prefer that catch statements *precede* try blocks? > > catch(memerr) > { > } > catch(fileerr) > { > } > try > { > } No but I generally prefer that 'if' statements precede their blocks. Perl lets you do it either way which is nice sometimes but in general you really want to know about all the assumptions that are being made up front. Phil -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Phil Goodwin @ 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Jeffrey C. Dege 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-04 0:00 UTC (permalink / raw) Phil Goodwin<pgoodwin@my-dejanews.com> writes: > > Matthew Heaney wrote in message ... > > >My philosophy is, handle the simple case first, then bail out: > > > > > > for (;;) > > > { > > > Get (N); > > > > > > if (!N) break; > > > > > > <process N> > > > } > > > > Ask yourself why 'break' is the most important concept of this > > function? Why is it more important to get the exceptional conditions > > out of the way first rather than to get right into the actual purpose > > of the function. > > You are absolutely right about readability Robert, I read this as "!N > is a precondition of <process N>. It IS important to know what the > preconditions of the function are before you get into the actual > purpose of the function. Perhaps I should have included a comment that said, /* Process a stream of integers. * * The stream is terminated by the value 0. */ The problem just easily could have been: /* Process a stream of characters. * * The stream is terminated by the value EOF. */ for (;;) { Get (C); if (C == EOF) break; <process C> } My point is that this is a common kind of problem. You process a stream of items, but one of those items is special, and means "no more items follow." I argue that the formulation above is the most natural way to implement this kind of problem. Researchers showed empirically that using the construction above, programmers produced fewer errors: Cognitive Strategies and Looping Constructs: An Empirical Study Soloway, Bonar, Ehrlich CACM, Nov 83, Vol 26, No 11, p853-860 As they say, the proof is in the pudding, not the pudding recipe. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Matthew Heaney @ 1998-09-04 0:00 ` Jeffrey C. Dege 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Logan 0 siblings, 2 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-04 0:00 UTC (permalink / raw) On Fri, 04 Sep 1998 05:07:36 GMT, Matthew Heaney <matthew_heaney@acm.org> wrote: > > /* Process a stream of characters. > * > * The stream is terminated by the value EOF. > */ > for (;;) { > Get (C); > > if (C == EOF) break; > > <process C> > } > >My point is that this is a common kind of problem. You process a stream >of items, but one of those items is special, and means "no more items >follow." I argue that the formulation above is the most natural way to >implement this kind of problem. What are the alternatives? Get(C); while (C != EOF) { <process C> Get(C) } while (Get(C), C != EOF) { <process C> } goto LABEL5; do { <process C> LABEL5: Get(C); } while (C != EOF); boolean done = false; while (!done) { Get(C); if (C == EOF) done = true; else { <process C> } } jump_buf jumpBuffer; if (!setjmp(jumpBuffer)) { for (;;) { Get(C); if (C==EOF) longjmp(1); <process C> } } >Researchers showed empirically that using the construction above, >programmers produced fewer errors: > >Cognitive Strategies and Looping Constructs: An Empirical Study >Soloway, Bonar, Ehrlich >CACM, Nov 83, Vol 26, No 11, p853-860 > >As they say, the proof is in the pudding, not the pudding recipe. > -- "Necessity is the mother of invention" is a silly proverb. "Necessity is the mother of futile dodges" is much nearer the truth. -- Alfred North Whitehead ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Jeffrey C. Dege @ 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Logan 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) In comp.object Jeffrey C. Dege <jdege@jdege.visi.com> wrote: : -- : "Necessity is the mother of invention" is a silly proverb. "Necessity : is the mother of futile dodges" is much nearer the truth. : -- Alfred North Whitehead We can take that the tone here is not Whitehead's because you are including your own material in these supposed quotes. This is highly dishonest, and disingenuous in my opinion. It's a shame that you smear the name of Whitehead and unjustifiably associate him with your craftite beliefs as you repeatedly do. Whitehead deserves much better than to be the poster guy for craftism, empiricism, and your backward brand of pragmatism (c/e/p). Of course "necessity is the mother of futile dodges", as it is "necessity"! "Necessity" can only futilely be avoided because by definition it is "necessity" (necessary). OTOH that doesn't mean that by addressing "necessity" we can't thereby gain greater freedom, which is what often happens. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Jeffrey C. Dege 1998-09-04 0:00 ` Ell @ 1998-09-04 0:00 ` Patrick Logan 1 sibling, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-04 0:00 UTC (permalink / raw) In comp.object Jeffrey C. Dege <jdege@jdege.visi.com> wrote: : > for (;;) { : > Get (C); : > if (C == EOF) break; : > <process C> : > } : What are the alternatives? [other alternatives omitted] And then there is... void processInput() { Get(C); if (EOF != C) { <process C> processInput(); } } ...which works fine if your compiler compiles tail recursion into efficient code. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Biju Thomas 1998-09-03 0:00 ` Phil Goodwin @ 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Ell ` (3 more replies) 2 siblings, 4 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: >Matthew Heaney wrote in message ... >> >>"Robert Martin" <rmartin@oma.com> writes: >>> >>> for(;;) >>> { >>> Get(N); >>> if (N) >>> <process N> >>> else >>> break; >>> } >>> >>Boy oh boy, Robert, we must come from different programming schools! >And that's part of the point I'm trying to make. There is no single >readability standard. We all come from different schools in some way or >another. So what you think is readable, will not be as readable to me, or >to someone else. But generally it is possible to get a plurality or majority to agree on what is readable. In most cases readability decisions are made by polling project developers where I work and have worked in the past. You have to go with something, why not the plurality, or majority? >>The dangerous thing about the code fragment above is that the else part >>can get lost, especially if <process N> is long-ish. >> >>My philosophy is, handle the simple case first, then bail out: >> >> for (;;) >> { >> Get (N); >> >> if (!N) break; >> >> <process N> >> } Makes imminent sense to me. >Ask yourself why 'break' is the most important concept of this function? >Why is it more important to get the exceptional conditions out of the way >first rather than to get right into the actual purppose of the function. > >I prefer a style that moves into the real action of the function as quickly >as possible, while deferring the exceptional conditions to the end. I advocate that in general we should test to see that pre-conditions are met, and if they aren't, bail. Why even try to process if pre-conditions have not been met? if (!pre-condition) bail else do_processing() endif Elliott >Consider this, would you prefer that catch statements *precede* try blocks? > >catch(memerr) >{ >} >catch(fileerr) >{ >} >try >{ >} Testing for pre-conditions before processing is not equal to what the try/catch idiom is about. 'catch' is about catching *exceptions* which occur *within* 'try' processing. It is not about testing *pre-conditions* to what is necessary for successfully processing in a block. The difference is that exceptions in processing may legitimately occur even though pre-conditions for processing have been met. N'est ce pas? Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell @ 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins ` (2 subsequent siblings) 3 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-04 0:00 UTC (permalink / raw) "Robert Martin" <rmartin@oma.com> wrote: [ In reference to the idea of testing for pre-conditions before processing, RCM, in part, said the following: ] >Consider this, would you prefer that catch statements *precede* try blocks? > >catch(memerr) >{ >} >catch(fileerr) >{ >} >try >{ >} Testing for pre-conditions before processing is not equal to what the try/catch idiom is about. 'catch' is about catching *exceptions* which occur *within* 'try' processing. It is not about testing *pre-conditions* to what is necessary for successfully processing in a block. The difference is that exceptions in processing may legitimately occur even though pre-conditions for processing have been met. N'est ce pas? Elliott ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Ell @ 1998-09-05 0:00 ` Loryn Jenkins 1998-09-06 0:00 ` Charles Hixson [not found] ` <35F074C9.E10C <35F2E907.594CD023@earthlink.net> 1998-09-10 0:00 ` Tim Ottinger 3 siblings, 1 reply; 510+ messages in thread From: Loryn Jenkins @ 1998-09-05 0:00 UTC (permalink / raw) > Testing for pre-conditions before processing is not equal to what the > try/catch idiom is about. Very true. > I advocate that in general we should test to see that pre-conditions > are met, and if they aren't, bail. Why even try to process if > pre-conditions have not been met? > > if (!pre-condition) > bail > else > do_processing() > endif This is an interesting approach to DBC: specify your preconditions and write your function to ensure the preconditions are met, else bail. However, I think Meyer's approach to DBC is more powerful than this. Basically, Meyer's approach is to make the calling routine check the preconditions, not the called routine. Imagine the following routine: put (v: SOME_ENTITY) is require not has (v) -- where `has' tests by OID. do ... ensure ... end I would argue that the calling routine is in the best position to check this precondition. For example, the calling routine may be creating an object, then inserting it into this object. It doesn't have to call `has' to make sure the object isn't yet inserted. Whereas, another client may have to check it. Checking for your own preconditions is simply defensive programming. The problem is that a calling class has no way of knowing (beforehand) whether the routine is going to work or not. Unless it too checks the preconditions, in which case your software is starting to be weighed down by multiple, repeated checks for consistency. And this is what preconditions and DBC is all about doing: eliminating uncertainty; eliminating the redundant code bloat of redundant error checking. On the other hand, if you're not going to expect your client routine to check the precondition, then you *must* handle everything yourself. (ie you shouldn't just *bail.) Why? Because that implies that the client routine is going to have to check *after the fact* whether the routine succeeded or failed. Then it's going to have to do something about it. You see, it would have been better to get the client routine to do its own checking before hand, then *expect* the routine to work. Now, when you observe this approach to DBC, then you gain a powerful insight into a disciplined use of exception handling. (Hint: It's used much less commonly than in the standard idiom apparent in C++ and Java world.) Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-05 0:00 ` Loryn Jenkins @ 1998-09-06 0:00 ` Charles Hixson 1998-09-07 0:00 ` Loryn Jenkins 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) Loryn Jenkins wrote: ... > This is an interesting approach to DBC: specify your preconditions and > write your function to ensure the preconditions are met, else bail. > > However, I think Meyer's approach to DBC is more powerful than this. > Basically, Meyer's approach is to make the calling routine check the > preconditions, not the called routine. ... > Loryn Jenkins But frequently the programmer does not have the choice of what language is to be used. E.g., most of my work for the last couple of years has been in various flavors of Visual Basic. (At least it's lots better than Dartmouth Basic). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-07 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-07 0:00 UTC (permalink / raw) Charles Hixson wrote: > > Loryn Jenkins wrote: > ... > > This is an interesting approach to DBC: specify your preconditions and > > write your function to ensure the preconditions are met, else bail. > > > > However, I think Meyer's approach to DBC is more powerful than this. > > Basically, Meyer's approach is to make the calling routine check the > > preconditions, not the called routine. > ... > > Loryn Jenkins > > But frequently the programmer does not have the choice of what language > is to be used. E.g., most of my work for the last couple of years has > been in various flavors of Visual Basic. (At least it's lots better > than Dartmouth Basic). DBC is a methodological principle. You can use this design mechanism in any language. DBC simply forms a protocol that holds between various routines in the software. You are currently using such a protocol (even if you haven't thought of it in these terms). This is just a different one. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35F074C9.E10C <35F2E907.594CD023@earthlink.net>]
* Re: Software landmines (loops) [not found] ` <35F074C9.E10C <35F2E907.594CD023@earthlink.net> @ 1998-09-07 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-07 0:00 UTC (permalink / raw) In article <35F2E907.594CD023@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: >Loryn Jenkins wrote: >> >> However, I think Meyer's approach to DBC is more powerful than this. >> Basically, Meyer's approach is to make the calling routine check the >> preconditions, not the called routine. > >But frequently the programmer does not have the choice of what language >is to be used. E.g., most of my work for the last couple of years has >been in various flavors of Visual Basic. (At least it's lots better >than Dartmouth Basic). Choice of language doesn't enter into it. A precondition is a condition that must hold for the effects of a routine to be well- defined. If that routine is called without the preconditions being satisfied, then you have a bug in your program. Thus, the caller must either check that the precondition holds, or else verify it by other means. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Ell ` (2 preceding siblings ...) [not found] ` <35F074C9.E10C <35F2E907.594CD023@earthlink.net> @ 1998-09-10 0:00 ` Tim Ottinger 1998-09-10 0:00 ` dewarr 3 siblings, 1 reply; 510+ messages in thread From: Tim Ottinger @ 1998-09-10 0:00 UTC (permalink / raw) Ell wrote: > But generally it is possible to get a plurality or majority to agree > on what is readable. what on earth makes you think that? > In most cases readability decisions are made by > polling project developers where I work and have worked in the past. > You have to go with something, why not the plurality, or majority? This is in direct opposition to your anti-pragmatism post which I read earlier this evening. For that matter, why not join the majority of people who believe se/se is the basis of SP? ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-10 0:00 ` Tim Ottinger @ 1998-09-10 0:00 ` dewarr 1998-09-11 0:00 ` prochak 1998-09-12 0:00 ` Ell 0 siblings, 2 replies; 510+ messages in thread From: dewarr @ 1998-09-10 0:00 UTC (permalink / raw) In article <35F74AEC.21982C2B@oma.com>, Tim Ottinger <ottinger@oma.com> wrote: > Ell wrote: > > But generally it is possible to get a plurality or majority to agree > > on what is readable. > > what on earth makes you think that? > > > In most cases readability decisions are made by > > polling project developers where I work and have worked in the past. > > You have to go with something, why not the plurality, or majority? > > This is in direct opposition to your anti-pragmatism post which > I read earlier this evening. > > For that matter, why not join the majority of people > who believe se/se is the basis of SP? > > For me, the reason it makes sense to simply take majority votes on style issues is that consistency is THE most important issue, much more important than the actual decisions (it's like driving, it really doesn't matter if you drive on the left or right, but it is really important to agree -- this observation thanks to Tarski :-) -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-10 0:00 ` dewarr @ 1998-09-11 0:00 ` prochak 1998-09-12 0:00 ` Ell 1 sibling, 0 replies; 510+ messages in thread From: prochak @ 1998-09-11 0:00 UTC (permalink / raw) In article <6t937n$ep6$1@nnrp1.dejanews.com>, dewarr@my-dejanews.com wrote: > In article <35F74AEC.21982C2B@oma.com>, > Tim Ottinger <ottinger@oma.com> wrote: > > Ell wrote: > > > But generally it is possible to get a plurality or majority to agree > > > on what is readable. > > > > what on earth makes you think that? > > > > > In most cases readability decisions are made by > > > polling project developers where I work and have worked in the past. > > > You have to go with something, why not the plurality, or majority? > > > > This is in direct opposition to your anti-pragmatism post which > > I read earlier this evening. > > > > For that matter, why not join the majority of people > > who believe se/se is the basis of SP? > > > > > > For me, the reason it makes sense to simply take majority > votes on style issues is that consistency is THE most > important issue, much more important than the actual > decisions (it's like driving, it really doesn't matter if > you drive on the left or right, but it is really important > to agree -- this observation thanks to Tarski :-) > Thank goodness somebody else sees the important issue here. As a department or project team, pick a style and stick with it. As an individual (especially a contractor like me), be flexible enough to pick up and use the client's style. To paraphrase an internet programming maxim: be strict in what you write, but flexible in what you read. (see another post of mine on the se-se issue about consistancy) > -----== Posted via Deja News, The Leader in Internet Discussion ==----- > http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum > -- Ed Prochak Magic Interface, Ltd. 440-498-3702 -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-10 0:00 ` dewarr 1998-09-11 0:00 ` prochak @ 1998-09-12 0:00 ` Ell 1998-09-12 0:00 ` dewarr 1 sibling, 1 reply; 510+ messages in thread From: Ell @ 1998-09-12 0:00 UTC (permalink / raw) In comp.object dewarr@my-dejanews.com wrote: : : Tim Ottinger <ottinger@oma.com> wrote: :> :> Ell wrote: :> > :> > But generally it is possible to get a plurality or majority to :> > agree on what is readable. :> what on earth makes you think that? Because I see it happening in all kinds of callective decision making groups. For goodness sake you don't? The bowling team, co-workers headed out to blow steam off on Friday, church groups, tour groups, band members, mob groups, etc, etc. People frequently able to reach majority decisions and if not there's almost always a plurality for one position or another. You all's view that we can know little to nothing for sure, and that one view is as good as another is so hackerish. It's such an on the knees appeal to accept unbridled and in many cases extremely harmful individulism. :> > In most cases readability decisions are made by :> > polling project developers where I work and have worked in the past. :> > You have to go with something, why not the plurality, or majority? :> :> This is in direct opposition to your anti-pragmatism post which :> I read earlier this evening. How? The pragmatist position is the super individualistic one. :> For that matter, why not join the majority of people :> who believe se/se is the basis of SP? What majority? Where? Most on comp.object seem to think it means navigating with discipline - using procedure calls to "meld" multiple returns into a single one. I.e. avoiding one way, non-round trip navigation, entering a block of code from the start. : For me, the reason it makes sense to simply take majority : votes on style issues is that consistency is THE most : important issue, much more important than the actual : decisions (it's like driving, it really doesn't matter if : you drive on the left or right, but it is really important : to agree Wrong headed pragmatism, pure and simple. It's ludicrous on the face of it to say all that matters is making a decision, not the content of the decision itself. That's like saying it's more important that we all decided to poison ourselves, rather than questioning the whole decision. -- this observation thanks to Tarski :-) I'm not surprised. I would be ashamed of this not happy. Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-12 0:00 ` Ell @ 1998-09-12 0:00 ` dewarr 1998-09-12 0:00 ` Charles Hixson 1998-09-14 0:00 ` Ell 0 siblings, 2 replies; 510+ messages in thread From: dewarr @ 1998-09-12 0:00 UTC (permalink / raw) In article <X4tK1.6$VP3.188022798@newsreader.digex.net>, Ell <ell@access1.digex.net> wrote: > >: For me, the reason it makes sense to simply take majority >: votes on style issues is that consistency is THE most >: important issue, much more important than the actual >: decisions (it's like driving, it really doesn't matter if >: you drive on the left or right, but it is really important >: to agree>>> > >Wrong headed pragmatism, pure and simple. > >It's ludicrous on the face of it to say all that matters is making a >decision, not the content of the decision itself. That's like saying it's >more important that we all decided to poison ourselves, rather than >questioning the whole decision. What on earth has poisoning ourselves got to do with the matter at hand, and what on earth makes you think I was suggesting that the majority decision is right for all things. If you must bring in totally irrelevant details like this, one can only assume you have no real argument! The issue I was raising was purely with respect to style issues. I find most arguments about style pretty silly. They are typically one person who is sure they are right but have no data to back up their opinions arguing with another person who argues something else and is sure they are right, but also has no data. I will repeat that what I *really* find important is consistency. When a team writes a program, it should be impossible to tell one person's style from another. This has many advantages, it means that it is much easier to read the code, since you only have to adjust to one style, and that code is more interchangable because people don't feel they own pieces of the code. Egotistical code ownership is definitely a negative factor in achieving high and reliable productivity from a programming group. That being said, to achieve consistency, you need to discuss various issues for sure, a majority decision taken without discussion is an uninformed decision, but after that decision using a majority vote is just fine, and everyone needs to agree in advance to be bound by this decision. This means that everyone has to agree in advance that consistency is more important than their pet programming style. This is particularly useful when the argument is about a totally idiotic issue like what style of {} to use in C code, or how many characters to indent. Of course some of these simple things can be handled by tools (and most certainly can be checked by a tool), but more complex style rules are not always susceptible to tool checking, because all but the simplest kind of rules tend to have legitimate exceptions. It is dealing with these exceptions that often causes trouble. For example, people know that gotos and spaghetti code are a bad thing, but they wouldn't recognize what is and what is not spaghetti code if it was wound around their fork, so they have to fall back on an absolute rule of no gotos. In any case the important thing for any project, really just a *starting* point towards achieving a well managed project, is to agree on a complete set of style guidelines/rules for coding. I am always amazed to find serious mission critical projects being coded in an anarchic style in environments where programmers would not be willing to touch code written by their colleages. I find that completely untenable. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-12 0:00 ` dewarr @ 1998-09-12 0:00 ` Charles Hixson 1998-09-13 0:00 ` dewarr 1998-09-14 0:00 ` Ell 1 sibling, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-12 0:00 UTC (permalink / raw) dewarr@my-dejanews.com wrote: > > In article <X4tK1.6$VP3.188022798@newsreader.digex.net>, > Ell <ell@access1.digex.net> wrote: > > > >: For me, the reason it makes sense to simply take majority > >: votes on style issues is that consistency is THE most > >: important issue, much more important than the actual > >: decisions (it's like driving, it really doesn't matter if > >: you drive on the left or right, but it is really important > >: to agree>>> > > > >Wrong headed pragmatism, pure and simple. > > > >It's ludicrous on the face of it to say all that matters is making a > >decision, not the content of the decision itself. That's like saying it's > >more important that we all decided to poison ourselves, rather than > >questioning the whole decision. > > What on earth has poisoning ourselves got to do with the > matter at hand, and what on earth makes you think I was > suggesting that the majority decision is right for all > things. If you must bring in totally irrelevant details > like this, one can only assume you have no real argument! > Some style choices ARE important, but in most agreement is more important than which style, and in some agreement is the only matter of importance (and in some, even that isn't important). I haven't seen anybody defending spaghetti code recently. This is a (practically universal) style (different things were being optimised), but agreement wasn't sufficient to maintain it. Whether or not the names of constants were written in all-caps is a style (actually, it's one that I, personally, don't like). It is the majority style in some camps of the computer community (C descendant languages, particularly). I don't think that it's important as long as that form is not used by anything else. Any good text editor do a set of global transforms on the code to match the style of the person who is using it, with NO IMPACT on anything else (actually, if the header files are shared with people using differing coding styles, then one set of the constant's names would need to be defined in terms of the other set of the constant's names (e.g. #define stdIn STDIN ), but this would only be needed in languages where the case of the variable name is a semantic marker, so Ada, for example, wouldn't need a comparable statement change). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-12 0:00 ` Charles Hixson @ 1998-09-13 0:00 ` dewarr 0 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-09-13 0:00 UTC (permalink / raw) In article <35FB19F8.D3AAEC2D@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: > dewarr@my-dejanews.com wrote: > > > Some style choices ARE important, but in most agreement is more > important than which style, and in some agreement is the only matter of > importance (and in some, even that isn't important). > I haven't seen anybody defending spaghetti code recently. This is a > (practically universal) style (different things were being optimised), > but agreement wasn't sufficient to maintain it. Whether or not the > names of constants were written in all-caps is a style (actually, it's > one that I, personally, don't like). It is the majority style in some > camps of the computer community (C descendant languages, particularly). > I don't think that it's important as long as that form is not used by > anything else. Any good text editor do a set of global transforms on > the code to match the style of the person who is using it, with NO > IMPACT on anything else (actually, if the header files are shared with > people using differing coding styles, then one set of the constant's > names would need to be defined in terms of the other set of the > constant's names (e.g. #define stdIn STDIN ), but this would only be > needed in languages where the case of the variable name is a semantic > marker, so Ada, for example, wouldn't need a comparable statement > change). > It is incorrect in my view to think that automatic reformatters can solve the problem. First, there are many style rules that are very difficult to automate, especially if they all have an implied "but this does not apply in special cases, and you need human intelligence to determine those cases". Second, if people continue to use their own styles, you still have the phenomenon of balkanization of the coding effort, and people prefer to use their own style. Even if you have a totally invertible transformer, which is in fact difficult to do, for example, the all CAPS style is not automatically convertible to mixed case: It is easy to go from UNIX_Package_Interface to UNIX_PACKAGE_INTERFACE. But it is harder work to go in the opposite direction, you need dictionaries etc. even if you have a totally invertible transformer, people do not feel happy working that way. They tend to maintain private copies of their own code in their own style, and grudgingly convert them to the offical style, feeling that they are destroying them Third, automatic transformers are definitely not good at dealing with conventions for the layout of comments, since these particularly, being natural language dependent have lots of exceptions. Fourth, since so many style rules do have exceptions, unless everyone understands and internalizes the style rules, they do not gather the understanding that is necessary to know when exceptions apply. All in all, between the two models: 1. Everyone in the team uses the same style, and that is what everyone becomes familiar with (it is amazing when you switch styles, how easy it is to get used to a new style -- when I started on the GNAT project, I preferred the Ada 83 style of ALL_UPPER_CASE with underscores, primarily because of the nice automatic separation of identifier names in comments, but the clear majority of programmers on the GNAT project was opposed to this style and now I cannot imagine ever liking it, compared to All_Upper_Case (postscript, I can't imagine every getting to like AllUpperCase, but I expect I would get used to it if I had to). 2. Everyone uses their own style, and automatic tools are used to get some semblance of consistency in the official checked in sources. I think 1 is FAR preferable. Not only does 2 result in real technical problems, e.g. preparing a quick patch to solve a particular bug, but it results in a far less effective level of social cooperation and team cohesion, important factors for the production of quality software. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-12 0:00 ` dewarr 1998-09-12 0:00 ` Charles Hixson @ 1998-09-14 0:00 ` Ell 1 sibling, 0 replies; 510+ messages in thread From: Ell @ 1998-09-14 0:00 UTC (permalink / raw) Ell <ell@access1.digex.net> wrote: >: For me, the reason it makes sense to simply take majority >: votes on style issues is that consistency is THE most >: important issue, much more important than the actual >: decisions (it's like driving, it really doesn't matter if >: you drive on the left or right, but it is really important >: to agree >Wrong headed pragmatism, pure and simple. > >It's ludicrous on the face of it to say all that matters is making a >decision, not the content of the decision itself. That's like saying >it's more important that we all decided to poison ourselves, rather than >questioning the whole decision. > > -- this observation thanks to Tarski :-) > >I'm not surprised. I would be ashamed of this not happy. Whoops sorry folks. I hadn't read that this was referring to "style". While I very much do think there are style basics that should be adhered to, I see where wide latitude should often be given style decisions - as long as for any given decision it applies project wide. There is the much vaunted "consistency" in this area. :-} Elliott -- :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering "The domain object model is the foundation of OOD." Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 2 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... >> For example, suppose I need to flush some buffers at the end of each >> iteration. I do this by calling 'flush'. I must write this as: >> >> for(;;) >> { >> Get(N); >> if (N) >> >> <process N> >> flush(); >> } >> else { >> break; >> flush(); >> } >> } > >I'm confused by your example. How does flush() get called in the else >part, if it's immediately preceeded by a break? Sorry, flush() should precede break; (too many articles, too little time.) >Shouldn't it be just > > for(;;) > { > Get(N); > if (N) > <process N> > flush(); > } > else { > break; > } > } No, every Get must be followed by a flush in this case. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Patrick Logan 2 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Matthew Heaney <matthew_heaney@acm.org> wrote: : Boy oh boy, Robert, we must come from different programming schools! : The dangerous thing about the code fragment above is that the else : part can get lost, especially if <process N> is long-ish. If you think <process N> should be longish *in line* then I can state it as a fact we come from different schools! Because my school taught me *modular* programming as well as structured! -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` dennison 1998-09-02 0:00 ` Dan Higdon 2 siblings, 0 replies; 510+ messages in thread From: dennison @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sjk3p$4tc$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > > Matthew Heaney wrote in message ... > > >Without being able to exit from the middle of a loop, I'd have to do > >this to terminate a read sequence: > > > > Get (N); > > > > while N /= 0 loop > > > > <process N> > > > > Get (N); > > > > end loop; > > > >So it's the structured approach which causes the redundancy, becuase Get > >must be called twice. > > Consider: > > do { > Get(N); > if (N) > <process N> > } while (N); > > Structured programming allows the loop condition to be either at the top or > the bottom. In Ada (which is what it looks like Matthew was writing in) there is no "do-while" loop construct. It has to be simulated with the "exit" statement as follows: (sorry if the nesting isn't there. DejaNews' posting software has problems with leading spaces) loop Get(N); if N then <process N> end if; exit when not N; end loop; which looks pretty awkward (and performs twice as many comparisons) compared to: loop Get(N); exit when not N; <process N> end loop; Anyway, if you think middle-exits are bad from a maintenence perspective, then in Ada you should probably stick to while and for. In your example there is nothing stopping a later maintainence person from inserting a line between the "exit" and the "end loop". -- T.E.D. -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` dennison @ 1998-09-02 0:00 ` Dan Higdon 2 siblings, 0 replies; 510+ messages in thread From: Dan Higdon @ 1998-09-02 0:00 UTC (permalink / raw) Robert Martin wrote in message <6sjk3p$4tc$1@hirame.wwa.com>... >Consider: > > do { > Get(N); > if (N) > <process N> > } while (N); > >Structured programming allows the loop condition to be either at the top or >the bottom. You just rolled the loop around - you're still testing the condition twice, you just made the *test* redundant. Having a single entry/exit point is good. Forcing the exit point to the top or bottom of the construct is artificial, IMHO. There are many cases (and this is a particularly good one) where the test to exit does not naturally occur at either the top or bottom of the loop, but midway through it. As an aside, a valid (IMHO) Eiffel extension would be to allow loops a little more freedom (yeah, I know, "everyone's a language designer" :-): -- standard from <init> until <test> loop <statements> end -- post test from <init> loop <statements> until <test> end -- in test from <init> loop <statements> until <test> else <statements> end Ignoring {in}variants for simplicity. (I suppose {in}variants would need to hold true at the "until".) so, our example becomes from <init> loop Get (N) until not N else <process N> end ---------------------------------------- hdan@charybdis.com "Throwing fire at the sun" ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin ` (3 preceding siblings ...) 1998-09-02 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson 1998-09-03 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-0309982311220001@dialup62.tlh.talstar.com> 6 siblings, 2 replies; 510+ messages in thread From: adam @ 1998-09-02 0:00 UTC (permalink / raw) In article <6simjo$jnh$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: > In any case, I note that in this thread nearly every article that advocates > multiple exits evokes either readability, complexity, or naturalness as the > justification. I contend that these are highly subjective things, that are > not shared by all programmers alike. Indeed, what is readable, natural and > simple to me, may be opaque and convoluted to you. I also contend that > these issues are somewhat emotional, as evidenced by the terms such as > "twist", "warp", "bend", "religious argument", etc. that have also been used > in this thread. > > Finally, I contend that the factors in favor of using a > single-entry/single-exit style are, on the other hand, quite concrete and > demonstrable. It has been shown that adhering to a structured style > facilitates both resource management and error processing. It has also > been shown that a multiple exit style is vulnerable to redundant code, and > code for recovery of state. > > So, it seems what we have here is "gut feelings" warring against empirical > data. I agree with the first quoted paragraph, but I wonder about the "empirical data" part. So far, on this thread, I haven't seen any empirical data at all, aside from the one study Matthew quoted. Instead, I've seen lots of theories and explanations for why style X is better than style Y. Some have sounded pretty logical, and others seem to have no connection to reality. Even so, all of them seem to be little more than speculation. Someone might say, "Putting all the predicate information at the top of the loop leads to better code", but where's the empirical evidence that this is the case? I mean, we could come up with all sorts of logic about why doing this should be better, but without some sort of study, our logic is based on assumptions about what *seems* like it should be more maintainable, assumptions that may or may not hold water. At best, these assumptions may reflect the poster's personal experience; but since not everyone thinks the same way, an assertion based on someone's experience may not be all that useful. One person may find code style X easier to deal with than Y, but another might find X to be more difficult. I've noticed this in some of the short examples posted, where one person posts something they think is quite clear, but I've had to stare at it for a long time to figure out what the code was supposed to do. This may be because all of us programmers have had difference experiences working with different kinds of code, so that a programming idiom that one programmer is intimately familiar with may take some effort for a different programmer to figure out. Anyway, as someone who has been pounding keyboards for 20+ years, I've had a lot of experience at noticing what kinds of coding techniques lead to more or fewer problems later when I try to maintain my code, and what techniques in other peoples' programs make them easier or more difficult to work with; still, I wouldn't call my own conclusions more than "gut feelings". Certainly, I haven't come close to the standards required to ensure that my conclusions are controlled for other factors, free from personal bias, etc., that would enable me to call my experiences "empirical data". At worst, the assumptions behind arguments for style X or Y are based on abstract ideas that we have no reason to believe has any actual correlation with maintainability. This was my original complaint about some of the arguments against GOTO, but it applies equally to the other arguments about "multiple exits", "continue" statements, etc. Some of these arguments strike me as someone struggling to come up with reasoning that supports a viewpoint that they believe in but don't have clear logical reasons for---i.e. a viewpoint they have no more than a gut feeling about. It's no wonder some of us look at these arguments as "religious wars". So, rather than gut feelings warring against empirical data, the whole thread appears to me to be gut feelings warring against other gut feelings. > I can understand why the gut reaction is so strong; multiple exits > are *eaiser* to write; and are, for some, easier to read. But those are not > the only, or even the most important, criteria for evaluating the quality of > a design. Maintainability is an issue too, and sometimes an overriding one. I agree that ease of writing doesn't correlate well with maintainability, but ease of reading seems to be a very important factor. I don't see how code can be maintainable if it's not easy to understand. If it's relatively difficult for someone to understand what's going on, it has to be relatively easier (it seems to me) to modify the code in a way that screws things up. For example, it seemed that one of your arguments about why fractional loops are worse is that you could add statements to the end of the loop and be assured that they would be executed every time. I don't see this. It seems to imply that a programmer should be able to just stick statements at the end of the loop, without understanding what the whole loop does, and be assured that they will be executed every time (how could this argument possibly make sense if the programmer fully understands the loop's control structure?). But my experience is that if I try to add code to the end of a loop without completely understanding what's going on, I'm just as likely to add bad code to a loop without multiple exits than to a loop with them. I think this argues that ease of reading is, in essence, the most important criteria, since it can't be separated from maintainability. Finally, a lot of people on this thread have tried to explain why they find multiple exits easier to read and understand, but you seem to be implying that they're doing this just to justify writing code that's easier to *write*. I don't see this at all, and I think it's an unwarranted insult. > In the end, the decision to use a structured style is a tradeoff. There are > benefits, and there are costs. And there are certainly situations in which > the costs outweight the benefits (e.g. quick an dirty programs that have > short lifetimes and require little maintenance during their life). It is > also true, however, that for a very large set of circumstances, the benefits > outweigh the costs. I agree, as long as "structured style" is loosely defined. Code that has any structure at all is easier to read than code that doesn't. And sometimes it's faster and easier to write unstructured or carelessly-structured code, but this should be avoided when possible. My own feeling is that once a programmer makes readability a priority, and follows certain general principles we can all agree with (e.g. break the code down into relatively small segments that have a clearly defined purpose, and use comments), the programmer will write code that's more maintainable. The programmer has to rely on judgment to decide what the best style is in a particular case, and of course more experience produces better judgment. But I just haven't seen any compelling evidence that, for a programmer who understands the importance of readability and has good judgment, any particular style will be preferable to any other particular style (occasional GOTO's vs. avoiding them like the plague, single-exit vs. multiple-exit, using return's in the middle of your procedures, etc.). I just don't see that we have enough empirical evidence to support any such conclusion. -- Adam -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` adam @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mike Spille ` (2 more replies) 1998-09-06 0:00 ` Charles Hixson 1 sibling, 3 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) adam@irvine.com wrote in message <6skcr2$i4o$1@nnrp1.dejanews.com>... >In article <6simjo$jnh$1@hirame.wwa.com>, >I agree that ease of writing doesn't correlate well with >maintainability, but ease of reading seems to be a very important >factor. I don't see how code can be maintainable if it's not easy to >understand. I agree with this. It's the converse that I don't agree with. Yes, code must be readable to be maintainable (whatever "readable" means). On the other hand, code that is readable is not necessarily easy to maintain. Simple example: the file 'error.h' is loaded with lots of #defines that specify all the various error codes that our functions can return. 'error.h' is very easy to read, and completely understandable. But maintaining it is a royal pain because every time we add a new error code, we have to recompile the world. >For example, it seemed that one of your arguments about why fractional >loops are worse is that you could add statements to the end of the >loop and be assured that they would be executed every time. I don't >see this. It seems to imply that a programmer should be able to just >stick statements at the end of the loop, without understanding what >the whole loop does, and be assured that they will be executed every >time (how could this argument possibly make sense if the programmer >fully understands the loop's control structure?). Think about this for a minute. Wouldn't it be nice if you *could* stick a line of code at the end of every loop, or at the end of every function, and be guaranteed that it would be called? For example, have you every had to put those interesting little print statements into functions: "entering function x", "exitting function x"? Wouldn't it be nice if you could just plop those print statement in without having to anlayze each and every function for multiple returns? (Yes, I know we can use RAI for this. But lets pretend that we are writing in Java, or C) >But my experience >is that if I try to add code to the end of a loop without completely >understanding what's going on, I'm just as likely to add bad code to a >loop without multiple exits than to a loop with them. I think this >argues that ease of reading is, in essence, the most important >criteria, since it can't be separated from maintainability. Yes, I agree with this, but only in part. Sometimes you really don't have to completely understand a function in order to make the necessary modifications. In those cases, if an se/se style has been adopted, it's a lot eaiser to understand the control flow and insert the appropriate statements. > >Finally, a lot of people on this thread have tried to explain why they >find multiple exits easier to read and understand, but you seem to be >implying that they're doing this just to justify writing code that's >easier to *write*. I don't see this at all, and I think it's an >unwarranted insult. No insult intended. However, the "easier to write" justification has been used in several postings. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Mike Spille 1998-09-03 0:00 ` Richard MacDonald 1998-09-03 0:00 ` Gerry Quinn 2 siblings, 0 replies; 510+ messages in thread From: Mike Spille @ 1998-09-02 0:00 UTC (permalink / raw) Robert Martin wrote: > > adam@irvine.com wrote in message <6skcr2$i4o$1@nnrp1.dejanews.com>... > >In article <6simjo$jnh$1@hirame.wwa.com>, > > >I agree that ease of writing doesn't correlate well with > >maintainability, but ease of reading seems to be a very important > >factor. I don't see how code can be maintainable if it's not easy to > >understand. > > I agree with this. It's the converse that I don't agree with. > > Yes, code must be readable to be maintainable (whatever "readable" means). > On the other hand, code that is readable is not necessarily easy to > maintain. > > Simple example: the file 'error.h' is loaded with lots of #defines that > specify all the various error codes that our functions can return. > 'error.h' is very easy to read, and completely understandable. But > maintaining it is a royal pain because every time we add a new error code, > we have to recompile the world. > An interesting branch from a loop discussion :-) > >For example, it seemed that one of your arguments about why fractional > >loops are worse is that you could add statements to the end of the > >loop and be assured that they would be executed every time. I don't > >see this. It seems to imply that a programmer should be able to just > >stick statements at the end of the loop, without understanding what > >the whole loop does, and be assured that they will be executed every > >time (how could this argument possibly make sense if the programmer > >fully understands the loop's control structure?). > > Think about this for a minute. Wouldn't it be nice if you *could* stick a > line of code at the end of every loop, or at the end of every function, and > be guaranteed that it would be called? For example, have you every had to > put those interesting little print statements into functions: "entering > function x", "exitting function x"? Wouldn't it be nice if you could just > plop those print statement in without having to anlayze each and every > function for multiple returns? > > (Yes, I know we can use RAI for this. But lets pretend that we are writing > in Java, or C) > As an aside...most hideous language proposals I've seen begin with "Wouldn't it be nice if....". The best proposals begin with "I have a strong need for....". I think there is a certain correlation to your above statement.... That said, I'll re-iterate what myself and others have said: your implication is that people should be able to muck with a function without understanding it (e.g. syntactical constructs are enough to tell the tale, and semantics beside the point). I strongly disagree - most of the maintenance goofs I've seen haven't come about due to multiple loop exits or "badly structured code" (whatever that may be) - it's been due to maintenance programmers not taking the time to understand the code. > >But my experience > >is that if I try to add code to the end of a loop without completely > >understanding what's going on, I'm just as likely to add bad code to a > >loop without multiple exits than to a loop with them. I think this > >argues that ease of reading is, in essence, the most important > >criteria, since it can't be separated from maintainability. > > Yes, I agree with this, but only in part. Sometimes you really don't have > to completely understand a function in order to make the necessary > modifications. In those cases, if an se/se style has been adopted, it's a > lot eaiser to understand the control flow and insert the appropriate > statements. Please don't take this as a personal attack, but I hope you never, ever touch any of my code. I would horse-whip any of my guys who "really don't completely understand a function" and made a modification to it. > > > >Finally, a lot of people on this thread have tried to explain why they > >find multiple exits easier to read and understand, but you seem to be > >implying that they're doing this just to justify writing code that's > >easier to *write*. I don't see this at all, and I think it's an > >unwarranted insult. > > No insult intended. However, the "easier to write" justification has been > used in several postings. > > Robert C. Martin | Design Consulting | Training courses offered: > Object Mentor | rmartin@oma.com | Object Oriented Design > 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ > Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > > "One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan -Mike ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mike Spille @ 1998-09-03 0:00 ` Richard MacDonald 1998-09-03 0:00 ` Gerry Quinn 2 siblings, 0 replies; 510+ messages in thread From: Richard MacDonald @ 1998-09-03 0:00 UTC (permalink / raw) Robert Martin wrote in message <6skhpr$459$1@hirame.wwa.com>... >Think about this for a minute. Wouldn't it be nice if you *could* stick a >line of code at the end of every loop, or at the end of every function, and >be guaranteed that it would be called? For example, have you every had to >put those interesting little print statements into functions: "entering >function x", "exitting function x"? Wouldn't it be nice if you could just >plop those print statement in without having to anlayze each and every >function for multiple returns? Very nice. Good example would be one of those cases where you are using an expensive resource (e.g., a file) and need to ensure that you close it whether or not everything worked great or it bombed. Smalltalk uses the aBlock #ensure: anotherBlock syntax, meaning no matter what happens in aBlock, anotherBlock is always executed when aBlock terminates. While this doesn't apply to loops, there are two ways to make it so: (1) Move everything in the loop to another method, then put the method in a block and apply the #do:ensure: approach to it. (2) For each loop method in the library, add another method that includes the #ensure: block. For the latter, you would want to have both pre and post ensure blocks, so this gets a little cumbersome. However, you would only have to write it (them) once, then all your code could use it (them). I've enjoyed following this discussion, but I think people are concentrating on too low a level. That is appropriate for procedural code (structured code). But we are missing higher-level solutions that OO provides us. In Smalltalk, the do loop is itself an OO method (construction). So why not add additional methods (constructions)? P.S. I like the #ensure: option, but I have measured a factor of 20 performance hit in Smalltalk when I use it. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mike Spille 1998-09-03 0:00 ` Richard MacDonald @ 1998-09-03 0:00 ` Gerry Quinn 2 siblings, 0 replies; 510+ messages in thread From: Gerry Quinn @ 1998-09-03 0:00 UTC (permalink / raw) In article <6skhpr$459$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> wrote: >Think about this for a minute. Wouldn't it be nice if you *could* stick a >line of code at the end of every loop, or at the end of every function, and >be guaranteed that it would be called? For example, have you every had to >put those interesting little print statements into functions: "entering >function x", "exitting function x"? Wouldn't it be nice if you could just >plop those print statement in without having to anlayze each and every >function for multiple returns? > It would be pretty easy - just wrap the function in another one. Of course by doing this you wouldn't have access to the local variables of the function without having to understand the function - but that can hardly be the point of 'structured programming', can it...? - Gerry ---------------------------------------------------------- gerryq@indigo.ie (Gerry Quinn) ---------------------------------------------------------- ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Robert Martin @ 1998-09-06 0:00 ` Charles Hixson 1 sibling, 0 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) adam@irvine.com wrote: ... > be little more than speculation. Someone might say, "Putting all the > predicate information at the top of the loop leads to better code", > but where's the empirical evidence that this is the case? I mean, we > could come up with all sorts of logic about why doing this should be > better, but without some sort of study, our logic is based on > assumptions about what *seems* like it should be more maintainable, > assumptions that may or may not hold water. > > At best, these assumptions may reflect the poster's personal > experience; but since not everyone thinks the same way, an assertion > based on someone's experience may not be all that useful. One person ... > experience produces better judgment. But I just haven't seen any > compelling evidence that, for a programmer who understands the > importance of readability and has good judgment, any particular style > will be preferable to any other particular style (occasional GOTO's > vs. avoiding them like the plague, single-exit vs. multiple-exit, > using return's in the middle of your procedures, etc.). I just don't > see that we have enough empirical evidence to support any such > conclusion. > > -- Adam > > -----== Posted via Deja News, The Leader in Internet Discussion ==----- > http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum A very important point. There is probably a range of "best choice"s, and it may be that no one person is in a position to recognize all of them. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin ` (4 preceding siblings ...) 1998-09-02 0:00 ` adam @ 1998-09-03 0:00 ` mfinney 1998-09-03 0:00 ` Robert Martin [not found] ` <gio+van+no+ni+8-0309982311220001@dialup62.tlh.talstar.com> 6 siblings, 1 reply; 510+ messages in thread From: mfinney @ 1998-09-03 0:00 UTC (permalink / raw) In <6simjo$jnh$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: >mfinney@lynchburg.net wrote in message ... >>And, as far as maintainability is concerned, I strictly use tree-structured >>programming and have *never* found it to be a maintenance problem. >>Sure, sometimes code transformations are required during maintenance, >>but they are sometimes required during coding. So what? There is no >>way to write code that never requires code transformations during >>maintenance, and trying to do so just makes the code harder to >>understand and ultimately increases maintenance cost. Far better is >>to endevour to reach 0 bugs so that maintenance is never required. >>Not easy, perhaps, but it is getting closer and closer every day. I >>personally am running somewhere around 0.0001 and 0.0002 errors >>per line of code -- prior to quality assurance getting the code. >Reaching zero bugs may not have that big an impact on maintenance, since >much of maintenance has to do with changes to the requirements. Reaching zero bugs means that changes are made by development rather than maintenance. That distinction is, of course, a matter of definition. It also depends on the ratio between code correction and requirement changes. >In any case, I note that in this thread nearly every article that advocates >multiple exits evokes either readability, complexity, or naturalness as the >justification. I contend that these are highly subjective things, that are >not shared by all programmers alike. Certainly true. But there does tend to be a rough consensus. Discussions like this tend to refine that consensus. >I also contend that >these issues are somewhat emotional, as evidenced by the terms such as >"twist", "warp", "bend", "religious argument", etc. that have also been used >in this thread. Quite true, although for the record I must say that I used the term "twist" as a synonym for "roll" or "rotate" and in an emotionally negative manner. The terms "warp" and "bend" were used to indicate the emotional "feel" of forcing code into a perceived unnatural state. >So, it seems what we have here is "gut feelings" warring against empirical >data. I would not agree with that. First, the "benefits" of structured programming have not been shown that clearly, and second, there is evidence on the other side as well. And, generally what was measured in most studies that I have seen is the difference between structured programmend and completely unstructured programming. Not the difference between structured programming and tree-structured programming which is the point of this argument. The only study quoted so far, favors the middle exit which is actually irrelevant to the difference between structured programming and tree-structured programming. >In the end, the decision to use a structured style is a tradeoff. There are >benefits, and there are costs. And there are certainly situations in which >the costs outweight the benefits (e.g. quick an dirty programs that have >short lifetimes and require little maintenance during their life). It is >also true, however, that for a very large set of circumstances, the benefits >outweigh the costs. First, I don't know about you, but I don't write "quick and dirty" programs. I write all programs in the same manner, regardless of their audience or intended lifespan -- those targets change far too frequently. Secondly, the benefits of structured programming over tree-structured programming have *not* been demostrated, so far as I know. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` mfinney @ 1998-09-03 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) mfinney@lynchburg.net wrote in message ... >Reaching zero bugs means that changes are made by development >rather than maintenance. That distinction is, of course, a matter of >definition. Yes, and apparently our definitions differ. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <gio+van+no+ni+8-0309982311220001@dialup62.tlh.talstar.com>]
* Re: Software landmines (loops) [not found] ` <gio+van+no+ni+8-0309982311220001@dialup62.tlh.talstar.com> @ 1998-09-03 0:00 ` Robert Martin 0 siblings, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Giovanni 8 wrote in message ... >> Robert Martin wrote: > >> Finally, I contend that the factors in favor of using a >> single-entry/single-exit style are, on the other hand, quite >> concrete and demonstrable. It has been shown that adhering >> to a structured style facilitates both resource management and >> error processing. > >Non sequitur. It hasn't been concretely shown that single >exits at the bottom of a loop facilitates resource management, >and I know it makes error processing more difficult because >the erroneous state is retained while slogging through >irrelevant code to the bottom of the loop. It's a kludge. If the loop, or function, is properly structured, then upon detection of the error, no further code is executed except the code that must be executed to complete the loop. while (some condition) { if (vetting condition) do something interesting else report error } No slogging through irrelevant code, no retention of erroneous state. And, the extra benefit that the loop body is completely self contained. For example, I can put X and UNX calls at the top and bottom of the loop body, and guarantee that every X and UNX will be paired. while (some condition) { X(); if (vetting condition) do something interesting else report error UNX(); } >Multiple exits, OTOH, are elegant. They can be, but they also have costs: while (some condition) { if (!vetting condition) { report error; continue; } do something interesting; } Why this is any more elegant than the se/se version above, I can't say; though some folks do like to focus on the negative aspects of the invariants first. However, this code no longer has the nice self contained property. I can no longer add the X and UNX pair conveniently. Rather I must add UNX in two places: while (some condition) { X(); if (!vetting condition) { report error; UNX(); continue; } do something interesting; UNX(); } This is a concrete benefit of se/se. It is not an appeal to elegance or readability. It is not an appeal to prettiness or common sense. It is an ability that se/se code has, that is lost if the se/se style is not conformed to. Does that mean that se/se should be *always* be used? No, it's just a concrete, demonstrable, benefit. > >> It has also been shown that a multiple exit style is >> vulnerable to redundant code, and code for recovery of >> state... > >No, that has not been shown, I presume that the above is sufficient proof? Note the reduntant UNX() call in the second case. >& I contend that it is the >exit only from the bottom of a loop style that creates >a need for redundant or extraneous code, while multiple >exits eliminates it. Can you provide a case in point like the one above? >Multiple exits promote >Readability: The code follows the algorithm without any > extraneous matter. >Complexity: No extraneous matter. No multiple checks of > a condition or state. No flags. >Naturalness: The exit happens when the prescribed condition > is satisfied, not before, and not after. I think the above is rather subjective as the following rebuttal points out. se/se promotes: Readability: every control flow is explicit. Complexity management: since all control flows are explicit, adding new statement to existing control flows is trivial. Natrualness: the function happens when all the vetting conditions pass, all error recovery is at the end, and each is in its own specific control flow, so that specific error recovery is trivial. >"[I]n the early 1980s, a survey [1980 _Software Maintenance > Management_ pp 151-157 & 492-497] by [B.] Lientz & [E.] Swanson > of 487 data processing organizations showed that only 20% of > the maintenance effort was spent on corrective maintenance. > [And 42% on user requested enhancements.]" --- Carma McClure > 1992 _The 3 Rs of Software Automation_ pp 15-17 Precisely! Programs need changing a lot more than then need fixing. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` mfinney ` (2 preceding siblings ...) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` john-clonts 1998-09-03 0:00 ` mfinney 3 siblings, 1 reply; 510+ messages in thread From: john-clonts @ 1998-09-02 0:00 UTC (permalink / raw) In article <Oi4H1.219$qj1.315418@newsread.com>, mfinney@lynchburg.net wrote: > In <6sh3qn$9p2$1@hirame.wwa.com>, "Robert Martin" <rmartin@oma.com> writes: > > >However, multiple exits to a single destination represent a problem. The > >two exits come from two different states within the algorithm. If the > >single destination must do some work that depends upon that state (or if in > >the future, that single destination must be modified to do work that depends > >upon that state), then the code in the single destination is going to get > >pretty ugly. > > I have been following this thread for a while (or at least part of the thread), > and it seems to me that the basic argument is between the use of structured > programming which requires a single entry and single exit and of tree- > structured programming which allows multiple-level breaks/continues, but > not arbitrary jumps into blocks. > > It turns out that tree-structured programming covers almost all of the flow > graphs actually encountered by compilers which are not undecomposable > and provides the necessary flow graph assurances for optimization (I do > have a reference on that, but have just finished moving and everything > is in boxes, so regrettably I can't provide it at this time). Multiple exits > > [snip] > > Michael Lee Finney > > What do you mean by 'tree-structured' programming? A simple example perhaps? THanks, John -----== Posted via Deja News, The Leader in Internet Discussion ==----- http://www.dejanews.com/rg_mkgrp.xp Create Your Own Free Member Forum ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` john-clonts @ 1998-09-03 0:00 ` mfinney 1998-09-06 0:00 ` Charles Hixson 0 siblings, 1 reply; 510+ messages in thread From: mfinney @ 1998-09-03 0:00 UTC (permalink / raw) In <6sk1k9$3r9$1@nnrp1.dejanews.com>, john-clonts@hlp.com writes: >What do you mean by 'tree-structured' programming? If memory serves correctly, one definition of tree-structured programming is those programs that can be written with the following control structures... 1. A named block 2. A "jump" to the start or end of a named block 3. A statement which conditionally executes the following statement Or, if C/C++ did not have a "goto" statement, but instead allowed a do/for/while block to be named and allowed that name to be used with a break/continue statement (you can get an arbitrary block in C/C++ by using a do {/*code*/} while (false); control structure). Then only tree-structured programs could be written (ignoring exceptions). A return statement in C/C++ effectively implements a multi-level break from the current module. The only other way to accomplish it in C/C++ is by using the "goto". Nevertheless, tree-structured programs are structured and can be characterized in a number of ways. Again, if memory serves (all of my references are still packed from my move), a tree-structured program can also be characterized as any program which contains no jumps into a block. For example... outer::while (someCondition) { // some code inner::while (anotherCondition) { // some code outer::break; // exit outermost loop inner::continue; // restart innermost loop outer::continue; // restart outermost loop inner::break; // exit innermost loop // some code } // some code } Here, I am using a notation which is modeled on C++'s "scoping" operator because you want to specify the "scope" which applies to the break/continue. The only difference between tree-structured programming and structured programming is that only a single level break/continue is allowed for structured programming and structured programming only allows a single exit from any block (both tree-structured and structured programming only allow a single entry to a block). The use of "goto" is strictly controlled in a tree-structued program and arbitrary "spaghetti" cannot be written. Knuth has shown that for any given set of control structures, there are some programs which cannot be easily represented. The set of programs which can be easily represented (without using "flag" tricks or other work-arounds) by structured programs is strictly less than the set of programs which can be easily represented by tree-structured programs. I personally believe that the incidence of programs which can be easily represented as tree-structured programs but not structured programs is high enough that restricting oneself to structured programming is not reasonable. That is, of course, a personal judgement call, but I do have a reasonable amount of experience to back it up. While I have found many, if not most, programs don't fit the structured program mold, I have found very few, if any, which do not fit the tree-structured program mold. I have often wished for additional control structures, but every one of them is tree-structured. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` mfinney @ 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` mfinney 0 siblings, 1 reply; 510+ messages in thread From: Charles Hixson @ 1998-09-06 0:00 UTC (permalink / raw) mfinney@lynchburg.net wrote: > > In <6sk1k9$3r9$1@nnrp1.dejanews.com>, john-clonts@hlp.com writes: > > >What do you mean by 'tree-structured' programming? > ... > For example... > > outer::while (someCondition) > { > // some code > inner::while (anotherCondition) > { > // some code > outer::break; // exit outermost loop > inner::continue; // restart innermost loop > outer::continue; // restart outermost loop > inner::break; // exit innermost loop > // some code > } > // some code > } > ... > Michael Lee Finney I feel that this is a structure to be avoided when it is easy to do so. I haven't needed this kind of sturcture more than about 10 times since the '80's. OTOH, sometimes it's what the sturcture of the problem seems to demand. Sometimes avoiding it would cause more problems than it solves. In such a case, be VERY careful to make your code as clear and obvious as possible, because this IS a more-difficult-to-understand-than-usual idiom. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-06 0:00 ` Charles Hixson @ 1998-09-06 0:00 ` mfinney 0 siblings, 0 replies; 510+ messages in thread From: mfinney @ 1998-09-06 0:00 UTC (permalink / raw) In <35F2F3F9.69ED1C30@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> writes: >mfinney@lynchburg.net wrote: >> >> In <6sk1k9$3r9$1@nnrp1.dejanews.com>, john-clonts@hlp.com writes: >> >> >What do you mean by 'tree-structured' programming? >> >.... >> For example... >> >> outer::while (someCondition) >> { >> // some code >> inner::while (anotherCondition) >> { >> // some code >> outer::break; // exit outermost loop >> inner::continue; // restart innermost loop >> outer::continue; // restart outermost loop >> inner::break; // exit innermost loop >> // some code >> } >> // some code >> } >> >.... >> Michael Lee Finney >I feel that this is a structure to be avoided when it is easy to do so. >I haven't needed this kind of sturcture more than about 10 times since >the '80's. OTOH, sometimes it's what the sturcture of the problem seems >to demand. Sometimes avoiding it would cause more problems than it >solves. In such a case, be VERY careful to make your code as clear and >obvious as possible, because this IS a >more-difficult-to-understand-than-usual idiom. I certainly don't need it often. I do frequently need the multiple return from a block or the n 1/2 loop (resulting in a mid-block loop break) which at least the first is not structured (but is tree-structured). And, there is a reasonable argument both ways about the mid-block loop break being structured because it is se-se, but the exit is neither at the top nor the bottom. I would personally argue that it meets the spirit, but not the letter of structured programming. It is, however, tree-structured. The need for the more comprehensive forms of tree-structured programming are rarer, but they do essentially encapsulate most of the need for more powerful control structures while maintaining most or all of the benefits of structured programming. I don't believe that I have ever written a program, even in assembly language, which was not tree-structured -- but I have written many programs, time and again, which are not structured just because here or there I needed just a bit more than is available with structured programming. And since efficiency *does* count -- at least sometimes -- adding flags or other forms of additional tests is generally not acceptable to me. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Robert Martin ` (2 preceding siblings ...) 1998-09-02 0:00 ` mfinney @ 1998-09-02 0:00 ` Gene Gajewski 3 siblings, 0 replies; 510+ messages in thread From: Gene Gajewski @ 1998-09-02 0:00 UTC (permalink / raw) Robert Martin wrote in message <6sh3qn$9p2$1@hirame.wwa.com>... <snip> >However, multiple exits to a single destination represent a problem. The >two exits come from two different states within the algorithm. If the >single destination must do some work that depends upon that state (or if in >the future, that single destination must be modified to do work that depends >upon that state), then the code in the single destination is going to get >pretty ugly. This statement could be true if computers were not the discontinous machines they are. Code is not executed all at once, hence 'state' is a fact of life. The existance of the exit itself is proof that the coder of the algorithm has considered state as a factor and has determined that it is 'safe to exit'. A maintainer of code knows intuititvely that any states he introduces affects all code following it. There is no choice but to encapsulate the existing code. If a particular function is written with a single exit point, it will be easy to encapsulate simply by making changes before and after the loop. No examination of the contents of the loop appear to be necessary. However, the procedures and actions performed by the function are no longer the same, the computer not being absolute at all times, some may say that the function is not the same. My preference is to avoid modifying a function that is correct. If additional functionality is needed within a program, than the program needs modification, not the function. It would be better to create a new function containing the new state which than calls the original function - all for what will be a new program. A modified program is new in the essence it is not the same program, although it may appear identical from the outside. This may not seem acceptable to some, especially if the function to be modified is referenced in many places. On the other hand, a function so often refrenced should be simple in design. A gross change in functionality would indicate a poor original analysis, IMO. This is the sort of particular problem that can be solved administratively. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-30 0:00 ` Robert Martin ` (5 preceding siblings ...) [not found] ` <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au> @ 1998-09-09 0:00 ` Jonas M�ls� [not found] ` <35f51e53.48044143@ <6t6l4n$rep@jbm.nada.kth.se> 7 siblings, 0 replies; 510+ messages in thread From: Jonas M�ls� @ 1998-09-09 0:00 UTC (permalink / raw) Matthew Heaney writes: > > > >I can almost live that. The real problem, however, is that using an >extra flag to terminate VASTLY complicates the predicate. In fact, the >flag doubles the number of states I have to think about when mentally >evaluating the predicate! That's the real source of the loop >termination errors. > > >Using an exit from the middle avoids the headaches (literally) >engendered by using an extra flag in the predicate. When you want to >exit, you just say that you want to exit, directly. No mental >gymnastics are required in order to determine whether you'll "really" >exit, as would be the case using the flag approach. Using an exit from the top avoids the headaches (quite literally) of having to figure out the condition for completing another round in the loop, which is one of the main conditions to specify, in order to avoid loop termination errors. Also, I have never encountered a real situation where I have needed an extra flag in the predicate. One can actually do fine without them. As an example, I hereby present to you three variations of str_index. The first one strictly exits at the top. The other two in the middle. The first one is much easier to reason about, and to understan, IMHO. Anyway, introducing an extra flag in the predicate is very often a sign of "patching the loop". Done right, one does not need it. /** str_index * * str_index returns a pointer to the first occurrence of * the given character in the given string. * If the given character does not occur in the given * string, str_index returns NULL. * * If the given pointer is NULL, the result is undefined. * */ char * str_index ( char *s, /* string to search */ char c) /* character to search for */ { while (*s != '\0' && *s != c) ++s; return (*s != c) ? NULL : s; } char * str_index2 ( char *s, /* string to search */ char c) /* character to search for */ { while (*s != '\0') if (*s == c) return s; else ++s; return 0; } char * str_index3 ( char *s, /* string to search */ char c) /* character to search for */ { while (*s != '\0') { if (*s == c) return s; ++s; } return 0; } ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <6t6l4n$rep@jbm.nada.kth.se>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <6t6l4n$rep@jbm.nada.kth.se> @ 1998-09-10 0:00 ` Mats Weber 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Mats Weber @ 1998-09-10 0:00 UTC (permalink / raw) Jonas M�ls� wrote: > Also, I have never encountered a real situation > where I have needed an extra flag in the predicate. > One can actually do fine without them. As an example, > I hereby present to you three variations of str_index. > > The first one strictly exits at the top. The other two > in the middle. The first one is much easier to reason > about, and to understan, IMHO. Anyway, introducing an > extra flag in the predicate is very often a sign of > "patching the loop". Done right, one does not need it. > > > char * > str_index ( > char *s, /* string to search */ > char c) /* character to search for */ > { > while (*s != '\0' && *s != c) > ++s; > > return (*s != c) ? NULL : s; > } The problem with this variant is that you are comparing *s with c once more than in the other two variants. With characters, this is perfectly OK, but this could become a problem if the comparison for equality is more expensive, for instance if you are comparing larger structures or have a more complicated equality function. In fact, you are using "*s == c" as a flag to check why you exited form your loop. Try to reprogram your example doing each comparison only once: you will need a flag if you don't use return in the loop. (I find the other two variants more readable, but that is a matter of taste). ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <6t6l4n$rep@jbm.nada.kth.se> 1998-09-10 0:00 ` Mats Weber @ 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 1637 bytes --] jbm@jbm.nada.kth.se (Jonas M�ls�) writes: > Also, I have never encountered a real situation > where I have needed an extra flag in the predicate. > One can actually do fine without them. As an example, > I hereby present to you three variations of str_index. > > The first one strictly exits at the top. The other two > in the middle. The first one is much easier to reason > about, and to understan, IMHO. Anyway, introducing an > extra flag in the predicate is very often a sign of > "patching the loop". Done right, one does not need it. > > > > /** str_index > * > * str_index returns a pointer to the first occurrence of > * the given character in the given string. > * If the given character does not occur in the given > * string, str_index returns NULL. > * > * If the given pointer is NULL, the result is undefined. > * > */ > > Here's another idea: char * str_index ( char *s, /* string to search */ char c) /* character to search for */ { for (;;) if (*s == c) return s; else if (*s == '\0') return NULL; else s++; } I don't know if this is typical C code, however. I suspect one would move some of the work up into the for loop declaration: for (; *s != '\0'; s++) if (*s == c) return s; return NULL; An Ada programmer has an easier go of it: function Get_Position (S : String; C : Character) return Natural is begin for Index in S'Range loop if S(Index) = C then return Index; end if; end loop; return 0; end Get_Position; ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <m3ogt3qgca.fsf@mheaney.ni.n <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net>]
* Re: Software landmines (loops) [not found] ` <m3ogt3qgca.fsf@mheaney.ni.n <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net> @ 1998-10-10 0:00 ` Patrick Doyle 1998-10-12 0:00 ` Charles H. Sampson 0 siblings, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-10-10 0:00 UTC (permalink / raw) In article <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net>, Charles H. Sampson <claveman@inetworld.net> wrote: > >In my entire career I have rarely written the following construct: > > <loop head> > <procedure call> > end loop > >Actually, I can't remember ever doing it, but I assume that I must have >at least a few times. Eh? How can you write a serious loop without calling a procedure from inside it? Do I misunderstand what you wrote? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-10 0:00 ` Patrick Doyle @ 1998-10-12 0:00 ` Charles H. Sampson 1998-10-13 0:00 ` Matthew Heaney 1998-10-14 0:00 ` Graham Perkins 0 siblings, 2 replies; 510+ messages in thread From: Charles H. Sampson @ 1998-10-12 0:00 UTC (permalink / raw) Patrick Doyle <doylep@ecf.toronto.edu> wrote: > In article <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net>, > Charles H. Sampson <claveman@inetworld.net> wrote: > > > >In my entire career I have rarely written the following construct: > > > > <loop head> > > <procedure call> > > end loop > > > >Actually, I can't remember ever doing it, but I assume that I must have > >at least a few times. > > Eh? How can you write a serious loop without calling a procedure > from inside it? > > Do I misunderstand what you wrote? I suspect that we're each misunderstanding the other, because your response has surely puzzled me. Before the confusion gets worse, maybe you should define the term "serious loop". The above structure, that I don't remember writing, is not a loop that fails to contain a procedure call in its body. It's a loop whose body consists entirely of a single procedure call. Charlie -- To get my correct email address, replace the "claveman" by "csampson" in my fake (anti-spam) address. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-12 0:00 ` Charles H. Sampson @ 1998-10-13 0:00 ` Matthew Heaney 1998-10-14 0:00 ` Graham Perkins 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-10-13 0:00 UTC (permalink / raw) claveman@inetworld.net (Charles H. Sampson) writes: >In my entire career I have rarely written the following construct: > > <loop head> > <procedure call> > end loop > >Actually, I can't remember ever doing it, but I assume that I must have >at least a few times. > The above structure, that I don't remember writing, is not a loop > that fails to contain a procedure call in its body. It's a loop whose > body consists entirely of a single procedure call. I do this from time-to-time, for a for loop body that's getting a long. Instead of: for Index in Index_Type loop declare <decl's that depend on Index> begin <lots of stuff here> end; end loop; I prefer to do this: procedure Do_Something (Index : in Index_Type); for Index in Index_Type loop Do_Something (Index); end loop; ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-12 0:00 ` Charles H. Sampson 1998-10-13 0:00 ` Matthew Heaney @ 1998-10-14 0:00 ` Graham Perkins 1998-10-15 0:00 ` Reimer Behrends 1 sibling, 1 reply; 510+ messages in thread From: Graham Perkins @ 1998-10-14 0:00 UTC (permalink / raw) Charles H. Sampson wrote: ... > The above structure, that I don't remember writing, is not a loop > that fails to contain a procedure call in its body. It's a loop whose > body consists entirely of a single procedure call. A very frequent construct in student programs! Also we often find "main program" which consists of a single procedure call, and many individual procedures which consist of nothing but two or three parameter-less procedure calls. We try to reform such people before they graduate!! But many slip through. Now someone please tell me that *all* of these student are kept away from real programming once they get jobs ! ---------------------------------------------------------------- Graham Perkins, De Montfort University, Milton Keynes http://www.mk.dmu.ac.uk/~gperkins/ ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-14 0:00 ` Graham Perkins @ 1998-10-15 0:00 ` Reimer Behrends 1998-10-15 0:00 ` dewarr 0 siblings, 1 reply; 510+ messages in thread From: Reimer Behrends @ 1998-10-15 0:00 UTC (permalink / raw) Graham Perkins (gperkins@dmu.ac.uk) wrote: [...] > Also we often find "main program" which consists of a single procedure > call, and many individual procedures which consist of nothing but > two or three parameter-less procedure calls. > > We try to reform such people before they graduate!! But many > slip through. Well, I hope so. :) An abstraction (procedure or class) is a good abstraction because it embodies a useful concept, not because it saves space. void f() { g(); } is a perfectly legitimate construct, with the obvious benefit that you can at any time change the implementation of f() from g() to h() without affecting the code that uses it. Imagine for instance the case of writing an anonymous mailer, where you want to eliminate all uses of the "From" address and replace it by a dummy. (Say, for anonymous feedback in a class.) Now, if there is a uniform function string from_address() { return user_name(); } then you can just change this single function. However, if user_name() were used all over the place, making the change is anything but pleasant. (Extra points for spotting the reference and noticing that it is anything but fictitious.) [...] Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-10-15 0:00 ` Reimer Behrends @ 1998-10-15 0:00 ` dewarr 0 siblings, 0 replies; 510+ messages in thread From: dewarr @ 1998-10-15 0:00 UTC (permalink / raw) In article <slrn72bafc.16n.behrends@allegro.cse.msu.edu>, behrends@cse.msu.edu (Reimer Behrends) wrote: > Graham Perkins (gperkins@dmu.ac.uk) wrote: > [...] > > Also we often find "main program" which consists of a single procedure > > call, and many individual procedures which consist of nothing but > > two or three parameter-less procedure calls. > > > > We try to reform such people before they graduate!! But many > > slip through. > > Well, I hope so. :) An abstraction (procedure or class) is a good > abstraction because it embodies a useful concept, not because it saves > space. I often tell students that if I see a large program which does NOT contain instances of subprograms called only once, it is misstructured. Indeed I find it annoying that many modern programming languages make it harder than necessary to introduce simple "refinement" procedures in two ways: 1. They require the declaration before the call, which is annoying in this case, since the program then is written "upside down". 2. They require a lot of syntax One of the most attractive features of COBOL is its economical syntax for this kind of refinement: check-balance. if balance > 0 then perform record-credit else perform send-bill end-if. record-credit. ... send-bill. ... Lambert Meertens ABC language provides a similar functionality as did Koster's CDL. But many modern Algol-derived languages are lacking in this area, and as a result one often sees conditionals nested annoyingly deep in an effort to avoid clarifying refinements. Robert Dewar -----------== Posted via Deja News, The Discussion Network ==---------- http://www.dejanews.com/ Search, Read, Discuss, or Start Your Own ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <l5HC1.6840$wN.18 <35F238F7.F57D3EC7@earthlink.net>]
* Re: Software landmines (loops) [not found] ` <l5HC1.6840$wN.18 <35F238F7.F57D3EC7@earthlink.net> @ 1998-09-06 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-06 0:00 UTC (permalink / raw) In article <35F238F7.F57D3EC7@earthlink.net>, Charles Hixson <charleshixsn@earthlink.net> wrote: > >But somehow pulling chunks of code into a function and then calling that >function makes things simpler, even though the flow of execution follows >the same path, so something else is going on here. > >I tend to think that one of the major activities of programming is >properly "chunking" the problem into pieces that have low-bandwidth >connections with the rest of the code. Abstraction, man! That's what you're grasping at here. :-) Abstraction is what makes things easier to understand. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <m31zpxqutn.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <m31zpxqutn.fsf@mheaney.ni.net> @ 1998-08-31 0:00 ` Jim Cochrane 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Matthew Heaney 0 siblings, 2 replies; 510+ messages in thread From: Jim Cochrane @ 1998-08-31 0:00 UTC (permalink / raw) How about the following version, without multiple exit points (written in Eiffel because it is a good language for this style [it actually doesn't allow the multiple return style] and because I'm familiar with Eiffel.) class STACK [G] ... is_equal (other: STACK [G]): BOOLEAN is -- Are all items in Current equal to all item in other? require other /= Void local i1, i2: STACK_ITERATOR do !!i1.make (Current); !!i2.make (other) from i1.start; i2.start until i1.after or i2.after or else i1.item /= i2.item loop i1.forth; i2.forth end Result := i1.after and i2.after end I don't think this is particularly hard to understand or maintain, plus it is simpler than the algorithm below - it eliminates the if statement at the beginning. (STACK_ITERATOR behavior is, hopefully, obvious - i.item means the value of item at the current cursor position of i.) I threw this together just for this post, so apologies if there are any bugs (and bonus points to those that find them :-) ). In article <m31zpxqutn.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: >ahussey@it.uq.edu.au (Andrew Hussey) writes: > >> >Using an exit from the middle avoids the headaches (literally) >> >engendered by using an extra flag in the predicate. When you want to >> >exit, you just say that you want to exit, directly. No mental >> >gymnastics are required in order to determine whether you'll "really" >> >exit, as would be the case using the flag approach. >> >> That's brilliant, now your code is much easier to write! >> Now let's see who has an easier time *testing* their code. >> I think you'll find the control-flow errors you introduce >> in the spaghetti you produce will more than make up for >> any gain you have from rapid coding. > >Here's is something I whipped up for another post recently. It's an >equality operator for a bounded stack. > >The implementation of the function has multiple returns. > >Does this implementation fit your definition of spaghetti code? > >Would the implementation be better by not using multiple returns? > > >function "=" (L, R : Stack_Type) return Boolean is >begin > > if L.Top /= R.Top then > return False; > end if; > > for Index in Positive range 1 .. L.Top loop > if L.Items (Index) /= R.Items (Index) then > return False; > end if; > end loop; > > return True; > >end "="; > > >My feeling is that trying to implement this operation using only a >single return would just make it more complicated. > > -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Jim Cochrane @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) jtc@dimensional.com (Jim Cochrane) writes: > How about the following version, without multiple exit points (written in > Eiffel because it is a good language for this style [it actually doesn't > allow the multiple return style] and because I'm familiar with Eiffel.) > > class STACK [G] ... > is_equal (other: STACK [G]): BOOLEAN is > -- Are all items in Current equal to all item in other? > require > other /= Void > local > i1, i2: STACK_ITERATOR > do > !!i1.make (Current); !!i2.make (other) > from > i1.start; i2.start > until > i1.after or i2.after or else i1.item /= i2.item > loop > i1.forth; i2.forth > end > Result := i1.after and i2.after > end > > I don't think this is particularly hard to understand or maintain, > plus it is simpler than the algorithm below - it eliminates the if > statement at the beginning. (STACK_ITERATOR behavior is, hopefully, > obvious - i.item means the value of item at the current cursor > position of i.) I threw this together just for this post, so > apologies if there are any bugs (and bonus points to those that find > them :-) ). I realized I had a compare op lying around implemented using the same idea: using iterators to simultaneously traverse over a pair of collections. As you can see, it's more or less like the earlier example I posted. (At least I'm consistent.) It avoids the mental gymnastics required to understand the (Eiffel) example shown above, because there isn't any complicated loop predicate. The conditions under which the loop terminates should be pretty obvious. Find a mismatch between items, and just bail out. Pure and simple. function ACL.Compare (Left : access Left_Collection; Right : access Right_Collection) return Boolean is Length : Natural renames Get_Length (Left.all); Left_Iter : Left_Iterator (Left); Right_Iter : Right_Iterator (Right); begin -- Compare if Length /= Get_Length (Right.all) then return False; end if; for Index in 1 .. Length loop if Get_Item (Left_Iter).all /= Get_Item (Right_Iter).all then return False; end if; Advance (Left_Iter); Advance (Right_Iter); end loop; return True; end ACL.Compare; ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-08-31 0:00 ` Jim Cochrane 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-01 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Jim Cochrane 1 sibling, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-01 0:00 UTC (permalink / raw) jtc@dimensional.com (Jim Cochrane) writes: > class STACK [G] ... > is_equal (other: STACK [G]): BOOLEAN is > -- Are all items in Current equal to all item in other? > require > other /= Void > local > i1, i2: STACK_ITERATOR > do > !!i1.make (Current); !!i2.make (other) > from > i1.start; i2.start > until > i1.after or i2.after or else i1.item /= i2.item > loop > i1.forth; i2.forth > end > Result := i1.after and i2.after > end > > I don't think this is particularly hard to understand or maintain, > plus it is simpler than the algorithm below - it eliminates the if > statement at the beginning. (STACK_ITERATOR behavior is, hopefully, > obvious - i.item means the value of item at the current cursor > position of i.) I threw this together just for this post, so > apologies if there are any bugs (and bonus points to those that find > them :-) ). I think this is a real brain teaser. Let me show you how I try to unravel it. Let's start by making a decision table for the loop predicate: 1 2 3 4 5 6 7 8 i1.after T T T T F F F F i2.after T T F F T T F F i1.item /= i2.item T F T F T F T F As you can see, there are 8 rules, which just exceeded the cognitive limits of most of human population. Already, we're in trouble. But there's more trouble ahead. The last part of the predicate uses a short-circuit form, so we're going to have to prune the table, by removing the rules in which i1.after and i2.after are both false. Or is it both true??? As I'm writing this post, I've already spent several minutes trying to figure out when the last part of the predicate actually gets executed. And I don't even know what the evaluation order rules are in Eiffel. Does i1.after or i2.after or else i1.item /= i2.item mean (i1.after or i2.after) or else i1.item /= i2.item or i1.after or (i2.after or else i1.item /= i2.item) Hmmm? Maybe these expressions both have the same value. I don't know, but I'm obligated to find out. This is mental work I shouldn't have to do, and I'll probably get it wrong. So I gotta ask: Is this a program, or an IQ test? I'll just use my little decision table friend again, to help me crack the secret of what result the predicate acually delivers. 1 2 3 4 5 6 7 8 i1.after T T T T F F F F i2.after T T F F T T F F i1.item /= i2.item - - - - - - T F The dash (-) means "does not matter." So the item test only influences the result (I think) when i1.after and i2.after are both false. (Gee, that's what I originally thought. A miracle happened, and I guessed right! But how many other times will I be this lucky?) Now I have to actually figure out what the result of the predicate is: 1 2 3 4 5 6 7 8 i1.after T T T T F F F F i2.after T T F F T T F F i1.item /= i2.item - - - - - - T F predicate has value T T T T T T T F Ah, so that's the secret! The loop teriminates (I think) when all sub-predicates yield false. Revealed at last, after several minutes of careful analysis, which I probably screwed up. But wait, I did screw up! Loop termination in Eiffel has opposite the traditional sense, which is to terminate when the predicate is false. So the loop terminates when the predicate is true. Whew! How many programmers do you think will take the time to figure all this out? How many programmers even know how to use a decision table? One more issue with this example. Following termination, calculating the result, Result := i1.after and i2.after means i1.after and i2.after get tested again. Why? They were tested already, in the loop. Why test them twice? Maybe I get bonus points for being able to decipher this, but is that how we should write software? Be rewarding those who perform mental gymnastics? I hope not. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-01 0:00 ` Matthew Heaney @ 1998-09-02 0:00 ` Jim Cochrane 1998-09-02 0:00 ` Richard Melvin 1998-09-03 0:00 ` Robert I. Eachus 0 siblings, 2 replies; 510+ messages in thread From: Jim Cochrane @ 1998-09-02 0:00 UTC (permalink / raw) In article <m3af4kpyr9.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: >jtc@dimensional.com (Jim Cochrane) writes: > >> class STACK [G] ... >> is_equal (other: STACK [G]): BOOLEAN is >>... (See below for entire original article.) You have provided a good, thorough analysis supporting the argument that my version is more complex, and I think you've convinced me. It is difficult to determine what the loop is doing when the exit condition is so complex. Also, I agree with your argument for separating the test of the two stack sizes being unequal into a separate statement from the loop body, since this does make the code easier to understand, as well as more efficient. I would like to now propose an algorithm that separates the equality check from the loop and that also returns only at the end of the function. I will include a loop invariant in the code, and I'll then copy your algorithm, inserting a loop invariant. The point of this exercise will be to see if how each idiom affects the traditional technique of analyzing a loop by means of the loop invariant. (In my version I have changed the type from STACK to ARRAY, since this operation is not really compatible with the STACK abstraction and because it makes expressing the loop invariant easier - using indexes instead of iterators. [Of course, a stack internally implemented as an array will be able to use this algorithm.]) My new version: class ARRAY [G] ... is_equal (other: ARRAY [G]): BOOLEAN is require arg_not_void: other /= Void local i: INTEGER do if count /= other.count then Result := false else from i := 1 invariant -- for_all j member_of {1..i - 1} it_holds -- Current @ j = other @ j until i > count or Current @ i /= other @ i loop i := i + 1 end check (i - 1 /= count) implies (Current @ i /= other @ i) count = other.count end Result := i - 1 = count end ensure -- Result = (count = other.count and for_all j member_of -- {1..count} it_holds Current @ j = other @ j) end Your version: function "=" (L, R : Stack_Type) return Boolean is begin if L.Top /= R.Top then return False; end if; for Index in Positive range 1 .. L.Top loop -- INV: for_all j member_of {1..Index - 1} it_holds -- L.Items (j) = R.items (j) if L.Items (Index) /= R.Items (Index) then -- not (Index - 1 = L.Top) return False; end if; end loop; -- L.Top = R.Top and Index - 1 = L.Top return True; -- Postcondition: Result = (L.Top = R.Top and for_all j member_of -- {1..L.Top} it_holds Current @ j = other @ j) end "="; When we compare these two implementations, your earlier comments (comparing your implementation with an implementation someone else proposed [I believe it was Loryn] that is very similar to mine) mostly still apply - especially the point that your loop termination condition is simpler than mine. But since you include what is in essence a hidden loop termination condition [L.Items (Index) /= R.Items (Index)], as someone else pointed out, the complexity of two termination conditions is still there. My routine does nest the loop within an else statement; but yours nests an if within a loop. Which is better? I don't know - I'm not sure it matters that much. In addition to the loop invariant, I have added a postcondition to both routines (which is the same for both routines; also, the loop invariant is the same for both routines). I have also added a couple other assertions to document program state at those points. Looking at my routine, you can easily determine that the loop invariant is correct and that, as a result, if i - 1 /= count then (although the loop invariant is true), Current @ i /= other @ i and the result will be false; otherwise, the result will be true. The postcondition of the routine follows straightforwardly from that. Looking at your routine, you need to check 3 different places to check that the postcondition is upheld, the 3 return statements: In the first if statement, in the second if statement in the middle of the loop, and at the end of the routine. This is a pretty straightforward process, but I think it makes it a little more difficult in that you need to check 3 separate locations, including in the middle of the loop. My conclusion at this point is that I don't see a noticable advantage to either idiom. I prefer the one that only exits at the end of the routine, but I don't think I would object to seeing your version in a code inspection. (Of course, if the code was written in Eiffel, your version would not be possible.) The one remaining question I have is: How will the two idioms compare with a more complex algorithm? I have a suspicion that having multiple return points with a more complex algorithm will make the routine postcondition and the loop invariant harder to verify than with the return-at-the-end idiom. Of course, I can't confirm that until I examine some examples. I think this has been a good discussion and (contrary to another poster's implication that this is simply a loop structuring war) I (and I would hope others) have learned from it. For comparison, here is my original version with loop invariant and postcondition added (and using indexes instead of iterators) (I also changed the "or else" term to "or", since they are semantically equivalent and the latter is easier to understand for those who don't know Eiffel well): class ARRAY [G] ... is_equal (other: ARRAY [G]): BOOLEAN is require arg_not_void: other /= Void local i: INTEGER do from i := 1 invariant -- for_all j member_of {1..i - 1} it_holds Current @ j = other @ j until i > count or i > other.count or Current @ i /= other @ i loop i := i + 1 end check i - 1 = count and i - 1 = other.count or count /= other.count or Current @ i /= other @ i end Result := i - 1 = count and i - 1 = other.count ensure -- Result = (count = other.count and for_all j member_of -- {1..count} it_holds Current @ j = other @ j) end In article <m3af4kpyr9.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: >jtc@dimensional.com (Jim Cochrane) writes: > >> class STACK [G] ... >> is_equal (other: STACK [G]): BOOLEAN is >> -- Are all items in Current equal to all item in other? >> require >> other /= Void >> local >> i1, i2: STACK_ITERATOR >> do >> !!i1.make (Current); !!i2.make (other) >> from >> i1.start; i2.start >> until >> i1.after or i2.after or else i1.item /= i2.item >> loop >> i1.forth; i2.forth >> end >> Result := i1.after and i2.after >> end >> >> I don't think this is particularly hard to understand or maintain, >> plus it is simpler than the algorithm below - it eliminates the if >> statement at the beginning. (STACK_ITERATOR behavior is, hopefully, >> obvious - i.item means the value of item at the current cursor >> position of i.) I threw this together just for this post, so >> apologies if there are any bugs (and bonus points to those that find >> them :-) ). > >I think this is a real brain teaser. Let me show you how I try to >unravel it. > >Let's start by making a decision table for the loop predicate: > > 1 2 3 4 5 6 7 8 >i1.after T T T T F F F F > >i2.after T T F F T T F F > >i1.item /= i2.item T F T F T F T F > >As you can see, there are 8 rules, which just exceeded the cognitive >limits of most of human population. Already, we're in trouble. But >there's more trouble ahead. > >The last part of the predicate uses a short-circuit form, so we're going >to have to prune the table, by removing the rules in which i1.after and >i2.after are both false. > >Or is it both true??? As I'm writing this post, I've already spent >several minutes trying to figure out when the last part of the predicate >actually gets executed. > >And I don't even know what the evaluation order rules are in Eiffel. >Does > > i1.after or i2.after or else i1.item /= i2.item > >mean > > (i1.after or i2.after) or else i1.item /= i2.item > >or > > i1.after or (i2.after or else i1.item /= i2.item) > >Hmmm? Maybe these expressions both have the same value. I don't know, >but I'm obligated to find out. This is mental work I shouldn't have to >do, and I'll probably get it wrong. > >So I gotta ask: Is this a program, or an IQ test? > >I'll just use my little decision table friend again, to help me crack >the secret of what result the predicate acually delivers. > > 1 2 3 4 5 6 7 8 >i1.after T T T T F F F F > >i2.after T T F F T T F F > >i1.item /= i2.item - - - - - - T F > >The dash (-) means "does not matter." > >So the item test only influences the result (I think) when i1.after and >i2.after are both false. (Gee, that's what I originally thought. A >miracle happened, and I guessed right! But how many other times will I >be this lucky?) > >Now I have to actually figure out what the result of the predicate is: > > 1 2 3 4 5 6 7 8 >i1.after T T T T F F F F > >i2.after T T F F T T F F > >i1.item /= i2.item - - - - - - T F > >predicate has value T T T T T T T F > >Ah, so that's the secret! The loop teriminates (I think) when all >sub-predicates yield false. > >Revealed at last, after several minutes of careful analysis, which I >probably screwed up. > >But wait, I did screw up! Loop termination in Eiffel has opposite the >traditional sense, which is to terminate when the predicate is false. >So the loop terminates when the predicate is true. Whew! > >How many programmers do you think will take the time to figure all this >out? How many programmers even know how to use a decision table? > >One more issue with this example. Following termination, calculating >the result, > > Result := i1.after and i2.after > >means i1.after and i2.after get tested again. Why? They were tested >already, in the loop. Why test them twice? > >Maybe I get bonus points for being able to decipher this, but is that >how we should write software? Be rewarding those who perform mental >gymnastics? > >I hope not. -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Jim Cochrane @ 1998-09-02 0:00 ` Richard Melvin 1998-09-03 0:00 ` Jim Cochrane 1998-09-03 0:00 ` Robert I. Eachus 1 sibling, 1 reply; 510+ messages in thread From: Richard Melvin @ 1998-09-02 0:00 UTC (permalink / raw) In article <6siqo0$hiv@flatland.dimensional.com>, Jim Cochrane <jtc@dimensional.com> writes > from > i := 1 > invariant > -- for_all j member_of {1..i - 1} it_holds > -- Current @ j = other @ j > until > i > count or Current @ i /= other @ i > loop > i := i + 1 > end > check > (i - 1 /= count) implies (Current @ i /= other @ i) > count = other.count > end > Result := i - 1 = count I'm not a fan of this line - if I was to translate it it into english, it would come out as something like 'which exit path did I take from the loop?'. In order to work this out, you have to reverse-engineer the loop. To me, i is an implementation detail of the loop - referring to it outside the loop almost seems to break encapsulation. Perhaps it would work better with more descriptive variable names? Perhaps numTested and numFoundEqual? (Although that makes the -1 problematic). -- Richard Melvin ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Richard Melvin @ 1998-09-03 0:00 ` Jim Cochrane 0 siblings, 0 replies; 510+ messages in thread From: Jim Cochrane @ 1998-09-03 0:00 UTC (permalink / raw) In article <sZ7ktUAz7a71Ewx0@radm.demon.co.uk>, Richard Melvin <rmelvin@radm.demon.co.uk> wrote: >In article <6siqo0$hiv@flatland.dimensional.com>, Jim Cochrane ><jtc@dimensional.com> writes >> from >> i := 1 >> invariant >> -- for_all j member_of {1..i - 1} it_holds >> -- Current @ j = other @ j >> until >> i > count or Current @ i /= other @ i >> loop >> i := i + 1 >> end >> check >> (i - 1 /= count) implies (Current @ i /= other @ i) >> count = other.count >> end >> Result := i - 1 = count > >I'm not a fan of this line - if I was to translate it it into english, >it would come out as something like 'which exit path did I take from the >loop?'. In order to work this out, you have to reverse-engineer the >loop. > >To me, i is an implementation detail of the loop - referring to it >outside the loop almost seems to break encapsulation. Well, i is an essential component of the loop invariant, which must be true when the loop has finished, as well as at the beginning of each iteration of the loop. It may be helpful to add the following predicate to the check statement at the end of the loop, which defines the postcondition of the loop (in comments because it is not codable): -- (i - 1 = count) = for_all j member_of {1..count} it_holds -- Current @ j = other @ j In other words, if and only if the loop has iterated over the entire array, such that i = count + 1, then each element of Current is equal to the corresponding element of other (since we know that Current.count = other.count). This is precisely the loop's job, to determine if the two arrays are equal. The substitution of {1..count} for {1..i - 1} is an important step that shows how the loop invariant brings about the loop postcondition. Therefore i must be available outside of the loop. It is no more internal to the loop than the array variables Current or other. > >Perhaps it would work better with more descriptive variable names? >Perhaps numTested and numFoundEqual? >(Although that makes the -1 problematic). > >-- >Richard Melvin -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Jim Cochrane 1998-09-02 0:00 ` Richard Melvin @ 1998-09-03 0:00 ` Robert I. Eachus 1 sibling, 0 replies; 510+ messages in thread From: Robert I. Eachus @ 1998-09-03 0:00 UTC (permalink / raw) In article <6siqo0$hiv@flatland.dimensional.com> jtc@dimensional.com (Jim Cochrane) writes: > Looking at your routine, you need to check 3 different places to check that > the postcondition is upheld, the 3 return statements: In the first if > statement, in the second if statement in the middle of the loop, and at the > end of the routine. This is a pretty straightforward process, but I think > it makes it a little more difficult in that you need to check 3 separate > locations, including in the middle of the loop. But this is irrelevant to the way the code was written, and to the way it should be understood. The code flows from this problem statement: "Two lists are equal if they are the same length and each element in the first list is equal to the corresponding element in the second list." Now the postconditions corresponding to the three exits are: Lengths not equal, lists not equal. Element L.Items(Index) /= R.Items(Index), lists not equal. Lengths and all elements equal, lists are equal. Before you jump all over me, realize that this is a DIFFERENT way of treating postconditions, factoring the full statement of the postcondition into separate cases, and having an exit/return for each case. There are many cases where it results in the best code, there are others where it is not the method of choice, but if you are willing to accept multiple returns, then you should add this approach to your bag of tricks. (Notice that it works best when you can linearize the cases as you can here.) -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <35EC1590.D50DB8F6@tisny.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EC1590.D50DB8F6@tisny.com> @ 1998-09-01 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-01 0:00 UTC (permalink / raw) In article <35EC1590.D50DB8F6@tisny.com>, Mike Spille <mspille@tisny.com> wrote: > >Would your average programmer ask the question "Where will the loop >terminate?", or "What does the function do?". I think the latter >question is alot more important. I personally subscribe to >the technique of "bailing-out" as soon as possible in a function. Importance is a pretty nebulous concept, but I think there are situations where both questions are asked. "I want this thing to print a message when it's finished doing xxx; where will the loop terminate?..." As for bailing out early in a function, that is the hallmark of defensive programming, which is considered by some (Bertrand Meyer, in particular) to be a harmful practice in large-scale software development. Defensive programming is necesssary at the boundaries of the system, but a system should not be designed to be internally defensive with respect to itself. >This has two effects: nesting later on is greatly reduced (I find >if-else nesting affects readability), and the early-bailouts give >me guarantees later in the code that I don't need to check for. Well, Design By Contract gives the same guarantees without the extra code for checking the conditions. This means that not only do you have no nesting problem, but in a release build, with assertions disabled, you also have no runtime overhead. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <6shunm$47g$1@hirame.wwa.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6shunm$47g$1@hirame.wwa.com> @ 1998-09-02 0:00 ` David E. Wallace 0 siblings, 0 replies; 510+ messages in thread From: David E. Wallace @ 1998-09-02 0:00 UTC (permalink / raw) In article <6shunm$47g$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> wrote: >This is, in fact, a characteristic of any good OO design that conforms to >the Open/Closed principle. New featuers are added by adding new code; not >by changing old working code. >Nevertheless, functions sometimes do change; and when they do its nice to >have the structured so as to facilitate those changes. But your argument against multiple exits was that even if they save effort in initial development, they cost you effort during the maintenance phase when you have to change the function to allocate and deallocate a resource. If such changes are rare, then the amount of effort saved during such maintenance has to be huge in order to justify the tradeoff. In particular, let's assume that the amount of effort saved per routine in initial development by using multiple exits is X. If 10% of the routines are subsequently modified in maintenance, and 10% of the changes involve adding an allocate/deallocate action that crosses these multiple exit points (very generous estimates in my opinion), and the average routine that is modified is modified 5 times during the course of maintenance, then the effort saved per allocation action added needs to be X/((.1)(.1)(5)) = 20X in order to break even. That calculation doesn't even take the time value of effort into account - a resource saved today is worth more than the same resource saved in the future, both because of the time value of money, and also because many new projects never make it into a significant maintenance phase, in which case any future savings projected are non-existent. So even with these very generous assumptions, you need to save substantially more than 20 times the effort in order to make the tradeoff worthwhile. If instead we assume that only 1% of the routines are modified, and only 5% of the changes involve adding such spanning allocates, then the maintenance effort saved needs to be X/((.01)(.05)(5)) = 400X, not counting the time value of effort. Such a large effort would never be justified (IMO) - if it really cost that much, you would simply rewrite the offending routine instead of modifying it. Note that the only allocate/deallocate pairs that are complicated by the presence of multiple exits are those where (1): an early exit occurs between the time of allocation and deallocation, and (2): the exit transfers control to a point subsequent to the deallocation. Early returns from a function prior to the initial allocation are not a problem, nor are break/continue style exits from a loop if the loop is contained within the allocate/deallocate span. So only a fraction of the allocate/deallocate additions will encounter problems with multiple exits. I can live with some contortions in those cases in order to simplify the initial development. -- Dave Wallace (wallace@netcom.com) It is quite humbling to realize that the storage occupied by the longest line from a typical Usenet posting is sufficient to provide a state space so vast that all the computation power in the world can not conquer it. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <m3zpck79xp.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <m3zpck79xp.fsf@mheaney.ni.net> @ 1998-09-02 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-02 0:00 UTC (permalink / raw) In article <m3zpck79xp.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > >Loryn Jenkins <loryn@s054.aone.net.au> writes: > >> equal (l,r: LIST): BOOLEAN is >> require >> l /= Void and r /= Void >> do >> Result := l.count /= r.count >> if Result then >> from >> l.start; r.start >> until >> not Result or l.off >> loop >> Result := l.item /= r.item >> l.forth; r.forth >> end >> end >> end > > [...] > >No, no, not the same here. > >If the test l.count /= r.count returns False, then you know immediately >what the return value of the function is, so why not deliver that >information right away? That way you can remove the test of result >(reducing the level of nesting), and simplify the predicate, No, if the test returns False then the *computer* knows immediately what the return value of the function is. But remember that it's the reader of the code that is important; he's the one that must know what's going on. I can tell by the line "until not Result or l.off" that either we'll go the the end of the loop or else we'll quit early if Result becomes false. I don't have to mentally single-step the code to find that out; it's right there in the "until" clause. >(By way of analogy, if you've found the house, then you can park in the >driveway right way, instead of driving to the end of the block to >announce that you found the house.) Right, this would be the best idea if, in the analogy, the programmer were the driver. However, it's the computer that's the driver here. The programmer is the one who told the driver to find the house. (At this point, the analogy becomes strained beyond all recognition... :-) >Let's once again compare the decision tables. If we re-write the code, >to put it into Matt-like (because Matt likes it) syntax: > > >equal (l,r: LIST): BOOLEAN is > require > l /= Void and r /= Void > do > if l.count /= r.count then > return False > end > > from > l.start; r.start > until > l.off > loop > if l.item /= r.item then > return False > end > > l.forth; r.forth > end > > return True > end > > >This version has only two rules in the decision table for the loop predicate: > > 1 2 >l.off T F Right, so you've just made it really easy for the computer to execute the loop. But now I have to mentally single-step the entire body of the function to understand it. Particularly, I have to read every line in the loop body to understand what conditions will hold upon loop/routine termination. In Loryn's version, this information appears in one place, so it's much easier to verify that the loop does what it's supposed to do. After all, the whole point of a loop like this one is to cause certain conditions to hold when the loop terminates, right? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <6shhg4$llp$1@hirame.wwa.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6shhg4$llp$1@hirame.wwa.com> @ 1998-09-02 0:00 ` Jim Cochrane 0 siblings, 0 replies; 510+ messages in thread From: Jim Cochrane @ 1998-09-02 0:00 UTC (permalink / raw) In addition to what Robert points out, the potential problem can easily be eliminated by changing "equal == true" to simply "equal". [Or you can simply switch to Eiffel where the equivalent typo "equal = true" -> "equal := true" would not compile. :-)] I think the problem here is not the proposed algorithm, but is simply a C++ syntax anomoly that causes a potential hazard, which can occur within any algorithm implementation. [Besides, why would anyone want to change a piece of code like this that is already written? You do have a rule in your org., don't you, that disallows copying and pasting? :-)] In article <6shhg4$llp$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> wrote: > >Chris Brand wrote in message <35EC3440.9FA81BF1@west.raytheon.com>... >>Robert Martin wrote: >>> >>> bool operator==(Stack& l, Stack& r) >>> { >>> bool equal = true; >>> for (int index = 1; index < l.top() && equal == true; index++) >>> { >>> if (l[index] != r[index]) >>> equal = false; >>> } >>> return equal; >>> } >>> >>> If this is more complex (something that is arguable) it is not *much* >more >>> complex. On the other hand, it is easier to maintain. >> >>It is open to (maintenance) errors such as >> for (int index = 1; index < l.top() && equal = true; index++) >>which the multiple-return version isn't, so the "easier to maintain" >>argument is far from clear-cut. > > >I think *all* structures are vulnerable to typos. The code above is no more >vulnerable than any other code is. > > >Robert C. Martin | Design Consulting | Training courses offered: >Object Mentor | rmartin@oma.com | Object Oriented Design >14619 N Somerset Cr | Tel: (800) 338-6716 | C++ >Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com > >"One of the great commandments of science is: > 'Mistrust arguments from authority.'" -- Carl Sagan > > > -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <6sjms6$7c4$1@hirame.wwa.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6sjms6$7c4$1@hirame.wwa.com> @ 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin ` (3 more replies) 0 siblings, 4 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-02 0:00 UTC (permalink / raw) In article <6sjms6$7c4$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> wrote: > >1. They are indeterminate. When you throw an exception, you have no idea >where control will wind up. It is not simply an exit from the current >scope, or even from the current function. By this logic, polymorphism is indeterminate too. When you call a polymorphic function, you have no idea where control will wind up. This is a Good Thing. It's what makes polymorphism powerful: the fact that you're giving someone else some control over the situation makes your code flexible. The same holds for exceptions. Having said that, I just used an exception for the first time yesterday. I (almost) never use them, and I don't even know why. But the nondeterminism isn't it. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle @ 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Patrick Logan ` (2 subsequent siblings) 3 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Patrick Doyle wrote in message ... >In article <6sjms6$7c4$1@hirame.wwa.com>, >Robert Martin <rmartin@oma.com> wrote: >> >>1. They are indeterminate. When you throw an exception, you have no idea >>where control will wind up. It is not simply an exit from the current >>scope, or even from the current function. > >By this logic, polymorphism is indeterminate too. When you call a >polymorphic function, you have no idea where control will >wind up. This is a Good Thing. It's what makes polymorphism >powerful: the fact that you're giving someone else some control >over the situation makes your code flexible. Granted. >The same holds for exceptions. But there is a difference. With polymorphism, though you may not know what function is actually being called, you do know that it will return to you. Thus, there is a postcondition that you can depend upon. But once you throw an exception, there is very little you can say about what happens next. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 0 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : But there is a difference. With polymorphism, though you may not know what : function is actually being called, you do know that it will return to you. : Thus, there is a postcondition that you can depend upon. But once you : throw an exception, there is very little you can say about what happens : next. But you (the method developer whose method is throwing an exception) don't care what happens next. You only care that your method has held up its end of the bargain. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan @ 1998-09-02 0:00 ` Robert Martin 1998-09-04 0:00 ` Patrick Logan 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Patrick Logan wrote in message ... >In comp.object Robert Martin <rmartin@oma.com> wrote: > >: But there is a difference. With polymorphism, though you may not know what >: function is actually being called, you do know that it will return to you. >: Thus, there is a postcondition that you can depend upon. But once you >: throw an exception, there is very little you can say about what happens >: next. > >But you (the method developer whose method is throwing an exception) >don't care what happens next. You only care that your method has held >up its end of the bargain. Agreed. I think we are lost. My initial point was that exceptions violate se/se structures, but we accept that because they are extraordinary means of control transfer. Exceptions, due to their extraordinary character, provide a benefit that outweighs the cost of losing the se/se structure. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Robert Martin @ 1998-09-04 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-04 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : Patrick Logan wrote in message ... : > : >But you (the method developer whose method is throwing an exception) : >don't care what happens next. You only care that your method has held : >up its end of the bargain. : Agreed. : I think we are lost. : My initial point was that exceptions violate se/se structures, but we accept : that because they are extraordinary means of control transfer. Exceptions, : due to their extraordinary character, provide a benefit that outweighs the : cost of losing the se/se structure. Well, one could be compulsive about SE/SE and place all the exceptions at the bottom of the method. I don't do that, but I write small methods anyway, and I am becoming more aware of the importance of that over anything else under discussion in this thread. I will try to communicate better what I attempted earlier. It has little if anything to do with SE/SE. Previously you wrote: : >: [Upon return from a method invocation] there is a postcondition : >: that you can depend upon. But once you throw an exception, there : >: is very little you can say about what happens next. My point is that when you invoke a method, you are relying on that method's contract in order to *proceed* in fulfilling your own contract. But when you are throwing an exception, you *are* fulfilling your own contract. When you say "there is very little you can say about what happens next" I agree. Whatever you can say has been said. You have fulfilled your contract. End of story. Nothing else matters to you. My argument (if it can be called that) is really with Patrick's bringing this issue up at all. It is apples and oranges to me, and I'm frustrated because I don't know how to compare apples and oranges. (Sorry Patrick. I know you have a point, I just have not been able to grasp it yet.) I hope this helps, at least to point out the general vicinity in which I am lost! -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin @ 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` mfinney 3 siblings, 1 reply; 510+ messages in thread From: Patrick Logan @ 1998-09-02 0:00 UTC (permalink / raw) In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: : By this logic, polymorphism is indeterminate too. When you call a : polymorphic function, you have no idea where control will : wind up. This is a Good Thing. It's what makes polymorphism : powerful: the fact that you're giving someone else some control : over the situation makes your code flexible. These are apples and oranges. Why the comparison? If your method performs polymorphic message sends to multiple objects, there is a contract each object has to uphold. If your method throws an exception, there is a contract it has to uphold, but beyond that, its work is done. There is a contract the caller has to uphold, but that is of no concern to your method. You're done. If your method has allocated some resources and your method throws an exception, your method has to put those resources into whatever state is specified by your contract. If your method has specified no contract about those resources, then it does not have to do anything in particular with them. Common sense may dictate that they be deallocated so the state of the world is as much like the state of the world before your method was called. But if commons sense dictates this, then I would argue so should your method's contract, explicitly! -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Logan @ 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 0 siblings, 2 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-02 0:00 UTC (permalink / raw) In article <NshH1.6521$f01.4705828@news.teleport.com>, Patrick Logan <plogan@user2.teleport.com> wrote: >In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: > >: By this logic, polymorphism is indeterminate too. When you call a >: polymorphic function, you have no idea where control will >: wind up. This is a Good Thing. It's what makes polymorphism >: powerful: the fact that you're giving someone else some control >: over the situation makes your code flexible. > >These are apples and oranges. Why the comparison? Merely to point out that not knowing the distination of a transfer of control does not make for a strong argument against exceptions. If it did, it should apply to polymorphism too. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle @ 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1 sibling, 0 replies; 510+ messages in thread From: Robert Martin @ 1998-09-02 0:00 UTC (permalink / raw) Patrick Doyle wrote in message ... >In article <NshH1.6521$f01.4705828@news.teleport.com>, >Patrick Logan <plogan@user2.teleport.com> wrote: >>In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: >> >>: By this logic, polymorphism is indeterminate too. When you call a >>: polymorphic function, you have no idea where control will >>: wind up. This is a Good Thing. It's what makes polymorphism >>: powerful: the fact that you're giving someone else some control >>: over the situation makes your code flexible. >> >>These are apples and oranges. Why the comparison? > >Merely to point out that not knowing the distination of a transfer >of control does not make for a strong argument against exceptions. >If it did, it should apply to polymorphism too. Did you think I was arguing *against* using exceptions? I wasn't. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Patrick Logan 1 sibling, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: : In article <NshH1.6521$f01.4705828@news.teleport.com>, : Patrick Logan <plogan@user2.teleport.com> wrote: : >In comp.object Patrick Doyle <doylep@ecf.toronto.edu> wrote: : > : >: By this logic, polymorphism is indeterminate too. When you call a : >: polymorphic function, you have no idea where control will : >: wind up. This is a Good Thing. It's what makes polymorphism : >: powerful: the fact that you're giving someone else some control : >: over the situation makes your code flexible. : > : >These are apples and oranges. Why the comparison? : Merely to point out that not knowing the distination of a transfer : of control does not make for a strong argument against exceptions. : If it did, it should apply to polymorphism too. OK. So with polymorphic methods, you are trusting them to do the right thing. And with exceptions, you are trusting them the exception to be handled properly. Although as the one throwing the exception, you do not know what "properly" means: your work is done. Is this a recap of what's been discussed? -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Patrick Logan @ 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` mfinney 3 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-03 0:00 UTC (permalink / raw) doylep@ecf.toronto.edu (Patrick Doyle) writes: > >1. They are indeterminate. When you throw an exception, you have no idea > >where control will wind up. It is not simply an exit from the current > >scope, or even from the current function. > > By this logic, polymorphism is indeterminate too. When you call a > polymorphic function, you have no idea where control will > wind up. This is a Good Thing. It's what makes polymorphism > powerful: the fact that you're giving someone else some control > over the situation makes your code flexible. > > The same holds for exceptions. This is not a correct analogy. The problem is this Seize (M); <do some work that may throw an exception> Release (M); The problem is that flow of control skips right past the Release when an exception occurs. This loss of control is definately NOT a good thing, because it will cause deadlock. My rebuttal to Robert's argument is that the seize and release calls should be called automatically, not manually by the programmer. Even if an exception occurs, Release gets called (automatically), and so no resource problems can occur. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 0 siblings, 1 reply; 510+ messages in thread From: Robert Martin @ 1998-09-03 0:00 UTC (permalink / raw) Matthew Heaney wrote in message ... > Seize (M); > <do some work that may throw an exception> > Release (M); > >The problem is that flow of control skips right past the Release when an >exception occurs. This loss of control is definately NOT a good thing, >because it will cause deadlock. > >My rebuttal to Robert's argument is that the seize and release calls >should be called automatically, not manually by the programmer. Even if >an exception occurs, Release gets called (automatically), and so no >resource problems can occur. And I agree. Controlled type, or RAI, are good approaches to managing resources, whether in the presence of exceptions or not. My point is that the technique is not completely general. It works well for mutexes, allocated memory buffers, locks, etc. But does not work as well for restoring partial results in complex data structures, etc. Robert C. Martin | Design Consulting | Training courses offered: Object Mentor | rmartin@oma.com | Object Oriented Design 14619 N Somerset Cr | Tel: (800) 338-6716 | C++ Green Oaks IL 60048 | Fax: (847) 918-1023 | http://www.oma.com "One of the great commandments of science is: 'Mistrust arguments from authority.'" -- Carl Sagan ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Robert Martin @ 1998-09-03 0:00 ` Patrick Logan 0 siblings, 0 replies; 510+ messages in thread From: Patrick Logan @ 1998-09-03 0:00 UTC (permalink / raw) In comp.object Robert Martin <rmartin@oma.com> wrote: : My point is that the technique is not completely general. It works well for : mutexes, allocated memory buffers, locks, etc. But does not work as well : for restoring partial results in complex data structures, etc. It would work well in a transactional runtime environment that supported nested transactions. A modification of some structure could be attempted within a nested transaction. If it failed for any reason, that transaction could be aborted, restoring the state of the runtime to what it was before the modification. Gemstone does not currently offer nested transactions. If you abort, you abort the all changes since the beginning of the current transaction. But you could still use a try{}finally{} in this style. Gemstone does have a "selective abort" where you can choose the specific objects to abort. You could selectively abort your modifications in a try{}finally{}. But this is tricky. Selective abort is usually considered a tool for implementing Gemstone itself, and not an application developer's tool. -- Patrick Logan (H) mailto:plogan@teleport.com (W) mailto:patrickl@gemstone.com http://www.gemstone.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-02 0:00 ` Patrick Doyle ` (2 preceding siblings ...) 1998-09-03 0:00 ` Matthew Heaney @ 1998-09-03 0:00 ` mfinney 1998-09-03 0:00 ` Patrick Doyle 3 siblings, 1 reply; 510+ messages in thread From: mfinney @ 1998-09-03 0:00 UTC (permalink / raw) In <EynyFt.Mwz@ecf.toronto.edu>, doylep@ecf.toronto.edu (Patrick Doyle) writes: >In article <6sjms6$7c4$1@hirame.wwa.com>, >Robert Martin <rmartin@oma.com> wrote: >>1. They are indeterminate. When you throw an exception, you have no idea >>where control will wind up. It is not simply an exit from the current >>scope, or even from the current function. >By this logic, polymorphism is indeterminate too. When you call a >polymorphic function, you have no idea where control will >wind up. This is a Good Thing. It's what makes polymorphism >powerful: the fact that you're giving someone else some control >over the situation makes your code flexible. >The same holds for exceptions. >Having said that, I just used an exception for the first time >yesterday. I (almost) never use them, and I don't even know >why. But the nondeterminism isn't it. Everybody in favor of non-deterministic algorithms (and control structures) raise your hand! They are not common, but sometimes they are just the ticket. It just requires a different way of thinking to use them. Don't knock non-determinism -- even Dijkstra's guarded conditions are non-deterministic. Knock instead an inappropriate use of non-determinism. Michael Lee Finney ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` mfinney @ 1998-09-03 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <oUsH1.484$qj1.1164857@newsread.com>, <mfinney@lynchburg.net> wrote: >In <EynyFt.Mwz@ecf.toronto.edu>, doylep@ecf.toronto.edu (Patrick Doyle) writes: > >>Having said that, I just used an exception for the first time >>yesterday. I (almost) never use them, and I don't even know >>why. But the nondeterminism isn't it. > >Everybody in favor of non-deterministic algorithms (and control >structures) raise your hand! They are not common, but sometimes >they are just the ticket. It just requires a different way of thinking >to use them. Don't knock non-determinism -- even Dijkstra's guarded >conditions are non-deterministic. Knock instead an inappropriate >use of non-determinism. Wait, have another look at my quote. I wasn't knocking nondeterminism. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <35EDC648.76F03F32@draper.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EDC648.76F03F32@draper.com> @ 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Tim McDermott 0 siblings, 2 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <35EDC648.76F03F32@draper.com>, Tim McDermott <mcdermott@draper.com> wrote: > >This seems a little extreme to me. While I have great respect for >combinatorial explosion, you are talking about a 3-term boolean expression. >There are only 6 ways to put one of those together, and I have no trouble >evaluating any of the forms. I know because I just listed them all, and ran >through their evaluation with no problem. Could you explain how you got the 6? If you want to talk about how many possible boolean expressions there are with n terms, that's 2^(2^n). There are 2^n assignments for the variables, and any combination of those assignments could make the expression true. If you're just talking about how many disjunctions there are, even that is 2^n because any combination of terms can be negated. Maybe what you're talking about is these?... A + B + C A & B + C A &(B + C) A + B & C (A + B)& C A & B & C However, these aren't really 6 distinct expressions. The third and fifth are the same, as are the second and fourth. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Patrick Doyle @ 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Tim McDermott 1 sibling, 0 replies; 510+ messages in thread From: Martin Tom Brown @ 1998-09-03 0:00 UTC (permalink / raw) On Thursday, in article <EypnAz.L66@ecf.toronto.edu> doylep@ecf.toronto.edu "Patrick Doyle" wrote: > In article <35EDC648.76F03F32@draper.com>, > Tim McDermott <mcdermott@draper.com> wrote: > > > >This seems a little extreme to me. While I have great respect for > >combinatorial explosion, you are talking about a 3-term boolean expression. > >There are only 6 ways to put one of those together, and I have no trouble > >evaluating any of the forms. I know because I just listed them all, and ran > >through their evaluation with no problem. > Could you explain how you got the 6? > Maybe what you're talking about is these?... > > A + B + C > A & B + C > A &(B + C) > A + B & C > (A + B)& C > A & B & C > > However, these aren't really 6 distinct expressions. The third > and fifth are the same, as are the second and fourth. Are your sure about that ?? And what did B + A & C B &(A + C) Do to deserve being missed out ? And when you allow for the shortcircuiting that some compilers do in code generation to avoid evaluting terms which cannot affect the result even things like A + B + C vs B + A + C could be distinct if there were side effects in A,B or C. I know they should not be, but people do these things. Regards, -- Martin Brown <martin@nezumi.demon.co.uk> __ CIS: 71651,470 Scientific Software Consultancy /^,,)__/ ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Martin Tom Brown @ 1998-09-03 0:00 ` Tim McDermott 1998-09-04 0:00 ` Patrick Doyle 1998-09-04 0:00 ` Matthew Heaney 1 sibling, 2 replies; 510+ messages in thread From: Tim McDermott @ 1998-09-03 0:00 UTC (permalink / raw) Patrick Doyle wrote: snip > >you are talking about a 3-term boolean expression. There are only 6 ways to > put one of those together, and I have no trouble > >evaluating any of the forms. I know because I just listed them all, and ran > >through their evaluation with no problem. > > Could you explain how you got the 6? I was wearing my bithead, thinking about the textual form of a predicate. I did neglect negation. > If you want to talk about how many possible boolean expressions there > are with n terms, that's 2^(2^n). There are 2^n assignments for the > variables, and any combination of those assignments could make > the expression true. There are 4 possible 1-term boolean expressions? Could you list them?Perhaps this is a terminology problem. By 3-term, I don't mean 3 variables used as often as you like, I mean 3 occurances of any variable and 2 operators (again neglecting negation). I am counting "A & (!A)" as a 2-term expression. > If you're just talking about how many disjunctions there are, even > that is 2^n because any combination of terms can be negated. > > Maybe what you're talking about is these?... Yep, the very beasts. > A + B + C > A & B + C > A &(B + C) > A + B & C > (A + B)& C > A & B & C > > However, these aren't really 6 distinct expressions. The third > and fifth are the same, as are the second and fourth. Hmmm. With A and B false and C true, the second expresion is true, while the fourth is false. The third and fifth expressions differ when A is false and B and C are true. (assuming '&' has higher precedence than '+') I guess the moral of the story is that this stuff really is hard, even at 3 terms. Tim ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Tim McDermott @ 1998-09-04 0:00 ` Patrick Doyle 1998-09-04 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-04 0:00 UTC (permalink / raw) In article <35EEF597.A1119EF4@draper.com>, Tim McDermott <mcdermott@draper.com> wrote: > >Patrick Doyle wrote: > >> If you want to talk about how many possible boolean expressions there >> are with n terms, that's 2^(2^n). There are 2^n assignments for the >> variables, and any combination of those assignments could make >> the expression true. > >There are 4 possible 1-term boolean expressions? Could you list them?Perhaps >this is a terminology problem. By 3-term, I don't mean 3 variables used as often >as you like, I mean 3 occurances of any variable and 2 operators (again >neglecting negation). >I am counting "A & (!A)" as a 2-term expression. Ok, I understand now. As for the 4 possible 1-term boolean expressions, you have A, !A, True (which could be written A + !A) and False (which could be written A * !A). If you want to get rid of the trivial True and False ones, the number is still O(2^(2^n)) (actually being 2^(2^n) - 2). >> A + B + C >> A & B + C >> A &(B + C) >> A + B & C >> (A + B)& C >> A & B & C >> >> However, these aren't really 6 distinct expressions. The third >> and fifth are the same, as are the second and fourth. > >Hmmm. With A and B false and C true, the second expresion is true, while the >fourth is false. The third and fifth expressions differ when A is false and B >and C are true. (assuming '&' has higher precedence than '+') Oh, I was neglecting the variable names. The second expression can be rewritten as C + B & A which, neglecting the letters, is the same as A + B & C. If you don't neglect the letters, then these are not the only possible expressions. There would also be: A & C + B (A + C)& B It's easier to enumerate them if you consider the possibilities with prefix notation. There will be two operators followed by three variables, like this: &+BCA If the operators are the same, the order of the variables doesn't matter. So, there are two of those; one for & and one for +. If the ops are different, then the order of the first two variables doesn't matter, but the third does. That gives 2 operator combinations and 3 distinct variable combinations, for a total of 6 possibilities. Altogether, then, there are eight such expressions. As for what you said about this being hard, I'd agree that counting theory is hard; but I don't see the relevance of that to understanding a loop. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Tim McDermott 1998-09-04 0:00 ` Patrick Doyle @ 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Patrick Doyle 1998-09-08 0:00 ` Tim McDermott 1 sibling, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-04 0:00 UTC (permalink / raw) Tim McDermott <mcdermott@draper.com> writes: > I guess the moral of the story is that this stuff really is hard, even at 3 > terms. Yes! That's the point I was trying make too. Although I can reason about a disjunction with two or three terms, I still prefer a loop predicate with just one term. By separating the array iteration from the item comparison, I can reason about the two different termination conditions independently. So instead of one (larger) problem with two terms, I have two (smaller) problems, with one term each. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Matthew Heaney @ 1998-09-04 0:00 ` Patrick Doyle 1998-09-08 0:00 ` Tim McDermott 1 sibling, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-04 0:00 UTC (permalink / raw) In article <m3ogsw503u.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > >By separating the array iteration from the item comparison, I can reason >about the two different termination conditions independently. So >instead of one (larger) problem with two terms, I have two (smaller) >problems, with one term each. ...thus doubling your problems. :-) -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Patrick Doyle @ 1998-09-08 0:00 ` Tim McDermott 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 1 reply; 510+ messages in thread From: Tim McDermott @ 1998-09-08 0:00 UTC (permalink / raw) Matthew Heaney wrote: > Tim McDermott <mcdermott@draper.com> writes: > > > I guess the moral of the story is that this stuff really is hard, even at 3 > > terms. > > Yes! That's the point I was trying make too. > > Although I can reason about a disjunction with two or three terms, I > still prefer a loop predicate with just one term. > > By separating the array iteration from the item comparison, I can reason > about the two different termination conditions independently. So > instead of one (larger) problem with two terms, I have two (smaller) > problems, with one term each. Since I wrote that bit about this being hard, I reallized that the difficulty arose from Partick Doyle and I talking about different things that looked similar enough to confuse me for a while. He was talking about logical fromulae; I was talking about textual forms. Leaving all that aside, evaluting a 3-proposition predicate requires the evaluation of the 3 propositions (neglecting short-circuiting) and applying 2 operators. Evaluating a 2-proposition predicate involves evaluation of 2 propostitions and applying 1 operator. It looks like the delta is 1 proposition evaluation and 1 operator application. Not a big deal IMO. > By separating the array iteration from the item comparison, I can reason > about the two different termination conditions independently. So > instead of one (larger) problem with two terms, I have two (smaller) > problems, with one term each. But here you are assuming that the termination conditions are disjoint! In the general case they are not. Have you never had the experience of writing something of the form while (A) { if (B) return b; ... if (C) return c; ... if (D) return d; } only to discover some time later that A&!B&!C (the path predicate of the if(D) statement forces the value of D? Worse yet, that the evaluation of the loop predicate interacts with the evaluation of the if predicates. My experience tells me that distributing complexity is a Bad Idea. That is not to say that I always use se/se. But I know that se/se is better form, and I have a real good idea of the risks of multiple return coding. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Tim McDermott @ 1998-09-17 0:00 ` Matthew Heaney 1998-09-17 0:00 ` Reimer Behrends 1998-09-18 0:00 ` Robert I. Eachus 0 siblings, 2 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) Tim McDermott <mcdermott@draper.com> writes: > Matthew Heaney wrote: > > > By separating the array iteration from the item comparison, I can reason > > about the two different termination conditions independently. So > > instead of one (larger) problem with two terms, I have two (smaller) > > problems, with one term each. > > But here you are assuming that the termination conditions are > disjoint! In the general case they are not. Have you never had the > experience of writing something of the form > > while (A) { > > if (B) return b; > ... > if (C) return c; > ... > if (D) return d; > > } > > only to discover some time later that A&!B&!C (the path predicate of > the if(D) statement forces the value of D? Worse yet, that the > evaluation of the loop predicate interacts with the evaluation of the > if predicates. My experience tells me that distributing complexity is > a Bad Idea. > > That is not to say that I always use se/se. But I know that se/se is better > form, and I have a real good idea of the risks of multiple return coding. Let's consider a real-life problem that I had to solve last week. I have a string that was padded on the right with blanks. What I need to do is strip off the blanks, and return the index of the last non-blank character. Let's analyze this problem first using Dijkstra's predicate transformer, and then using Ada. S is a string of length n. It is indexed starting from 0, and therefore ending with index n-1. The Linear Search theorem tells us to search backwards from the maximum index value, since we want to find the maximum index with a character that is not blank. If the string is all blanks, then we return -1. Here's the postcondition: R: -1 <= i < n and Aj: i+1 <= j < n: S[j] = ' ' and i /= -1 => S[i] /= ' ' Let's derive the invariant by weakening the postcondition, which in this case means just removing some conjuncts. Studying the postcondition for things always true means that the postcondition is P: -1 <= i < n and Aj: i+1 <= j < n: S[j] = ' ' We know that P and not B => R where B is the loop predicate. So our loop predicate is the negation of that last conjunct of the postcondition: not B is: i /= -1 => S[i] /= ' ' Getting rid of the implication: i /= -1 => S[i] /= ' ' is same as i = -1 cor S[i] /= ' ' Now negate this to give us the loop predicate: i /= -1 cand S[i] = ' ' Initialization means making the invariant true, so just initialize i to the value n-1. (The universal quantifier is true by virtue of the fact that a null range is defined to have the value True.) Here is the result of our efforts: i := n-1; do i /= -1 cand S[i] = ' ' -> i := i - 1 od QED As Benjamin Whorf is want to remind us, the language we use has a profound effect on how we think. The Ada language provides loop constructs to traverse an array, and so the Ada programmer will "naturally" use a for loop, not a while loop, to index into the string. This doesn't mean you can't use a while loop to do the job. But if you do, you'll force readers of your code to ask why you didn't just use a for loop. They'll ask, because you violated the Principle of Least Astonishment. What if the string is all blanks? In a real program, the bounds of a non-null string can be any positive integer (starting with 1). Let's therefore return the value 0 if there are all blanks in the string. (We could have easily decided to return S'First - 1, or indeed any number less than S'First.) The Ada programmer first tackles the job of setting up the loop. We use a for loop, iterating in reverse (because we're searching for the largest index that's not a blank): procedure Op (S : in String) is Last : Natural := ???; begin for Index in reverse S'Range loop ??? end loop; We have to give Last the value of the largest index that's not a blank. for Index in reverse S'Range loop if S (Index) /= ' ' then Last := Index; ... If the string comprises all blanks, then we'll iterate over the entire string without the if-test ever being true, and so we have to give Last a default value to handle that case: Last : Natural := 0; begin for Index in reverse S'Range loop ... If we do find a value that's not blank, then we just bail out of the loop, because we're done: Last : Natural := 0; begin for Index in reverse S'Range loop if S (Index) /= ' ' then Last := Index; exit; end if; end loop; {R: Last = 0 or else S (Last) /= ' '} QED That's how an Ada programmer thinks. Just think of a for loop as an array iterator. We terminate the loop early, via an exit, because we don't need to visit all components of the array. This is an example of reasoning by using the programming language itself, instead of Dijkstra's formalism. The point is that the algorithm above can be reasoned about, in spite of the presence of an exit from the middle of the loop. The examples above illustrate two modes of thinking: top-down and bottom-up. Dijkstra is clearly a top-down thinker - and a very, very good one. He likes to reason about correctness in the abstract, using the predicate calculus, independently of any specific programming language. (Indeed, he seems almost proud of the fact the none of his programs are executable.) The rest of us are bottom-up thinkers. We reason about correctness using constructs of the target language, and using idioms that have greater "cognitive fit" to the human programmer. That's what the ACM paper I cited earlier was all about: how rules about programming derived via top-down thinking clash with cognitive models (bottom-up reality) used by ordinary programmers. You tell the programmer how it "should" be done by (ie "don't terminate a loop by exiting from the middle"), but such a solution doesn't always match what a human programmer feels is a more "natural" solution to the problem. So he makes mistakes trying to reason about what he has been told is the "right" way to do it. Worse, he may even reason less, or not at all, thinking that "this must be OK because I don't exit the loop from the middle." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` Matthew Heaney @ 1998-09-17 0:00 ` Reimer Behrends 1998-09-18 0:00 ` Robert I. Eachus 1 sibling, 0 replies; 510+ messages in thread From: Reimer Behrends @ 1998-09-17 0:00 UTC (permalink / raw) Matthew Heaney (matthew_heaney@acm.org) wrote: [...] > Last : Natural := 0; > begin > for Index in reverse S'Range loop > if S (Index) /= ' ' then > Last := Index; > exit; > end if; > end loop; > > {R: Last = 0 or else S (Last) /= ' '} feature { ANY } last_non_blank(s: STRING): INTEGER is local pos: INTEGER do from pos := s.count until pos = 0 or else s @ pos /= ' ' loop pos := pos - 1 end Result := pos ensure Result = 0 or else s @ Result /= ' ' end Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` Matthew Heaney 1998-09-17 0:00 ` Reimer Behrends @ 1998-09-18 0:00 ` Robert I. Eachus 1998-09-18 0:00 ` Jeffrey C. Dege 1 sibling, 1 reply; 510+ messages in thread From: Robert I. Eachus @ 1998-09-18 0:00 UTC (permalink / raw) In article <m3pvcv6cr5.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes: > I have a string that was padded on the right with blanks. What I need > to do is strip off the blanks, and return the index of the last > non-blank character. > Let's analyze this problem first using Dijkstra's predicate transformer, > and then using Ada... Not to disagree with Matt, because he is trying to give an example of how to reason about a problem, but there is a better approach: Ada.Strings.Fixed.Trim(S,Right)'Last Of course, you probably want to use the value returned from Trim instead of just the index of the last non-blank character. (Technically, if you want to insure that the value returned for a null string is zero, you need to do: function Last_Non_Blank_Index(S: String) return Natural is Temp : constant Natural := Ada.Strings.Fixed.Trim(S,Right)'Last; begin if Temp = S'First then return 0; else return Temp; end if; end Last_Non_Blank_Index; but the convention of returning 0 in this case was not part of the original problem statement: > I have a string that was padded on the right with blanks. What I > need to do is strip off the blanks, and return the index of the > last non-blank character. Why bring this up? Because when doing ANY kind of engineering, the first approach to try should be to ask, "Is there something in the standard catalog that is available off-the-shelf?" It is so easy and enjoyable to solve these problems in Ada, that we often lose sight of how much grief using the library function will save later. For example: If you need to truncate from both ends? Change "Right" to "Both". If you need to truncate spaces and horizontal tabs from both ends, and commas and periods from the right: with Ada.Strings.Maps, Ada.Characters.Latin_1; use Ada.Strings.Maps, Ada.Characters.Latin_1; ... Ada.Strings.Fixed.Trim(S, To_Set(Space & HT), To_Set(Space & HT & Comma & Full_Stop); -- Although I would probably declare the Character_Sets as -- constants in some package. -- Robert I. Eachus with Standard_Disclaimer; use Standard_Disclaimer; function Message (Text: in Clever_Ideas) return Better_Ideas is... ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-18 0:00 ` Robert I. Eachus @ 1998-09-18 0:00 ` Jeffrey C. Dege 0 siblings, 0 replies; 510+ messages in thread From: Jeffrey C. Dege @ 1998-09-18 0:00 UTC (permalink / raw) On 18 Sep 1998 02:11:42 GMT, Robert I. Eachus <eachus@spectre.mitre.org> wrote: >In article <m3pvcv6cr5.fsf@mheaney.ni.net> Matthew Heaney <matthew_heaney@acm.org> writes: > > > I have a string that was padded on the right with blanks. What I need > > to do is strip off the blanks, and return the index of the last > > non-blank character. > > Not to disagree with Matt, because he is trying to give an example >of how to reason about a problem, but there is a better approach: > > Ada.Strings.Fixed.Trim(S,Right)'Last > if Temp = S'First then return 0; else return Temp; end if; > end Last_Non_Blank_Index; > > Why bring this up? Because when doing ANY kind of engineering, >the first approach to try should be to ask, "Is there something in the >standard catalog that is available off-the-shelf?" It is so easy and >enjoyable to solve these problems in Ada, that we often lose sight of >how much grief using the library function will save later. And if you don't have a a catalog, off-the-shelf tool to solve the problem, create a tool and put it on the shelf... -- Personally, I think my choice in the mostest-superlative-computer wars has to be the HP-48 series of calculators. They'll run almost anything. And if they can't, while I'll just plug a Linux box into the serial port and load up the HP-48 VT-100 emulator. ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <904556531. <m3lno372be.fsf@mheaney.ni.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <904556531. <m3lno372be.fsf@mheaney.ni.net> @ 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Patrick Doyle 1 sibling, 1 reply; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <m3lno372be.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > >My argument concerns the complexity of the decision table for the loop >predicate. Adding a flag doubles the number of states. I don't get this. Who enumerates the states? Who really finds this necessary to understand a loop? The termination condition is always the disjunction of the normal termination condition and the flags. A disjunction is a very simple, straightforward logical operation, and I believe that the effort in comprehending a disjunction is O(n), not O(2^n), in the number of terms. Look at this: from x := 1 until x > maximum or error_detected or user_interruption or list_is_sorted loop ... end This has four conditions. Do you really think it's 16 times harder to understand than just "until x > maximum"? I'd believe it's 4 times harder. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-03 0:00 ` Patrick Doyle @ 1998-09-03 0:00 ` Loryn Jenkins 0 siblings, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-03 0:00 UTC (permalink / raw) > The termination condition is always the disjunction of the normal > termination condition and the flags. A disjunction is a very > simple, straightforward logical operation, and I believe that > the effort in comprehending a disjunction is O(n), not O(2^n), in > the number of terms. > > Look at this: > > from > x := 1 > until > x > maximum > or error_detected > or user_interruption > or list_is_sorted > loop > ... > end > > This has four conditions. Do you really think it's 16 times harder > to understand than just "until x > maximum"? I'd believe it's 4 > times harder. Mathematically, maybe. I don't think it's even four times harder, sociologically speaking. Obviously, this is just my personal experience reading the code the first time: I took longer to understand the first and second portions of the statement, because of the change in operator. However, once I had read and comprehended the second line, the next two were real easy, real fast. I'm human, not machine. And no, I *do not* figure out a truth table for every loop I write. Instead, I use the abstractional capabilities of the tools at hand. Bertrand Meyer described these abstractions quite nicely in the paper located at http://www.elj.com/elj/v1/n3/bm/loop/. Just scan down until you get to the section beginning: [This for me is the key reason.] It is interesting to note that I *like* abstracting things. Whereas many of my colleagues (and particularly my brother, I notice), likes approaching things procedurally. I don't know why. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <904556531. <m3lno372be.fsf@mheaney.ni.net> 1998-09-03 0:00 ` Patrick Doyle @ 1998-09-03 0:00 ` Patrick Doyle 1 sibling, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-03 0:00 UTC (permalink / raw) In article <m3lno372be.fsf@mheaney.ni.net>, Matthew Heaney <matthew_heaney@acm.org> wrote: > > loop > > Get (N); > > exit when N = 0; > > <process N> > > end loop; > >eliminates the redundancy. Sorry for the two replies... This is interesting. It has only one entry and one exit. Is it not structured, then? -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.48044143@ <m3af4mq7f4 <35EC937F.94420C51@ibm.net>]
* Re: Software landmines (loops) [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EC937F.94420C51@ibm.net> @ 1998-09-07 0:00 ` Michael F Brenner 0 siblings, 0 replies; 510+ messages in thread From: Michael F Brenner @ 1998-09-07 0:00 UTC (permalink / raw) Biju > The problem with such refactoring during maintenance is that it may > introduce new problems, and you need to do extensive testing to make > sure that you haven't broken anything. Often, this type of extensive > testing may not be feasible at all during maintenance, because of budget > and time constraints. This type of attitude may explain why new releases > of software (which are supposed to do bug fixing too) introduce more > bugs than the original version. I think you meant: this type of attitude (refactoring during maintenance) explains new bugs being released. However, I think this is what is true: this type of attitude (coding systems that are expensive to test automatically) explains new bugs being released. Most large systems have: no automated unit testing (all paths or all extreme values), no automated stress testing, no automated functional (requirements) testing, no automated regression (to previous baselines) testing, no automated hanging pointer testing, no automated performance testing, and no automated memory leakage measurement. Exits in the middle of the loop or any other syntactic feature used (gotos, nested tasking, complex expressions, high complexity measures, high lines of code, etc.) are all just noise compared to the lifecycle cost of not automatically testing for bugs, hanging pointers, and memory leakage. We should remove the log before worrying about the twig. Mike Brenner ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.480<904556531.666222@ <6t42kg$son$1@hirame.wwa.com>]
* Re: Software landmines (loops) [not found] ` <35f51e53.480<904556531.666222@ <6t42kg$son$1@hirame.wwa.com> @ 1998-09-08 0:00 ` Patrick Doyle 0 siblings, 0 replies; 510+ messages in thread From: Patrick Doyle @ 1998-09-08 0:00 UTC (permalink / raw) In article <6t42kg$son$1@hirame.wwa.com>, Robert Martin <rmartin@oma.com> wrote: > >duncan@yc.estec.esa.nlx wrote in message ... > >>Even with an indent level of only 2 spaces, the code would >>regularly march off the right of the screen and wrap around, >>making readability, maintenance and reformatting in the event >>of a change an absolute nightmare. > >In this extreme situation it seems clear that you'd want to use multiple >exits. The cost of the se/se solution in this context probably outweighs >any benefits that might be derived. It seems clear, IMHO, that what's really needed is a better data abstraction. Having multiple functions which all traverse a data structure and do all sorts of error checking along the way seems to scream for a better abstraction. Of course, this is based on limited info about the project, and the design certainly could have been justified. -PD -- -- Patrick Doyle doylep@ecf.toronto.edu ^ permalink raw reply [flat|nested] 510+ messages in thread
[parent not found: <35f51e53.480 <904556531.66622 <EyyLos.2nx@yc.estec.esa.nl>]
* Re: Software landmines (loops) [not found] ` <35f51e53.480 <904556531.66622 <EyyLos.2nx@yc.estec.esa.nl> @ 1998-09-08 0:00 ` duncan 1998-09-16 0:00 ` Matthew Heaney 1998-09-08 0:00 ` Jim Cochrane 1 sibling, 1 reply; 510+ messages in thread From: duncan @ 1998-09-08 0:00 UTC (permalink / raw) One issue which I haven't yet seen addressed in this thread (but then our news feed is particularly patchy) is abnormal flow of control. As far as I can see, the single entry/single exit paradigm assumes that there is a simple flow of control, through the code as you can see it. So far, nobody has made any comment on "abnormal" flow of control, such as interrupts, multi-threading, and what might be more interesting in these news groups, exceptions. Any comments? This is my article, not my employer's, with my opinions and my disclaimer! -- Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx To avoid junk email my quoted address is incorrect. Use nl instead of nlx. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` duncan @ 1998-09-16 0:00 ` Matthew Heaney 1998-09-17 0:00 ` Reimer Behrends 0 siblings, 1 reply; 510+ messages in thread From: Matthew Heaney @ 1998-09-16 0:00 UTC (permalink / raw) duncan@yc.estec.esa.nlx writes: > One issue which I haven't yet seen addressed in this thread (but then > our news feed is particularly patchy) is abnormal flow of control. > > As far as I can see, the single entry/single exit paradigm assumes > that there is a simple flow of control, through the code as you can > see it. So far, nobody has made any comment on "abnormal" flow of > control, such as interrupts, multi-threading, and what might be more > interesting in these news groups, exceptions. This has been discussed wrt resource management. Robert Martin argued against early returns (or middle-exit loops) by stating that you might forget to release a resource, if you return early. I gave the counter-example that the resource management problem should be solved another way, by using a deconstructor (C++) or a controlled type (Ada95). I based my arguement on the fact that this is what you should do no matter what, because of the presence of exceptions. Stroustrup calls this idiom "resource acquistion is initialization." ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-16 0:00 ` Matthew Heaney @ 1998-09-17 0:00 ` Reimer Behrends 1998-09-17 0:00 ` Ell 0 siblings, 1 reply; 510+ messages in thread From: Reimer Behrends @ 1998-09-17 0:00 UTC (permalink / raw) Anybody got a suggestion what a reasonable value for Followup-To would be for this? Matthew Heaney (matthew_heaney@acm.org) wrote: [...] > Robert Martin argued against early returns (or middle-exit loops) by > stating that you might forget to release a resource, if you return > early. Or more generally, to reestablish a predicate that has been temporarily violated. > I gave the counter-example that the resource management problem should > be solved another way, by using a deconstructor (C++) or a controlled > type (Ada95). I based my arguement on the fact that this is what you > should do no matter what, because of the presence of exceptions. > > Stroustrup calls this idiom "resource acquistion is initialization." It should, however, be noted that there are those who as a general rule don't use exceptions at all, with the obvious benefits alluded to by Robert Martin. Also, using single-entry/single-exit in such a strict fashion allows you to view _any_ code block as an abstract unit, with the added benefit that you can decompose and restructure complex code almost at will. Reimer Behrends ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-17 0:00 ` Reimer Behrends @ 1998-09-17 0:00 ` Ell 0 siblings, 0 replies; 510+ messages in thread From: Ell @ 1998-09-17 0:00 UTC (permalink / raw) In comp.object Reimer Behrends <behrends@cse.msu.edu> wrote: : It should, however, be noted that there are those who as a general rule : don't use exceptions at all, with the obvious benefits alluded to by : Robert Martin. Also, using single-entry/single-exit in such a strict : fashion allows you to view _any_ code block as an abstract unit, with : the added benefit that you can decompose and restructure complex code : almost at will. At the point of each one of the mutiple exits the post-conditions for the code block as a whole can be checked. "Multiple exits" do not mean that each exit must immediately leave the code block without some form of checking. Elliott -- :=***=: VOTE NO TO MODERATION! ALL IDEAS SHOULD BE CRITICIZABLE! :=***=: MODERATORS SHOULD NOT HAVE LIFETIME TERMS! :=***=: Objective * Pre-code Modelling * Holistic :=***=: Hallmarks of the best SW Engineering Check out SW Modeller vs SW Craftite Central : www.access.digex.net/~ell Copyright 1998 Elliott. exclusive of others' writing. may be copied without permission only in the comp.* usenet and bitnet groups. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) [not found] ` <35f51e53.480 <904556531.66622 <EyyLos.2nx@yc.estec.esa.nl> 1998-09-08 0:00 ` duncan @ 1998-09-08 0:00 ` Jim Cochrane 1998-09-09 0:00 ` duncan 1998-09-09 0:00 ` Charles Hixson 1 sibling, 2 replies; 510+ messages in thread From: Jim Cochrane @ 1998-09-08 0:00 UTC (permalink / raw) Of course, if the conditions being checked in the code below are really pre-conditions - that is, it can be considered a coding error that the function is called with one of these conditions true, then it would be better coded as: void Worker::do_something (Tree *top) { assert (top != NULL && top->child != NULL && ...); _error_code = really_do_something(top->child...->child); if (_error_code != 0) // or whatever value means non-error { _error_occurred = true; } else { _error_occurred = false; } } Where the assertion would be documented as a pre-condition of the function specification. Then a client would do: // ensure the pre-condition for root worker.do_something (root); if (worker.error_occurred()) { //report/handle the error with worker.error_code() ... } [Changed to an OO style, since the discussion is occurring on OO newsgroups.] The difference, of course, is that the checking for null pointers becomes part of the function specification rather than being explicitely coded (the assertion will probably be turned of in the production release). This is the difference between design by contract and defensive coding. In article <EyyLos.2nx@yc.estec.esa.nl>, <duncan@yc.estec.esa.nlx> wrote: > > >This is a response to several articles in different subthreads, so >you might not have seen some of the quoted articles on your way here... > > ... >Although many people may have been taught about Structured Programming, >and the importance of single entry and single exit points for program >proving and testing, there are often times when other factors - shall I >say "political" rather than technical - come into play. > >For example, I once worked on a C project where se/se was the be-all >and end-all of the technical factors, with the testing for errors at >every point coming in a close second. As the system consisted of 7 >sub-systems all communicating via shared memory there was the risk >that although the logic in one system would preclude future errors, >this couldn't be guaranteed in general. The data was organised in >huge tree structures, all linked by pointers. Therefore, each routine >always did "redundant" testing: > >int doSomething(Tree *pTop) >{ > int errorCode; > > if (pTop != NULL) > { > if (pTop->pChild != NULL) > { > if (pTop->pChild->pChild != NULL) > { > /* lots of nesting omitted */ > > if (pTop->pChild...->pChild != NULL) > { > errorCode = reallyDoSomething(pTop->pChild...->pChild); > } else > { > errorCode = ERRORX; > } else > { > errorCode = ERROR3; > } > } else > { > errorCode = ERROR2; > } > } else > { > errorCode = ERROR1; > } > return(errorCode); >} > -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Jim Cochrane @ 1998-09-09 0:00 ` duncan 1998-09-11 0:00 ` Jim Cochrane 1998-09-09 0:00 ` Charles Hixson 1 sibling, 1 reply; 510+ messages in thread From: duncan @ 1998-09-09 0:00 UTC (permalink / raw) In article <6t4dmi$rhp@flatland.dimensional.com>, Jim Cochrane <jtc@dimensional.com> wrote: >Of course, if the conditions being checked in the code below are really >pre-conditions - that is, it can be considered a coding error that the >function is called with one of these conditions true, then it would be >better coded as: > >void Worker::do_something (Tree *top) >{ > assert (top != NULL && top->child != NULL && ...); > > _error_code = really_do_something(top->child...->child); > if (_error_code != 0) // or whatever value means non-error > { > _error_occurred = true; > } > else > { > _error_occurred = false; > } >} > >Where the assertion would be documented as a pre-condition of the function >specification. > >Then a client would do: > > // ensure the pre-condition for root > worker.do_something (root); > if (worker.error_occurred()) > { > //report/handle the error with worker.error_code() ... > } > >[Changed to an OO style, since the discussion is occurring on OO >newsgroups.] > >The difference, of course, is that the checking for null pointers becomes >part of the function specification rather than being explicitely coded (the >assertion will probably be turned of in the production release). This is >the difference between design by contract and defensive coding. The first 'Commandments' for coding were: 1. Thou shalt use single entry/single exit routines. 2. Thou shalt guarantee all pointers before dereferencing. As mentioned before, the system was made up of 7 sub-systems, all running as separate processes, and communicating via shared memory. Hence there was a lot of 'redundant' checking. Yes, you could use 'assert' but seeing as the error checking had to go into the production code anyway, there was little point. Yes, the pre-conditions could have been checked before the routine was actually called, but now you have moved knowledge of where in the tree data structure the relevant information lives into the caller. When you consider that some of the paths through the tree involved following 6 or more pointers, that's a lot of encapsulation and data hiding that has been lost. All of the code for determining which error has occurred has also been moved from the routine to the caller... These are all tradeoffs that need to be made. I believe that there are various 'good practices' which should be included in an ideal world, but until I find employment in the ideal world, it's going to be a case of making these tradeoffs, and some of the 'good practices' may not be applied in all cases. Of course it helps if you are aware of the 'good practices' in the first place so that you know what you are missing. Cheers Duncan This is my article, not my employer's, with my opinions and my disclaimer! -- Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx To avoid junk email my quoted address is incorrect. Use nl instead of nlx. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` duncan @ 1998-09-11 0:00 ` Jim Cochrane 1998-09-11 0:00 ` duncan 0 siblings, 1 reply; 510+ messages in thread From: Jim Cochrane @ 1998-09-11 0:00 UTC (permalink / raw) In article <Ez0D7y.DCG@yc.estec.esa.nl>, <duncan@yc.estec.esa.nlx> wrote: >In article <6t4dmi$rhp@flatland.dimensional.com>, >Jim Cochrane <jtc@dimensional.com> wrote: >>Of course, if the conditions being checked in the code below are really >>pre-conditions - that is, it can be considered a coding error that the >>function is called with one of these conditions true, then it would be >>better coded as: >> >>void Worker::do_something (Tree *top) >>{ >> assert (top != NULL && top->child != NULL && ...); >> >> _error_code = really_do_something(top->child...->child); >> if (_error_code != 0) // or whatever value means non-error >> { >> _error_occurred = true; >> } >> else >> { >> _error_occurred = false; >> } >>} >> >>Where the assertion would be documented as a pre-condition of the function >>specification. >> >>Then a client would do: >> >> // ensure the pre-condition for root >> worker.do_something (root); >> if (worker.error_occurred()) >> { >> //report/handle the error with worker.error_code() ... >> } >> >>[Changed to an OO style, since the discussion is occurring on OO >>newsgroups.] >> >>The difference, of course, is that the checking for null pointers becomes >>part of the function specification rather than being explicitely coded (the >>assertion will probably be turned of in the production release). This is >>the difference between design by contract and defensive coding. > > >The first 'Commandments' for coding were: >1. Thou shalt use single entry/single exit routines. >2. Thou shalt guarantee all pointers before dereferencing. > >As mentioned before, the system was made up of 7 sub-systems, >all running as separate processes, and communicating via >shared memory. Hence there was a lot of 'redundant' checking. I understand that things are not black and white in the "real world" and that compromises sometimes need to be made. (For one thing, the fact that C was used here, which has no exception handling mechanism, is a factor in what path to take.) However, I think if I was in this situation, I would ask a few questions, such as: What are the error handling requirements in the case where a pointer is null? If one of these errors does occur, is this a coding error, a bug? If so, where would the source of this bug likely be? If one of these errors occurred, will the program still be able to run correctly? In other words, can the program recover from the error, or should it report the error and terminate in order to not cause a problem, such as corrupted data? Who (what module(s) or routine(s)) is responsible for building the tree so that the required nodes were not null? If the answer is that no-one was responsible, can the design be changed so that this responsibility can be assigned to a particular module or modules? Who (what module or routine) is responsible for setting things right (if that is possible) if an error does occur? Can the fact that a certain depth of the tree is required be considered a contract that must be established by some (direct or indirect) client routine, even if it is in another process? Can the design be changed so that, even if assertions cannot reasonably be used, the structure is less awkward? (At the very least, it seems, the original "do_something" function could be structured to check for the error and report it first, rather than nesting the check of each node, as the original did: if (null_descendant (root, required_depth, &null_depth)) { //report that error occurred at depth null_depth and deal with it } else { really_do_something(top->child...->child); ... }) I suppose my main point is that rather than simply following an edict, it is important to ask questions like these to find out if there might be a better way of doing things. If this was done, and the decision to proceed as you described was done for a good reason, then that is basically all you can ask. > >Yes, you could use 'assert' but seeing as the error checking >had to go into the production code anyway, there was little point. > >Yes, the pre-conditions could have been checked before the >routine was actually called, but now you have moved knowledge >of where in the tree data structure the relevant information >lives into the caller. When you consider that some of the paths >through the tree involved following 6 or more pointers, that's >a lot of encapsulation and data hiding that has been lost. >All of the code for determining which error has occurred has >also been moved from the routine to the caller... > >These are all tradeoffs that need to be made. I believe that >there are various 'good practices' which should be included >in an ideal world, but until I find employment in the ideal >world, it's going to be a case of making these tradeoffs, and >some of the 'good practices' may not be applied in all cases. > >Of course it helps if you are aware of the 'good practices' >in the first place so that you know what you are missing. Definitely - both because you will likely be able to apply these practices in the future, and, even in the case where such a compromise is made, this knowledge will still allow you to do a better job (write more correct code, etc.) within the context of the existing environment. > >Cheers >Duncan > >This is my article, not my employer's, with my opinions and my disclaimer! >-- >Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands >Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx >To avoid junk email my quoted address is incorrect. Use nl instead of nlx. -- Jim Cochrane jtc@dimensional.com ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-11 0:00 ` Jim Cochrane @ 1998-09-11 0:00 ` duncan 0 siblings, 0 replies; 510+ messages in thread From: duncan @ 1998-09-11 0:00 UTC (permalink / raw) In article <6taqch$42b@flatland.dimensional.com>, Jim Cochrane <jtc@dimensional.com> wrote: > >I understand that things are not black and white in the "real world" and >that compromises sometimes need to be made. (For one thing, the fact that >C was used here, which has no exception handling mechanism, is a factor in >what path to take.) However, I think if I was in this situation, I would >ask a few questions, such as: > >What are the error handling requirements in the case where a pointer is null? >If one of these errors does occur, is this a coding error, a bug? >If so, where would the source of this bug likely be? >If one of these errors occurred, will the program still be able to run >correctly? In other words, can the program recover from the error, or >should it report the error and terminate in order to not cause a problem, >such as corrupted data? >Who (what module(s) or routine(s)) is responsible for building the tree so that >the required nodes were not null? If the answer is that no-one was >responsible, can the design be changed so that this responsibility can be >assigned to a particular module or modules? >Who (what module or routine) is responsible for setting things right (if >that is possible) if an error does occur? >Can the fact that a certain depth of the tree is required be considered a >contract that must be established by some (direct or indirect) client >routine, even if it is in another process? >Can the design be changed so that, even if assertions cannot reasonably be >used, the structure is less awkward? (At the very least, it seems, the >original "do_something" function could be structured to check for the error >and report it first, rather than nesting the check of each node, as the >original did: > > if (null_descendant (root, required_depth, &null_depth)) > { > //report that error occurred at depth null_depth and deal with it > } > else > { > really_do_something(top->child...->child); > ... > }) > >I suppose my main point is that rather than simply following an edict, it >is important to ask questions like these to find out if there might be a >better way of doing things. If this was done, and the decision to proceed >as you described was done for a good reason, then that is basically all you >can ask. I agree with everything you say. The system I've been describing was one I worked on 10 years ago, but it taught everyone concerned many valuable lessons. Unfortunately, we inherited all of this code (in C) from a previous programming group in a different country, so all of the decisions had already been made and we had to go along with the existing style. With the usual tight schedule for such things, it was simply not possible to revisit the original analysis and design decisions. As I've stressed before, the system consisted of 7 processes communicating via shared memory, and I believe that the obsessive checking of all pointers stemmed from paranoia about which process could update what and when. As it turned out, the project was canned after our group had been working on it for a year, mainly because it was just too slow, and just for the hell of it someone instrumented some of of the code before all 4000+ source files were wiped from disk and we moved on to other things. He discovered that the paranoia was not well founded. He discovered that only two out of the seven processes actually had need to access the data simultaneously, and even then they took copies on which to work and derived results into their own area of shared memory. No other processes could run until these two completed, so there was no chance of incomplete data being read prematurely. A lot of the code was simply over-engineered to take into account something that was not likely to happen. All access to the shared memory was controlled by semaphores. All pointer access was checked. No wonder it ran so slowly. Maybe earlier designs were more likely to suffer from problems - it ran on custom built hardware until we got our hands on it - or it was considered that even a crash resulting from the unlikely was still not acceptable. The whole purpose of this string of articles is to illustrate that sometimes it is not always possible to follow all of the 'good practices' that you have learned, and that there will always be compromises. Cheers Duncan This is my article, not my employer's, with my opinions and my disclaimer! -- Duncan Gibson, ESTEC/YCV, Postbus 299, 2200AG Noordwijk, The Netherlands Tel: +31 71 5654013 Fax: +31 71 5656142 Email: duncan@yc.estec.esa.nlx To avoid junk email my quoted address is incorrect. Use nl instead of nlx. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-08 0:00 ` Jim Cochrane 1998-09-09 0:00 ` duncan @ 1998-09-09 0:00 ` Charles Hixson 1998-09-10 0:00 ` Loryn Jenkins 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 2 replies; 510+ messages in thread From: Charles Hixson @ 1998-09-09 0:00 UTC (permalink / raw) Jim Cochrane wrote: > > Of course, if the conditions being checked in the code below are really > pre-conditions - that is, it can be considered a coding error that the > function is called with one of these conditions true, then it would be > better coded as: > > void Worker::do_something (Tree *top) > { > assert (top != NULL && top->child != NULL && ...); > > _error_code = really_do_something(top->child...->child); > if (_error_code != 0) // or whatever value means non-error > { > _error_occurred = true; > } > else > { > _error_occurred = false; > } > } > > Where the assertion would be documented as a pre-condition of the function > specification. > > Then a client would do: > > // ensure the pre-condition for root > worker.do_something (root); > if (worker.error_occurred()) > { > //report/handle the error with worker.error_code() ... > } > > [Changed to an OO style, since the discussion is occurring on OO > newsgroups.] > > The difference, of course, is that the checking for null pointers becomes > part of the function specification rather than being explicitely coded (the > assertion will probably be turned of in the production release). This is > the difference between design by contract and defensive coding. > ... > -- > Jim Cochrane > jtc@dimensional.com It has been claimed that Design By Contract (DBC) can be done entirely by comments and documentation. I, personally, don't believe it. It is my expectation that the routines with explicit pre-conditions and post-conditions would work as desired in the Eiffel environment, where the developer could have pre-conditions enabled while developing it, and only remove them (IN LAYERS!) when the final code was produced. I don't think that this would work at all as well without support from the IDE. Now it is true, that the failures of DBC in an environment that doesn't support it can be traced to the contract not being lived up to, but ENFORCEABILITY IS A PART OF THE CONTRACT. In an environment that doesn't enforce the contract, violations will not be detected, and I don't know about you, but my programs always need to have the bugs cleaned out of them before they are ready for delivery. ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Charles Hixson @ 1998-09-10 0:00 ` Loryn Jenkins 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Loryn Jenkins @ 1998-09-10 0:00 UTC (permalink / raw) > It has been claimed that Design By Contract (DBC) can be done entirely > by comments and documentation. I, personally, don't believe it. It is > my expectation that the routines with explicit pre-conditions and > post-conditions would work as desired in the Eiffel environment, where > the developer could have pre-conditions enabled while developing it, and > only remove them (IN LAYERS!) when the final code was produced. I don't > think that this would work at all as well without support from the IDE. > > Now it is true, that the failures of DBC in an environment that doesn't > support it can be traced to the contract not being lived up to, but > ENFORCEABILITY IS A PART OF THE CONTRACT. In an environment that > doesn't enforce the contract, violations will not be detected, and I > don't know about you, but my programs always need to have the bugs > cleaned out of them before they are ready for delivery. Yes, of course it can. And yes, it would not nearly be as clean or easy to do without the Eiffel environment support. Having said that, Geoff Eldridge has used this style quite successfully in Perl (as documentation only); Don Harrison has used it very successfully in Ada (using Ada approximations pre-, post-conditions and invariants); others have used it to good effect in C++. It most certainly is a rigorous methodological approach to designing software (and therefore is not specific to a language), but is greatly helped by automated tool support. Loryn Jenkins ^ permalink raw reply [flat|nested] 510+ messages in thread
* Re: Software landmines (loops) 1998-09-09 0:00 ` Charles Hixson 1998-09-10 0:00 ` Loryn Jenkins @ 1998-09-17 0:00 ` Matthew Heaney 1 sibling, 0 replies; 510+ messages in thread From: Matthew Heaney @ 1998-09-17 0:00 UTC (permalink / raw) Charles Hixson <charleshixsn@earthlink.net> writes: > It has been claimed that Design By Contract (DBC) can be done entirely > by comments and documentation. I, personally, don't believe it. It is > my expectation that the routines with explicit pre-conditions and > post-conditions would work as desired in the Eiffel environment, where > the developer could have pre-conditions enabled while developing it, and > only remove them (IN LAYERS!) when the final code was produced. I don't > think that this would work at all as well without support from the IDE. > > Now it is true, that the failures of DBC in an environment that doesn't > support it can be traced to the contract not being lived up to, but > ENFORCEABILITY IS A PART OF THE CONTRACT. In an environment that > doesn't enforce the contract, violations will not be detected, and I > don't know about you, but my programs always need to have the bugs > cleaned out of them before they are ready for delivery. Use assertions to check preconditions. When you're satisfied everyone is obeying them, then recompile the body with assertions turned off: function Get_Top (Stack : Stack_Type) return Stack_Item is begin pragma Assert (Stack.Top /= 0); ... end Get_Top; You can even use a controlled type to check that a representation invariant is being satisfied on procedure entry and exit. ^ permalink raw reply [flat|nested] 510+ messages in thread
end of thread, other threads:[~1998-10-15 0:00 UTC | newest] Thread overview: 510+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1998-09-07 0:00 Software landmines (loops) Robert Martin 1998-09-08 0:00 ` Mike Spille -- strict thread matches above, loose matches on Subject: below -- 1998-08-06 0:00 Why C++ is successful Robert Dewar 1998-08-07 0:00 ` harald.mueller 1998-08-07 0:00 ` Brian Rogoff 1998-08-07 0:00 ` Timothy Welch 1998-08-08 0:00 ` Robert Dewar 1998-08-08 0:00 ` Jeffrey C. Dege 1998-08-10 0:00 ` Laurent GUERBY 1998-08-12 0:00 ` Andy Ward 1998-08-14 0:00 ` Robert Dewar 1998-08-14 0:00 ` Software landmines (was: Why C++ is successful) dennison 1998-08-16 0:00 ` Robert Dewar 1998-08-17 0:00 ` dennison 1998-08-19 0:00 ` ell 1998-08-19 0:00 ` adam 1998-08-19 0:00 ` Dan Higdon 1998-08-20 0:00 ` adam 1998-08-20 0:00 ` Software landmines (loops) Nick Leaton 1998-08-30 0:00 ` Matthew Heaney 1998-08-30 0:00 ` Robert Martin 1998-08-30 0:00 ` Charles Hixson 1998-08-31 0:00 ` Robert I. Eachus 1998-08-31 0:00 ` dennison 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Andrew Reilly 1998-09-01 0:00 ` dennison 1998-09-01 0:00 ` dewarr 1998-09-01 0:00 ` Matthew Heaney [not found] ` <35f51e53.48044143@news.erols.c <m3af4mq7f4.fsf@mheaney.ni.net> 1998-08-31 0:00 ` Patrick Doyle 1998-08-31 0:00 ` Gene Gajewski 1998-08-31 0:00 ` Richard D Riehle 1998-09-01 0:00 ` Simon Wright 1998-09-02 0:00 ` adam 1998-09-01 0:00 ` Matthew Heaney [not found] ` <35f51e53.48044143@ <m3af4mq7f4.fsf@mheaney.ni.net> 1998-08-31 0:00 ` Andrew Hussey 1998-08-31 0:00 ` Mattias Lundstr�m 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Robert I. Eachus 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Stephen Leake 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Richard Jones 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 1998-09-01 0:00 ` Mattias Lundstr�m 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Robert I. Eachus 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mattias Lundstr�m 1998-09-01 0:00 ` Tim Ottinger 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Tim McDermott 1998-08-31 0:00 ` Larry Brasfield 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` dewar 1998-09-01 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Gene Gajewski 1998-09-01 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerhard Menzl 1998-09-02 0:00 ` Tres Seaver 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Patrick Logan 1998-09-01 0:00 ` Robert I. Eachus 1998-09-01 0:00 ` sureshvv 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` sureshvv 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Charles Hixson 1998-09-04 0:00 ` Patrick Logan 1998-09-04 0:00 ` adam 1998-09-06 0:00 ` Gerry Quinn 1998-09-04 0:00 ` Rick Smith 1998-09-04 0:00 ` Charles Hixson 1998-09-04 0:00 ` Robert Martin 1998-09-08 0:00 ` adam 1998-09-08 0:00 ` Rick Smith [not found] ` <gio+van+no+ni+8-0809981818260001@dialup75.tlh.talstar.com> 1998-09-08 0:00 ` Rick Smith 1998-09-08 0:00 ` Mark A Biggar 1998-09-02 0:00 ` Robert Martin 1998-09-01 0:00 ` Richard Melvin 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Jim Cochrane 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Jim Cochrane 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Jim Cochrane 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Biju Thomas 1998-09-02 0:00 ` Phil Goodwin 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Phil Goodwin 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-01 0:00 ` Chris Brand 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Biju Thomas 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` James Weirich 1998-09-01 0:00 ` Mike Spille 1998-09-02 0:00 ` Nick Leaton 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Chris Saunders 1998-09-02 0:00 ` Nick Leaton 1998-09-01 0:00 ` Darren New 1998-09-02 0:00 ` Loryn Jenkins 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` John Volan 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Loryn Jenkins 1998-09-02 0:00 ` Tim McDermott 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Joe Gamache 1998-09-04 0:00 ` Charles Hixson 1998-09-05 0:00 ` Patrick Logan 1998-09-05 0:00 ` Charles Hixson 1998-09-04 0:00 ` Charles Hixson 1998-09-05 0:00 ` Loryn Jenkins 1998-09-01 0:00 ` dewarr 1998-09-04 0:00 ` Jean-Marc Jezequel 1998-09-04 0:00 ` Richard Melvin 1998-09-07 0:00 ` Jean-Marc Jezequel 1998-09-01 0:00 ` Don Harrison 1998-09-01 0:00 ` dewarr 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Jeffrey C. Dege 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Gene Gajewski 1998-08-31 0:00 ` Stephen Leake 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Agent 1998-09-01 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-09-01 0:00 ` Tim Ottinger 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` dennison 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Andrew Reilly 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` dennison [not found] ` <6sfqul$ggg$1@hirame. <6sidsq$e6c$1@hirame.wwa.com> 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Charles Hixson 1998-09-03 0:00 ` John G. Volan 1998-09-01 0:00 ` Phil Goodwin 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Tim Ottinger 1998-09-02 0:00 ` dennison 1998-09-02 0:00 ` Richard Melvin 1998-09-02 0:00 ` Richard MacDonald (dogmat) 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-0309982244140001@dialup62.tlh.talstar.com> 1998-09-04 0:00 ` Ell [not found] ` <gio+van+no+ni+8-0309982225160001@dialup62.tlh.talstar.com> 1998-09-15 0:00 ` mfinney 1998-09-01 0:00 ` Matthew Heaney 1998-10-01 0:00 ` Charles H. Sampson 1998-10-02 0:00 ` Robert C. Martin 1998-10-02 0:00 ` Charles H. Sampson 1998-10-03 0:00 ` Reimer Behrends 1998-10-04 0:00 ` Charles H. Sampson 1998-10-05 0:00 ` Reimer Behrends 1998-10-05 0:00 ` Patrick Logan 1998-10-06 0:00 ` Charles H. Sampson 1998-10-11 0:00 ` Reimer Behrends 1998-10-02 0:00 ` John I. Moore, Jr. 1998-10-02 0:00 ` Ell 1998-10-03 0:00 ` John Goodsen 1998-10-03 0:00 ` Robert C. Martin 1998-10-03 0:00 ` Richard D Riehle 1998-10-03 0:00 ` Ell 1998-10-03 0:00 ` John I. Moore, Jr. 1998-10-05 0:00 ` Robert C. Martin 1998-10-06 0:00 ` Matt Kennel 1998-10-06 0:00 ` Ell 1998-10-05 0:00 ` dewarr 1998-10-04 0:00 ` Robert C. Martin 1998-10-05 0:00 ` Ell 1998-10-05 0:00 ` Ell 1998-10-05 0:00 ` Ell 1998-10-09 0:00 ` Matthew Heaney 1998-10-09 0:00 ` Ell 1998-10-02 0:00 ` Ell 1998-10-03 0:00 ` Ell 1998-10-03 0:00 ` Ell 1998-10-05 0:00 ` Graham Perkins 1998-10-08 0:00 ` s350817 1998-10-09 0:00 ` Matthew Heaney 1998-10-02 0:00 ` Ell 1998-08-31 0:00 ` Matthew Heaney 1998-08-31 0:00 ` Patrick Logan 1998-09-01 0:00 ` dewarr 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Ell 1998-08-31 0:00 ` Robert Martin 1998-09-03 0:00 ` Steven Perryman 1998-09-01 0:00 ` Charles Hixson 1998-08-31 0:00 ` Phlip 1998-08-31 0:00 ` Robert Martin 1998-08-31 0:00 ` Gene Gajewski 1998-09-01 0:00 ` Charles Hixson [not found] ` <35f51e53.48044143@ <904556531.666222@miso.it.uq.edu.au> 1998-09-01 0:00 ` Gerry Quinn 1998-09-01 0:00 ` Robert Martin 1998-09-01 0:00 ` Gerry Quinn 1998-09-01 0:00 ` Robert Martin 1998-09-02 0:00 ` Gerry Quinn 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-04 0:00 ` Andre Tibben 1998-09-04 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Gerry Quinn 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Ell 1998-09-04 0:00 ` Ell 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Doyle 1998-09-05 0:00 ` Ell 1998-09-05 0:00 ` Jeffrey C. Dege 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Patrick Doyle 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Patrick Logan 1998-09-08 0:00 ` Tim McDermott 1998-09-08 0:00 ` Patrick Doyle 1998-09-08 0:00 ` Patrick Logan 1998-09-17 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Robert Martin 1998-09-09 0:00 ` Tim Ottinger 1998-09-17 0:00 ` Matthew Heaney 1998-09-16 0:00 ` Tim Ottinger 1998-09-05 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 1998-09-05 0:00 ` Robert Martin 1998-09-06 0:00 ` Loryn Jenkins 1998-09-04 0:00 ` Robert Martin 1998-09-05 0:00 ` Loryn Jenkins 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Mike Spille 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Robert Martin 1998-09-04 0:00 ` Mike Spille 1998-09-05 0:00 ` Ell 1998-09-04 0:00 ` Ray Blaak 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Robert Martin 1998-09-07 0:00 ` Patrick Logan 1998-09-04 0:00 ` Gerry Quinn [not found] ` <EyyLos.2nx@yc.estec.esa.nl> 1998-09-08 0:00 ` Robert Martin 1998-09-08 0:00 ` John G. Volan 1998-09-08 0:00 ` duncan 1998-09-08 0:00 ` Patrick Doyle 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Charles Hixson 1998-09-09 0:00 ` sureshvv 1998-09-03 0:00 ` Patrick Logan 1998-09-04 0:00 ` Matthew Heaney [not found] ` <6skqf3$ <35F0B5B0.8E2D0166@s054.aone.net.au> 1998-09-06 0:00 ` Will Rose 1998-09-06 0:00 ` Ell 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-01 0:00 ` Mike Spille 1998-09-01 0:00 ` Robert Martin [not found] ` <gio+van+no+ni+8-0309982212300001@dialup62.tlh.talstar.com> 1998-09-04 0:00 ` Robert I. Eachus [not found] ` <gio+van+no+ni+8-0809981840170001@dialup75.tlh.talstar.com> 1998-09-09 0:00 ` Nick Leaton [not found] ` <gio+van+no+ni+8-1609980026290001@dialup26.tlh.talstar.com> 1998-09-16 0:00 ` Nick Leaton 1998-09-02 0:00 ` mfinney 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` john-clonts 1998-09-02 0:00 ` Darren New 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Oliver 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` sureshvv 1998-09-03 0:00 ` Patrick Logan 1998-09-06 0:00 ` Charles Hixson 1998-09-07 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` Jeffrey C. Dege 1998-09-02 0:00 ` Matthew Heaney 1998-09-05 0:00 ` Ray Gardner 1998-09-05 0:00 ` Matthew Heaney 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Patrick Doyle 1998-09-07 0:00 ` dewarr 1998-09-07 0:00 ` Ell 1998-09-09 0:00 ` Adrian P. Morgan 1998-09-09 0:00 ` Charles Hixson 1998-09-10 0:00 ` mfinney [not found] ` <gio+van+no+ni+8-1609981736190001@dialup47.tlh.talstar.com> 1998-09-17 0:00 ` mfinney 1998-09-07 0:00 ` Ray Gardner 1998-09-07 0:00 ` Ell 1998-09-07 0:00 ` Ell 1998-09-09 0:00 ` Ray Gardner 1998-09-07 0:00 ` dewarr 1998-09-09 0:00 ` Ray Gardner 1998-09-11 0:00 ` Robert I. Eachus 1998-10-09 0:00 ` Matthew Heaney [not found] ` <m31zpq4pim.fsf@mheaney.ni.ne <m3af36wtwh.fsf@mheaney.ni.net> 1998-10-11 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Rick Smith 1998-09-02 0:00 ` Robert I. Eachus 1998-09-02 0:00 ` Patrick Logan 1998-09-03 0:00 ` Robert I. Eachus 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-03 0:00 ` Ell 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Ell 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Joe Gwinn 1998-09-03 0:00 ` Robert Martin 1998-09-04 0:00 ` sureshvv 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Robert Martin 1998-09-04 0:00 ` Ell 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` Matthew Heaney 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Ell 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-11 0:00 ` Robert I. Eachus 1998-09-12 0:00 ` Patrick Logan 1998-09-06 0:00 ` Robert Martin 1998-09-06 0:00 ` Jeffrey C. Dege 1998-09-06 0:00 ` Robert Martin 1998-09-08 0:00 ` adam 1998-09-09 0:00 ` Gerry Quinn [not found] ` <gio+van+no+ni+8-1609980034390001@dialup26.tlh.talstar.com> 1998-09-16 0:00 ` Biju Thomas 1998-09-17 0:00 ` Gerry Quinn 1998-09-17 0:00 ` dewarr 1998-09-18 0:00 ` Gerry Quinn 1998-09-18 0:00 ` Biju Thomas 1998-09-18 0:00 ` Robert C. Martin 1998-09-19 0:00 ` Rick Smith 1998-09-19 0:00 ` Ell 1998-09-19 0:00 ` dewarr 1998-09-21 0:00 ` Richard D Riehle 1998-09-19 0:00 ` dewarr 1998-09-17 0:00 ` dewarr 1998-09-18 0:00 ` Ell 1998-09-03 0:00 ` Malcolm Steel [not found] ` <o1fH1.543$495.1 <gwinn-0309982042490001@d8.dial-4.cmb.ma.ultra.net> 1998-09-04 0:00 ` Samuel Mize 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 1998-09-09 0:00 ` Samuel Mize 1998-09-09 0:00 ` sureshvv 1998-09-10 0:00 ` prochak 1998-09-11 0:00 ` Patrick Doyle 1998-09-17 0:00 ` Matthew Heaney 1998-09-10 0:00 ` Tim Ottinger [not found] ` <01bddccc$98b2dda0$ca3aea9e@tom> 1998-09-10 0:00 ` Tim Ottinger 1998-09-11 0:00 ` Robert I. Eachus 1998-09-12 0:00 ` Loryn Jenkins 1998-09-11 0:00 ` alan walkington 1998-09-12 0:00 ` Loryn Jenkins [not found] ` <6sjnlu$83l$1@hirame.wwa.c <35EE5F67.80D@gecm.com> 1998-09-03 0:00 ` Patrick Doyle 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Phil Goodwin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Patrick Logan 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Patrick Logan 1998-09-03 0:00 ` Ole-Hjalmar Kristensen 1998-09-03 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Biju Thomas 1998-09-03 0:00 ` Phil Goodwin 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Jeffrey C. Dege 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Patrick Logan 1998-09-04 0:00 ` Ell 1998-09-04 0:00 ` Ell 1998-09-05 0:00 ` Loryn Jenkins 1998-09-06 0:00 ` Charles Hixson 1998-09-07 0:00 ` Loryn Jenkins [not found] ` <35F074C9.E10C <35F2E907.594CD023@earthlink.net> 1998-09-07 0:00 ` Patrick Doyle 1998-09-10 0:00 ` Tim Ottinger 1998-09-10 0:00 ` dewarr 1998-09-11 0:00 ` prochak 1998-09-12 0:00 ` Ell 1998-09-12 0:00 ` dewarr 1998-09-12 0:00 ` Charles Hixson 1998-09-13 0:00 ` dewarr 1998-09-14 0:00 ` Ell 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1998-09-02 0:00 ` dennison 1998-09-02 0:00 ` Dan Higdon 1998-09-02 0:00 ` adam 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Mike Spille 1998-09-03 0:00 ` Richard MacDonald 1998-09-03 0:00 ` Gerry Quinn 1998-09-06 0:00 ` Charles Hixson 1998-09-03 0:00 ` mfinney 1998-09-03 0:00 ` Robert Martin [not found] ` <gio+van+no+ni+8-0309982311220001@dialup62.tlh.talstar.com> 1998-09-03 0:00 ` Robert Martin 1998-09-02 0:00 ` john-clonts 1998-09-03 0:00 ` mfinney 1998-09-06 0:00 ` Charles Hixson 1998-09-06 0:00 ` mfinney 1998-09-02 0:00 ` Gene Gajewski 1998-09-09 0:00 ` Jonas M�ls� [not found] ` <35f51e53.48044143@ <6t6l4n$rep@jbm.nada.kth.se> 1998-09-10 0:00 ` Mats Weber 1998-09-17 0:00 ` Matthew Heaney [not found] ` <m3ogt3qgca.fsf@mheaney.ni.n <1dghyt5.oik1lzhxzf2N@n207167116176.inetworld.net> 1998-10-10 0:00 ` Patrick Doyle 1998-10-12 0:00 ` Charles H. Sampson 1998-10-13 0:00 ` Matthew Heaney 1998-10-14 0:00 ` Graham Perkins 1998-10-15 0:00 ` Reimer Behrends 1998-10-15 0:00 ` dewarr [not found] ` <l5HC1.6840$wN.18 <35F238F7.F57D3EC7@earthlink.net> 1998-09-06 0:00 ` Patrick Doyle [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <m31zpxqutn.fsf@mheaney.ni.net> 1998-08-31 0:00 ` Jim Cochrane 1998-09-01 0:00 ` Matthew Heaney 1998-09-01 0:00 ` Matthew Heaney 1998-09-02 0:00 ` Jim Cochrane 1998-09-02 0:00 ` Richard Melvin 1998-09-03 0:00 ` Jim Cochrane 1998-09-03 0:00 ` Robert I. Eachus [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EC1590.D50DB8F6@tisny.com> 1998-09-01 0:00 ` Patrick Doyle [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6shunm$47g$1@hirame.wwa.com> 1998-09-02 0:00 ` David E. Wallace [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <m3zpck79xp.fsf@mheaney.ni.net> 1998-09-02 0:00 ` Patrick Doyle [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6shhg4$llp$1@hirame.wwa.com> 1998-09-02 0:00 ` Jim Cochrane [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <6sjms6$7c4$1@hirame.wwa.com> 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Robert Martin 1998-09-04 0:00 ` Patrick Logan 1998-09-02 0:00 ` Patrick Logan 1998-09-02 0:00 ` Patrick Doyle 1998-09-02 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1998-09-03 0:00 ` Matthew Heaney 1998-09-03 0:00 ` Robert Martin 1998-09-03 0:00 ` Patrick Logan 1998-09-03 0:00 ` mfinney 1998-09-03 0:00 ` Patrick Doyle [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EDC648.76F03F32@draper.com> 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Martin Tom Brown 1998-09-03 0:00 ` Tim McDermott 1998-09-04 0:00 ` Patrick Doyle 1998-09-04 0:00 ` Matthew Heaney 1998-09-04 0:00 ` Patrick Doyle 1998-09-08 0:00 ` Tim McDermott 1998-09-17 0:00 ` Matthew Heaney 1998-09-17 0:00 ` Reimer Behrends 1998-09-18 0:00 ` Robert I. Eachus 1998-09-18 0:00 ` Jeffrey C. Dege [not found] ` <35f51e53.48044143@ <904556531. <m3lno372be.fsf@mheaney.ni.net> 1998-09-03 0:00 ` Patrick Doyle 1998-09-03 0:00 ` Loryn Jenkins 1998-09-03 0:00 ` Patrick Doyle [not found] ` <35f51e53.48044143@ <m3af4mq7f4 <35EC937F.94420C51@ibm.net> 1998-09-07 0:00 ` Michael F Brenner [not found] ` <35f51e53.480<904556531.666222@ <6t42kg$son$1@hirame.wwa.com> 1998-09-08 0:00 ` Patrick Doyle [not found] ` <35f51e53.480 <904556531.66622 <EyyLos.2nx@yc.estec.esa.nl> 1998-09-08 0:00 ` duncan 1998-09-16 0:00 ` Matthew Heaney 1998-09-17 0:00 ` Reimer Behrends 1998-09-17 0:00 ` Ell 1998-09-08 0:00 ` Jim Cochrane 1998-09-09 0:00 ` duncan 1998-09-11 0:00 ` Jim Cochrane 1998-09-11 0:00 ` duncan 1998-09-09 0:00 ` Charles Hixson 1998-09-10 0:00 ` Loryn Jenkins 1998-09-17 0:00 ` Matthew Heaney
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox