when GOTO makes sense.

  • Thread starter Debashish Chakravarty
  • Start date
D

Dan Pop

In said:
falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();

That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

Dan
 
E

Ed Morton

Dan said:
That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

I agree it's not a mistake that one person will make many times, but
it's a mistake that many people will make once, so it is still desirable
to use braces. Typing those couple of extra characters is no big deal
and is well worth the extra second or so of typing if it can avoid a
future bug being introduced. It also removes much of the need for using
"do { ... } while(0)" in compound-statement macros (though, to be
honest, I do that too since my macros are often used in other peoples code).

Ed.
 
A

Alan Balmer

That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

Dan

The problem is that for real software products, maintained over a
number of years, it's not "one", but many.
 
D

Dan Pop

In said:
The problem is that for real software products, maintained over a
number of years, it's not "one", but many.

People who maintain software don't actually test the changes they make?

If I change a bit of code, it is because I want to alter its behaviour.
The next thing after doing it is testing it, to see if I got it right.
And if I didn't get it right, I find my bug(s) and fix the code.

Do I have some weird ideas about what software maintenance means?

Dan
 
E

Ed Morton

On 12/4/2003 12:42 PM, Dan Pop wrote:
People who maintain software don't actually test the changes they make?

If I change a bit of code, it is because I want to alter its behaviour.
The next thing after doing it is testing it, to see if I got it right.
And if I didn't get it right, I find my bug(s) and fix the code.

Do I have some weird ideas about what software maintenance means?

Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and retesting.
b) During developer-testing, every developer catches every bug they introduced.
c) All software can be tested thoroughly in a cheap development environment
(e.g. off the potentially expensive production hardware).

Ed.
 
C

Christian Bau

Ed Morton said:
There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();

Are you teaching courses "C for talentless beginners" ?

I cannot remember seeing that mistake being made in twenty years.
 
E

Ed Morton

Christian said:
Are you teaching courses "C for talentless beginners" ?

No, I teach behavioral modeling, but I do inspect a lot of code written
by people with less experience.
I cannot remember seeing that mistake being made in twenty years.

Then you've been incredibly fortunate or don't get to inspect a lot of
code written by relative newcomers or have missed many mistakes.

Ed.
 
J

James Dow Allen

First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.
No. It was the loop termination condition that was the hardest to
understand. I don't mean I can't read the C, I just don't know what the
abstraction is for the C (i.e. what it "means").

The program does have a few comments, including one immediately
before the for statement you snipped:
/* Loop to play tricks forward until the outcome is conclusive */
for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;
tnum++, P++, success = IS_CONT(pwin)) {

I assumed an understanding of whist and game search -- the loop
terminates when it is known either that contract will succeed or
won't succeed (and "success" will tell you which.)
I was wrong, it doesn't hang. It does just take a few minutes.

To change the subject, I was pretty sure the program would
run the 2nd input if it could run the 1st. Why? *Because it doesn't
rely on anything.* Some programs have code like
foogle_gark(CanonPrinter, DVI_Level17, REV14_3);
/* remember to ask Tony if we need to change this for
* Rev 14.4 (when line speed exceeds BAUDLIMIT_39) */
My program depended only on printf(), etc. which haven't changed
since the Pleistocene. And even the cheapest cell phone today
has enough memory to run it.
Well, if you decomposed what you have into a few small functions (with
their own local variables ...)

Studying the program I believe you'll find that to be undoable.
You'll either need lots of global variables, or unwieldy state-
passing in both directions.
Until then, your words

You can dismiss my comments if you like, but I wasn't pedantic about
anything. I didn't say anything like "this code uses goto and therefore
is bad" I said "This code is hard to read, and here's some examples of why".

I apologize. My point was very badly phrased and, anyway, directed
more at another poster who over-generalized. I stand by my essential
point: My 200-line program is harder to read than a 500-line program,
but many programmers would construct a 2000-line solution if they could
do it all. Let's wait till the alternative is on display before
declaring it more readable.

James
 
D

Dan Pop

On 12/4/2003 12:42 PM, Dan Pop wrote:


Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and retesting.
b) During developer-testing, every developer catches every bug they introduced.
c) All software can be tested thoroughly in a cheap development environment
(e.g. off the potentially expensive production hardware).

You're ignoring the punctual nature of the issue. There is no need to
perform a full retesting of the application, only the correctness of the
changes made needs to be tested, and this is, usually, far easier.

