Is use of GOSUB bad coding?

Everything else that doesn't fall into one of the other PB categories.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Kale,
look at the 2 examples posted above and show me how you would accomplish the same with easier to follow code.

Paul.
User avatar
Hades
Enthusiast
Enthusiast
Posts: 188
Joined: Tue May 17, 2005 8:39 pm

Post by Hades »

Goto is a shortcut. And it's a natural way of thinking. 'I'm ready here, so I Goto there'

That would be very fine, if software development wouldn't be such a complex thing.
Most of the time you don't write some code and never touch it again. Often you have to edit and reedit it again and again. And even if everything was crystal clear at first, it is very easy to loose track on what's going on in your code after some changes, because there is no clear structure with Goto's.
It's a bit like with EnableExplicit. It seems cumbersome to have to define each Variable before use, but it can really save you from a lot of trouble.

I've stopped using Goto a long time ago, and I won't touch it again just because of it's potential of getting me into trouble.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Hades,
there are times when a short cut is the best method.

If you're embedded deep in loops and if..then..else..endif and case..endcase structures when it becomes clear there is no longer a point to being there, such as if an overflow occurs half way through a complex calculation, then it is easier to follow a shortcut than to follow the tortuous coding needed to exit every structure the "correct" way. It's also a lot more efficient and gives smaller code size.

When you come back to the code a year later, the short cut in those circumstances is clear and makes perfect sense immediately, but the setting of error flags or setting loop variables to the upper limit in order to exit the nested structures is not at all clear and is far more likely to lead to problems.

I'd re-iterate Dare2 from earlier:
IMO, bad code is code that is hard to support.

If it does the job adequately: If the next guy can understand it and enhance it: If you can maintain it 1 year down the track: Then it is good code.

That is all that really matters.
GOTO and GOSUB are not bad code. It's how you use them that matters.

Paul.
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

dioxin wrote:Kale,
look at the 2 examples posted above and show me how you would accomplish the same with easier to follow code.

Paul.
I said real world examples. I've never seen a procedure have that many args in any app code i've seen and that code you've posted doesn't really show anything well..

As for your argument about being 'embedded deep in loops' etc... if your inside nested loops more than 2 or 3 deep your doing something wrong already.

I admit Breaks and Continues are probably Goto's under the hood, but im talking about human readable code here and keeping it simple for them to understand. Gotos mess stuff up, period! If you design an app carefully from the beginning using a few simple rules then you will never need Goto and Gosub and you will probably wonder why you ever used them. bleh! :p
--Kale

Image
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Kale,
you never go more than 3 structures deep? Surely you jest. I assumed you were a programmer! Even the basic Windows message loop for handling a key press is 4 structures deep before you even do anything!

But even really simple code that only needs 2 structures is easier to follow with the GOTO than with other exit stategies. Follow the above example and show me otherwise. How would you do it?


As for how real the examples were. The GOTO example is actually simplified in that post as it demonstrates the point well enough. In real life 6-8 structures deep is not that unusual.

I did exagerate the GOSUB example for effect but it is really based on a program I altered about 4 weeks ago.
There were 12 calls to the GOSUB and the parameters required were:
3 Integers
1 String
1 Integer Arrays with 1000 entries
1 User Defined array with 1000 entries, each entry being 7 strings

How long and how much code would it take to have to push that lot onto the stack for each procedure call? It took literally no time at all using GOSUB and is every bit as easy to follow as any other approach.

Gotos mess stuff up, period!
You're wrong.
You still haven't shown how you would do the 2 examples posted. I accept there is little substance to them because they were intended to show the approach without hiding it in hunderds of lines of code but that should work to your advantage as your code to accomplish the same should be so crystal clear and succinct when not surrounded by the fluff of a real application that you will be able to demonstrate clearly the advantage of avoiding GOTO and GOSUB once and for all.

Paul.
Kale
PureBasic Expert
PureBasic Expert
Posts: 3000
Joined: Fri Apr 25, 2003 6:03 pm
Location: Lincoln, UK
Contact:

Post by Kale »

i give up. Continue using gotos if u want... no-ones stopping u.
--Kale

Image
Pupil
Enthusiast
Enthusiast
Posts: 715
Joined: Fri Apr 25, 2003 3:56 pm

Post by Pupil »

For the record, i agree wholy with you dioxin. But i don't think it's of any use to argument as there's probably no way to convince those who have already their mind set on -how fundamentaly wrong it is to ever use goto- that using goto doesn't automaticly make the code badly written.
SFSxOI
Addict
Addict
Posts: 2970
Joined: Sat Dec 31, 2005 5:24 pm
Location: Where ya would never look.....

Post by SFSxOI »

Well, i'm convinced now that GOTO's and GOSUB's have their place but just not very often. Maybe an occaisional GOTO or GOSUB is not such a bad thing and then again maybe it is, i guess it depends on the circumstances and what your trying to achieve.

Anyway, its all fun until someone puts an eye out then its not so much fun anymore is it :)
Phoenix
Enthusiast
Enthusiast
Posts: 141
Joined: Sun Sep 04, 2005 2:25 am

Post by Phoenix »

Using Gosub is just the same as calling a procedure, and the Return command is the same as EndProcedure. The only difference is that procedures have local variables.
josku_x
Addict
Addict
Posts: 997
Joined: Sat Sep 24, 2005 2:08 pm

