GOTO statement and return results way

R

Roger Tranchez

Hello,

I have a question about the infamous GOTO statement and the way to return a
result from a sub:


I have a sub that has to make some calls to external COM methods, and
because these methods can fail I have to check them to be running ok, like
this:

sub method(byval param1 as integer, ...., BYREF result as String)

dim ...
..
..
result=callCOM1(params)
if result=-1 then 'bad result
result="callCOM1 failed, dude!"
GOTO ENDPOINT
..
..
result=callCOM2(params)
if result=-1 then 'bad result
result="callCOM2 failed, dude!"
GOTO ENDPOINT
..
..


ENDPOINT:

'make some dispose, and additional tasks

end sub

Then, the CALLER function will check the RESULT var and will proceed as
required.
I choosed a sub instead of a function as I think that a function have to
return other information than "function executed ok or not", as datasets,
application objects etc.

The second doubt is the GOTO: you know, it is a bad wound in code, but I
use it as a fast way to exit the sub.

How would you change all this to be more structured and aesthetic ? maybe
creating a sub where all the dispose is done ? --> then I'd have to pass all
the vars to be disposed or make them public/friend 8-( ...

Thanks in advance,

Roger Tranchez
MCTS
..NET 2005 and DB developer
 
C

Cor Ligthert [MVP]

Roger,

What you want is from before 1970.

Just Create an, what you call "Endpoint function", call that end then use
"Return" that has the same effect.

Cor
 
A

AMercer

The second doubt is the GOTO: you know, it is a bad wound in code, but I
use it as a fast way to exit the sub.
How would you change all this to be more structured and aesthetic ?

When I have some functions to perform in sequence and I want to quit on the
first failure, I use one of two constructs - 'nested if' or 'do once'. I
prefer 'nested if' when I have few functions, I prefer 'do once' when I have
many.

Assuming the functions are x1, x2, and x3, 'nested if' is:

x1
If Success Then
x2
If Success Then
x3
If Success Then
' processing here for all success
End If
End If
End If

'Do Once':

Do
x1
If Fail Then Exit Do
x2
If Fail Then Exit Do
x3
If Fail Then Exit Do
' processing here for all success
Loop Until True

These constructs compile to code that is similar to yours with 'goto
endpoint', but the source code avoids goto's and label's. I prefer them over
goto's because I think they are easier to understand for a new person or for
you when you come back to the code after not looking at it for a few months.
 
R

Roger Tranchez

Hello,

Thanks for your answer.

I kew that about nested ifs, but I don't like it because it adds complexity
to code.

I found the second method more elegant: do.. loop until true, I LIKE it.
But, risking to be too fussy, this "loop until true" trick seems just a bit
round-about 8-D

What do you think about the first question ? : to return if a procedure has
done well its work you 'd use a FUNCTION that returns the result code for
the operation, or a sub that, by means of a byref parameter returns the
result code ?

Wich is the paradigm for types of result codes: Strings, integers, custom
objects ?

Thanks again,


Roger Tranchez
MCTS
..NET 2005 and DB developer
 
A

AMercer

What do you think about the first question ? : to return if a procedure has
done well its work you 'd use a FUNCTION that returns the result code for
the operation, or a sub that, by means of a byref parameter returns the
result code ?

I don't have a problem with functions that return status indicators, and I
don't have a problem with subs/functions that have byref parameters for
returning results. Fxcop guides against byref parameters, and I seem to
recall reading somewhere that Fxcop or MS guides against returning status
codes (I think an MS programming guideline, but memory fails). If the
setting is simple, I don't accept such guidance. If the setting is complex
(many functions, many function outputs, etc), then I would create a class
that encapsulates all the complexity.
 
S

Stephany Young

I think the point that has been missed is that you need to do some other
processing between the target of the 'goto' and the actual end of the 'sub'.

A mechanism that has been designed exactly for this purpose is the
Try...Finally...End Try construct.

In your case it would become something like:

sub method(byval param1 as integer, ...., BYREF result as String)

Try
 
S

SurturZ

I think there is nothing wrong with your code. Avoiding GOTO at all costs is
considered harmful :) Why otherwise competent programmers go to such lengths
to avoid GOTO is beyond me.

At the risk of starting a flame war, I would highly recommend AGAINST the
two suggestions by AMercer.

1) Nested IF
This one is okay provided you don't have too many conditions. Once you get
more than about five IFs though, the indenting makes the code harder, not
easier to read. (five IFs = 20 spaces indent = 25% whitespace on a 80 column
screen)

2) Do...Loop Until True
This is an abomination and any programmer that uses such a construct is
avoiding GOTO for avoidance' sake. THERE IS NO LOOP, so the use of Do...Loop
in this way is a misuse of the command. Furthermore the use of Exit Do in
this construct is as an unconditional jump. There is already an unconditional
jump command, and that command is GOTO. If indenting is so important to you,
turn off pretty code and indent it yourself.

I'm not saying we should all start using GOTO everywhere, but it certainly
should be used when:
* You have a transaction consisting of multiple steps
* If any step fails, the transaction as a whole fails, and you do not need
to perform the subsequent steps
* Whether or not the transaction fails, some cleanup operations are required

See also: http://slashdot.org/~SurturZ/journal/145833

The original "considered harmful" article by Dijkstra published almost 40
years ago! It is barely relevant today, if it was ever relevant. Back then,
computer memory was measured in KILObytes and the memory (stack) usage
implications of GOSUB/SUB were not inconsiderable; so GOTO might have been
required for those reasons (rewriting code to save a SINGLE BYTE of memory
was commonplace back then). Code is sometimes hard to read by necessity.
 
S

SurturZ

"Exit Try" instead of "Return" might be a bit easier to read, and allows you
to have code after the Try block (eg. if the Try block is itself in an IF
block or somesuch).
 
S

Stephany Young

Now that's just getting picky for the sake of getting picky.

As you can clearly see, there is NO code after the Try...Finally...End Try
block so your e. is completely irrelevant.

In the context, changing the Return ... to Exit Try would add unecessary
complexity, because one would have to add Return ... after the End Try
which, in turn, would necessitate moving the declaration of _result to
before the Try.

As you can see, that is totally unecessary in the context of the example.
 
S

SurturZ

Now that's just getting picky for the sake of getting picky.

You had different expectations in a computer programmers' forum? :)
As you can clearly see, there is NO code after the Try...Finally...End Try
block so your e. is completely irrelevant.

You are right, it is a style preference. I feel the Exit Try makes it more
obvious that the Finally block gets executed. But I suppose it is not too
much to ask that programmers know that a Finally block always gets executed.
Your code is certainly more compact and is a correct solution.
 

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

Top