Anyone who changes the code and doesn't test his changes should be
kicked out of this profession.

Dan
 
E

Ed Morton

Dan said:
You're ignoring the punctual nature of the issue.

Not at all.

There is no need to
perform a full retesting of the application, only the correctness of the
changes made needs to be tested, and this is, usually, far easier.

Of course rerunning one or 2 tests is easier/cheaper than retesting the
whole code. No-one suggested otherwise.
Anyone who changes the code and doesn't test his changes should be
kicked out of this profession.

s/should/will but that also has nothing whatsoever to do with anything I
said.

Ed.
 
C

CBFalconer

Dan said:
.... snip ...

You're ignoring the punctual nature of the issue. There is no
need to perform a full retesting of the application, only the
correctness of the changes made needs to be tested, and this is,
usually, far easier.

Anyone who changes the code and doesn't test his changes should
be kicked out of this profession.

Such changes have been known to affect seemingly totally unrelated
functions. Which is why having a fully automated regression test
suite available is invaluable. Such a test suite should be
generated with the original application, but often is ignored.
 
D

Dan Pop

In said:
Such changes have been known to affect seemingly totally unrelated
functions.

It doesn't matter. You simply test their impact on the program behaviour.
If they break something, it doesn't matter where that something is: you
track it and fix it.
Which is why having a fully automated regression test
suite available is invaluable. Such a test suite should be
generated with the original application, but often is ignored.

Especially when generating it is 10 times or more expensive than
developing the application. Which is often the case with complex
applications (e.g. compilers), so you use incomplete testing procedures.

However, when you make a punctual change, it is usually possible to
completely test its effects.

Dan
 
E

Ed Morton

James said:
First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.

Not at all. Likewise, I appologise if I was rude or sounded offended.

I've added an "OT" label to the subject as I'm about to talk about
algorithms rather than ANSI C:

I took another look at the code and, though I don't get the details, the
comments sound like you're (very roughly) attempting to deal the cards
until some predefined outcome, and backtracking when you hit dead-ends.
If so, did you consider using, say, bit-state-hashing with a depth-first
(recursive-descent) algorithm, e.g. something like this pseudo-code:

play() {
deal(); /* determine possible next states from the
* current state, e.g. card hand combinations.
*/
for (state in possibleStates) {
if (state == the_desired_result) {
return;
} else {
idx = hash(state);
if (hashTbl[idx] == 0) {
/* This is a new configuration
* so continue
*/
hashTbl[idx] = 1;
play();
}
/* else, we've seen this configuration
* before so move on or backtrack
*/
}
}
}

main() {
bool hashTbl[size] = { 0 };
play();
printState(state);
}

Regards,

Ed.
 
L

Les Cargill

James said:
First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.


The program does have a few comments, including one immediately
before the for statement you snipped:

I assumed an understanding of whist and game search -- the loop
terminates when it is known either that contract will succeed or
won't succeed (and "success" will tell you which.)


To change the subject, I was pretty sure the program would
run the 2nd input if it could run the 1st. Why? *Because it doesn't
rely on anything.* Some programs have code like
foogle_gark(CanonPrinter, DVI_Level17, REV14_3);
/* remember to ask Tony if we need to change this for
* Rev 14.4 (when line speed exceeds BAUDLIMIT_39) */
My program depended only on printf(), etc. which haven't changed
since the Pleistocene. And even the cheapest cell phone today
has enough memory to run it.


Studying the program I believe you'll find that to be undoable.
You'll either need lots of global variables, or unwieldy state-
passing in both directions.


I apologize. My point was very badly phrased and, anyway, directed
more at another poster who over-generalized. I stand by my essential
point: My 200-line program is harder to read than a 500-line program,

All other things being equal, this is almost never the case. Simply
by fact of the program having more stuff in it, it will be somewhat
harder to read. This a variaiton of Strunk and White's "Omit needless
words".

But this is stated in the absence of a lot of other information
that would be necessary to really evaluate a comparison between
the two. A factor of 2.5 is very significant.
 
C

CBFalconer

James said:
First: I did appreciate your words and your taking the time to
rerun the program. Sorry if I sounded irritable.
.... snip ...

I too tried it out, and all seems correct after some repairs, such
as the appropriate #includes, and replacing 'index' with 'strchr'.