Post by josku_x »

which looks prettier?

Code: Select all

Gosub TheLabel

TheLabel:
Debug "LOL"
Return

Code: Select all

Procedure DoIt()
Debug "LOL"
EndProcedure

DoIt()
I like the procedure way more than the gosub way.
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Pupil,
I know I was never going to convince the folk who'd made their minds up about it but the argument has to be put so those who aren't yet stuck in their ways have the information to decide for themselves instead of just accepting one side of the argument as fact.

SFSxOI,
You're convinced they have their place when used wisely? Success!


Pheonix,
I'm not sure they are entirely the same.
GOSUB should have no overhead, it's just a CALL and RET at assembly level.
Procedures (I'm guessing 'cos I don't know) will almost certainly save registers and establish space on the stack when they're called even if they don't always need to. They then have to clear up afterwards before returning so there is probably a lot more overhead than with GOSUB.

josku_x

Code: Select all

DoIt: 
Debug "LOL" 
RETURN

GOSUB DoIt

..looks pretty enough to me and it saves 30% of the typing compared to your PROCEDURE and is both faster and shorter when compiled.


Paul.
josku_x
Addict
Addict
Posts: 997
Joined: Sat Sep 24, 2005 2:08 pm

Post by josku_x »

it's your opinion. I don't care if others say GOSUB is used for bad practicing. I am making a program and after I release it, how do you think you could ever knew that I used gosub???
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

hehe. This whole thing is getting silly. Another hair to split:
dioxin wrote:

Code: Select all

DoIt: 
Debug "LOL" 
RETURN

GOSUB DoIt
Needs the extra typing to "goto" around the "DoIt" code, to a label.

lol. If we split this hair a few more times we'll be splitting the atom (and the Alliance of the Willing will invade us!) :D


Anyhow, here is something that may interest you (quickly contrived, gives procedure's a slight edge, however some better tests may prove otherwise).

Code: Select all

Global aa.l, bb.l, cc.l            ; Not needed for the gosubs

Goto jumpToAvoidTheGosubs          ; Not needed for procs or if gosubs are last (after End)

abcG:
  aa = bb + cc
Return

xyzG:
  xx = yy + zz
Return

Procedure abcP()
 aa = bb + cc
EndProcedure

Procedure xyzP(yy.l, zz.l)
 ProcedureReturn yy + zz
EndProcedure

jumpToAvoidTheGosubs:

someLargeNumber = 1      ; must be very large!

w.s = "And the results (tah-dah)" + Chr(10) + Chr(10)

t = ElapsedMilliseconds()
For i=1 To someLargeNumber
  bb = 1
  cc = 1
  abcP()
Next
t = ElapsedMilliseconds() - t
w+"abcP = " + Str(t) + " (" + Str(aa) + ")" + Chr(10)

t = ElapsedMilliseconds()
For i=1 To someLargeNumber
  bb = 1
  cc = 1
  Gosub abcG
Next
t = ElapsedMilliseconds() - t
w+"abcG = " + Str(t) + " (" + Str(aa) + ")" + Chr(10)

t = ElapsedMilliseconds()
For i=1 To someLargeNumber
  xx = xyzP(2,3)
Next
t = ElapsedMilliseconds() - t
w+"xyzP = " + Str(t) + " (" + Str(xx) + ")" + Chr(10)

t = ElapsedMilliseconds()
For i=1 To someLargeNumber
  yy = 2
  zz = 3
  Gosub xyzG
Next
t = ElapsedMilliseconds() - t
w+"xyzG = " + Str(t) + " (" + Str(xx) + ")" + Chr(10)

MessageRequester("!",w,0)

End
@}--`--,-- A rose by any other name ..
dioxin
User
User
Posts: 97
Joined: Thu May 11, 2006 9:53 pm

Post by dioxin »

Dare2,
well of course you'd put the GOSUBs beyond the END so as not to need the jump. I only did it the way I did so it was directly comparable to the "pretty" Procedure version and would hopefully take on some of the pretty characteristics of that version, at least in the eye of its creator.

The "less typing" comment wasn't meant to be taken too seriously, after all, if you call the GOSUB many times it takes 3 characters more typing each time than the PROCEDURE version so in real life it'll take more typing.. but don't tell the others or they'll use it to argue against GOSUBs!


As for the timing of GOSUB vs. PROCEDURE, I'm only able to speculate as I don't actually own PureBASIC so I can't compile or experiment with it but, as a guess, I'd say that the routines are both very short and in very tight loops so will be prone to the well known branch target alignment problem. If the code was moved around a bit, for example by swapping the position of the PROCEDURE and GOTO calling routines, or by adding a small amount of code at the start of the program, then it may give different results.

Sounds like atom spiltting again, I know, but you can gain or lose 20% in speed by altering the alignment of critical parts of your code.

Paul.
Dare2
Moderator
Moderator
Posts: 3321
Joined: Sat Dec 27, 2003 3:55 am
Location: Great Southern Land

Post by Dare2 »

dioxin wrote:.. but don't tell the others or they'll use it to argue against GOSUBs!
:D
@}--`--,-- A rose by any other name ..
Post Reply