It is wanting in input checking. The use of scanf is fatal. I
especially discovered this when a typo in one input hand caused a
12 card hand, and the result announced success after 12 tricks!
My first attempt to feed it a hand used something like "S AKJ543"
etc. and resulted in segfaults. This is where functional
separation greatly eases improvement.
 
C

CBFalconer

Dan said:
Especially when generating it is 10 times or more expensive
than developing the application. Which is often the case with
complex applications (e.g. compilers), so you use incomplete
testing procedures.

By the very nature of the beast tests are never complete. If they
were we could prove the absence of bugs.

IMO this is an outstandingly poor example of something hard to
regression test. A compiler has to deal with known syntax,
rejecting much, and the code snippets are relatively easy to
create. I know of no important compilers without such a suite.

However I have found no /reasonable/ way to regression test my
nmalloc package, since the pointers it returns depend on the state
of the rest of the machine.
 
J

James Dow Allen

Les Cargill said:
All other things being equal, this is almost never the case. Simply
by fact of the program having more stuff in it, it will be somewhat
harder to read. This a variaiton of Strunk and White's "Omit needless
words".

Although your comment appears contrary to mine, I assume you
realize you are strongly taking my side in this debate.

No one has deigned to display any alternative program, but
if any of the posters have actually spent any effort towards that
goal I'm sure they will agree the "structured" alternative must have
many more keystrokes in it. ... And if posters claim otherwise,
but find it too difficult to modify this 200-liner, ... well
I'll avoid the term "idle pedantry" but just say that either their
love or skill for programming isn't enough.

* * * *

Addressing some other comments, I thought my discussion made it
*very clear* that the example program was deliberately streamlined
to demonstrate algorithmic simplicity and a unique control flow,
and was *not* intended as an "industrial strength" user-friendly
application. Hence, comments like "avoid scanf()" are at cross purpose.

James
 
J

James Dow Allen

Ed Morton said:
I took another look at the code and, though I don't get the details, the
comments sound like you're (very roughly) attempting to deal the cards
until some predefined outcome, and backtracking when you hit dead-ends.
If so, did you consider using, say, bit-state-hashing with a depth-first
(recursive-descent) algorithm, e.g. something like this pseudo-code:...

The program is one of several example programs at that site.
Unfortunately the webpage doesn't have an appropriate Back button or
you might have stumbled on further discussion and examples.
(I'll add such a Back link, but it didn't seem fully necessary:
you can rubout the last part of the URL and get the Index page for
that directory. The double-dummy program is introduced in Lesson 9.)

I've written other game-search programs, usually similar to your
description, and at least three other example programs at the website
fit that category, none similar to the Whist program.

FWIW, (drumroll), it was my program that first solved the game of
Connect-Four. (That program didn't happen to have "goto", BTW. :)

BTW, typical games progress
Black, White, Black, White, Black, White, ...
but Whist progresses
N, E, S, W, determine_who_leads, S, W, N, E, determine_who_leads, etc.
This complication is a major reason that more traditional control
flow would become more complicated than the Favorite Goto(tm) does.

James
 
B

Barbrawl McBribe

Debashish Chakravarty said:
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.

Breaking out of complex loops?? That's the O'Reilly example at any rate.
 
D

Dan Pop

In said:
By the very nature of the beast tests are never complete. If they
were we could prove the absence of bugs.

Never is too strong. If the full set of inputs is reasonably small,
the brute force approach is doable. In some other cases, it is possible
to identify a problematic subset of inputs that need testing (if they
are correctly handled, it is possible to prove that anything else will
be correctly handled). But, often enough, NOTHING can replace the
testing (usually involuntarily) performed by the real world users of your
application.
IMO this is an outstandingly poor example of something hard to
regression test. A compiler has to deal with known syntax,
rejecting much, and the code snippets are relatively easy to
create. I know of no important compilers without such a suite.

You forgot to engage your brain, again. I know of no important
compilers without such a suite, either, yet I know of no important
compiler which is bug free. Which makes it an outstandingly *good*
example of something hard to test.
However I have found no /reasonable/ way to regression test my
nmalloc package, since the pointers it returns depend on the state
of the rest of the machine.

If you have problems testing a malloc package, it's most likely due to its
extremely bad design.

Dan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,756
Messages
2,569,534
Members
45,007
Latest member
OrderFitnessKetoCapsules

Latest Threads

Top