a bad practice?

Blitz3D Forums/Blitz3D Programming/a bad practice?

Yue(Posted 2010) [#1]
Referred to as a bad programming practice to use functions such as GOTO or GOSUB, perhaps not part of the language and are good for something, my concern is that without GOTO I see no other possible way to do little or nothing I've done .

Greetings.


jfk EO-11110(Posted 2010) [#2]
You can write a program only with GOTO, PEEK and POKE. Then you can translate it almost command for command directly to Assembler.

Just don't expect to get a Job as a programmer when you release Surcecodes with GOTO.

Personally I often use it to skip parts of the code (a kind of block remark). An other situation where GOTO makes sense is a multiple nested FOR loop that you want to exit. Using EXIT would exit only from one For loop, but with Goto you can exit to a label right after the whole nested structure.

Using too much GOTO will result in socalled "Spaghetti-Code", that is hard to analyze and to edit and to debug. GOSUB is obsolete IMHO because you can use a FUNCTION instead and that's even good practice.

It's also good practice to declare all local variables in a Function explicitely as LOCALs, for in case of globals with the same name.


Shambler(Posted 2010) [#3]
Give us an example of where you have used goto or gosub and we can show you a better function derived solution to your code.


Yue(Posted 2010) [#4]
Shambler Hi, well I'm glad your disposal to help me understand better.

What I've done so far is not much, is simply a menu of a game where you have options to change the screen resolution, the quality of the shadows and into a level and return to the main menu, you see this I have made with the Goto command.

;========================================================
; Proyecto    : Beta
; Nombre File : Menu_Principal.bb
; Programador : Yue Rexie
; Empresa     : Iris3D -Games Studios- ©
; URL         : http://www.iris3d.tk
; ©           : 2007-2011
;========================================================
; OBJETIVO    : Menu Principal
;========================================================
.Menu_Inicial

;-----------------------------
; Fisica Implementada.
;-----------------------------
pxCreateWorld(0,"t>4a3624l]64dm60]m28d\48mm70UT28")
pxSetGravity (0,-30,0)




;Menu = 1
MoveMouse GraphicsHeight()/2+100,GraphicsHeight()/2
CambiandoR = False 




;-----------------------------
; Includes Especiales -S-
;-----------------------------
Include "Includes3\ShadowsSimple.bb"
.Cambiando_Sombra

CreateShadow Calidad
;ShadowRange 1

Global Textura0  = ShadowTexture()



;-----------------------------
; Includes Recursos2
;-----------------------------

Include "Includes\Recursos2.bb"

;-----------------------------
; Escena del Menu.
;-----------------------------

Crear_Menu()

CreateShadowCaster Jeep,0,1
CreateShadowCaster Llanta0,0,1
CreateShadowCaster Llanta1,0,1
CreateShadowCaster Llanta2,0,1
CreateShadowCaster Llanta3,0,1

EntityTexture Casa,Textura0,0,1
;-----------------------------
; Emisor Particulas.
;-----------------------------

Type Particle_Star
Field particle
Field sprite
End Type

Global EmisorP =  pxParticleCreateEmitter()
pxParticleEmitSetRadius(EmisorP, .2)
pxParticleEmitSetStartSpeed( EmisorP, 0,.2)
pxParticleEmitSetTDAcceleration(EmisorP, -1, 2, 0)
pxParticleEmitSetRandRadius( EmisorP, .1)
pxParticleEmitSetScaleFactor(EmisorP, 1, 0.1)

pxParticleEmitSetPosition (EmisorP,-1.7,4.55,6.75)













Repeat 
	
	n=1-n
	If n=1 CreateParticleStar()
	
	
	;PointEntity Camara,Jeep

	;CamaraFalsa()
	
	
	
		If KeyDown(200) MoveEntity  Camara,0,0,-.2
	
	
	
	If Calidad <> -1 UpdateShadows Camara,1.0
		If Calidad = -1 FreeShadows()
		
		
		AntiAlias AAlias 
		UpdateParticleStar()
		pxRenderPhysic(60,0)
		
		
		
		pxParticleUpdateEmitter(EmisorP)
		
		RenderWorld 1.0
	; Funciones
		;DebugShadow
		Menu()
		
	
		
		Text_(0,0,FPS()+ "Memoria Usada : " +StarAmount + " " + Menu,100,100,0)
	Flip Turbo
	
	
	
	
		
	
	
	
	
	
	
	If CambiandoR = True 
		StarAmount = 0
		Delete Each Particle_Star
		Goto Cambio_Resolucion
	End If 
	
	
	If CambiandoS = True  
		Eliminar_Menu()
		FreeShadows()
		StarAmount = 0
		Delete Each Particle_Star
		ClearWorld True,True,False 
		
		
		
		CambiandoS = False 
		Goto Cambiando_Sombra
	End If 
	
	
	If Nivel = 1 
		Eliminar_Menu()
		FreeShadows()
		Delete Each Particle_Star
		StarAmount = 0
		ClearWorld True,True,False
		
		Goto Cargando
		
	End If 
	
	
Forever


.Cargando 




;-----------------------------
; Cargando Nivel 1
;-----------------------------
Include "Includes\Recursos3.bb"
Camara = CreateCamera()

Repeat 
	Local Frames#
	Local Iniciando_Nivel#
	Frames = Frames + .5
	If Frames => 13 
		Iniciando_Nivel = Iniciando_Nivel +.5
		Frames = 0
		
		If Iniciando_Nivel > .5
			Iniciando_Nivel = 0
			Goto Primer_Nivel
		End If 
		
	End If 
	
	
	RenderWorld
		
	StartDraw
;	If Frames > 0 And Frames < 4
;		SetColor 255,0,0
;	ElseIf Frames >4 And Frames < 8
;		SetColor 255,255,0
;	ElseIf Frames > 8 And Frames < 13
;		SetColor 0,255,0
;	End If 
	DrawImageEx (Cargando,GraphicsWidth()/2,GraphicsHeight()/2,Frames)
		
	EndDraw
	
	Text 0,0, "Memoria Disponeble :" + AvailVidMem()
	Flip Turbo
		
	Forever
	
	.Primer_Nivel
	ClearWorld True,True,False
	
	Include "Includes\Nivel_1.bb"
	
	
	




For example to change the quality of the shadow use this.

	If CambiandoS = True  
		Eliminar_Menu()
		FreeShadows()
		StarAmount = 0
		Delete Each Particle_Star
		ClearWorld True,True,False 
		
		
		
		CambiandoS = False 
		Goto Cambiando_Sombra
	End If 



CambiandoS is a variable that indicates that a new quality value was assigned to the quality of the shade, so I use the goto to remove the entire scene and reconstruct the new quality of the shadow.


D4NM4N(Posted 2010) [#5]
Tobe honest i am not even sure why b3d has goto and gosub. They are largely useless and should not ever be used.
There should be no situation where one is needed (except some very rare circumstances), where a well structured switch (select), if-tree or loop break can do the job much better.
Basically if you need to use goto's the code is not structured properly.

ps you should never use repeat --- forever s either ALWAYS condition them.

Last edited 2010


Yasha(Posted 2010) [#6]
you should never use repeat --- forever s either ALWAYS condition them

Not necessarily: http://en.wikipedia.org/wiki/Control_flow#Loop_with_test_in_the_middle

That is to say, yes there is a condition check (implemented via "If cond Then Exit") but it's not on the "Until" clause; in that case, having an "Until" there anyway would make such code less clear.

I would recommend doing some reading up on Structured Programming, and possibly follow that up with a bit about procedural programming, for the adventurous. How to structure algorithms and break them down into component procedures can be hard to grasp initially, if it doesn't seem obvious that these things are actually clearer and simpler than Goto and labels, but it's really worth taking the time and effort to find out why they are.

Unfortunately a lot of this isn't stuff that can really be taught with a small number of examples of changes to your own work - you need to do a lot of reading and understand the reasoning behind the design decisions, then a get lot of practice creating such things yourself.


Yue(Posted 2010) [#7]
Not to say about it, the only way to see if you do not use the "Goto" command in the case of shadows is to triple the code written to establish three types of shadow quality: low, medium and high, ie if I have 100 lines of code to do it without the goto command, would have to do 300 lines of code, this is just one example, since there is no other way to do it.


H&K(Posted 2010) [#8]
First can you imagine that goto doesnt exist and that all you have is gosub?

This is important, with goto you have sent the program flow somewhere else, and cannot simply get it back to where you where, but gosub lets (makes) you bring it back.

so
Goto cargando
...
...
.cargando
...
...
Stuff after cargando

becomes
Gosub cargando

Stuff after cargando
...
.cargando
...
return

Now in the goto example to read your program I need to find and go to cargando and continue reading from there. In the gosub example, if I can assume cargando works, then I can just continue reading the program knowing that the next command is the one that will be after cargando.

Gosub is more like reading a book, you get to something with an appendix note (1), and when you have read the appendix, you go straight back to where you where.
Goto is not as intuitive when reading (2)
(3) And that means this bit makes nonsense, unless you actually went and read the appendix.
Now as most programmers will tell you, MORE time is spent re-reading a program than writing it, so dont use goto cos it makes it a lot harder to read.

Select Case.

if a =1
    gosub/goto One
else if a =2
    gosub/goto two
etc


Select A
		Case 1
		Print "Mission 1."
		
		Case 2
		Print "Mission 2."

		Case 3
		Print "Mission 3."		
	End Select

http://www.blitzbasic.com/b3ddocs/command.php?name=Select&ref=2d_a-z

Gosubprogram, Go-subroutine = Function (ish)
Gosub label
...
...
.label
return

DoFunction ()
...
...
Function DoFunction ()
End Function
http://www.blitzbasic.com/b3ddocs/command.php?name=Function&ref=2d_a-z

(NB You cannot just DO this thou, because inside the Function only certain of your variables exist, but you need to learn which exist, and why)



To be Turing complete, it is enough to have conditional branching (an "if" and "goto" statement), this basically means that if and goto in a language is enough to ensure you can do everything that any other language can do, you you can nearly always solve your problem with these. AND in some ways this would make you a better programmer than most. In most cases you would just endup modelling the higher level commands, which is a waste of effort.
(And no one will read your listings)


(1) A note at the end of the chapter or book
(2) When writing it is.
Because you just continue to write where ever you are, but as you can see it has made reading this a lot harder than it needs to be. And the only way to get back to where you where is to have another appendix note lining back into the text (3)


Beaker(Posted 2010) [#9]
I never ever use goto/gosub, and haven't done for over 10 years (at least). There is always a way to avoid them, and once you've done so for a while you never even think of using them.


_Skully(Posted 2010) [#10]
Me either... YUK!

They are left-overs from when languages were birthed and goto is pretty much completely responsible for what is termed "spagetti code." I like to think that Methods and Functions and more advanced controls such as For, While, Repeat, Select have completely obscured the need for goto/gosub.

Why is Gosub no good? it forces all your variables to be global in scope because you cant pass a variable to a gosub

Why is Goto no good? because it obscures program flow (lack of structure).. which is not readily apparent in small programs but becomes a nightmare in larger ones.


Yue(Posted 2010) [#11]
Well thank you for your help with this, I'm not a programmer, just pretend to be and I'm learning. It is clear that a solution to the problem look like option to use "Goto" and I suppose that the practice will prove me right, and that the only way to learn is to deal with thousands and thousands of lines of code and learn to solve problems the best way.


jfk EO-11110(Posted 2010) [#12]
Let me add a further comment here. While GOTO is a NOGO in a wide area of professional Programming, we should not forget that we're BASIC Programmers. Why are we BASIC programmers? Because testing, editing and runnig code is much faster than any other System. Hit F5 and you know if it'S gonna work almost immediately, where all the other language compilers that I ever tried in the past ()eg. vc++, will make a big deal out of the slightes hello world program, and if you once got everything right in your code, includig access paths to includes, linker etc. it still takes seconds to compile a 1 liner.

If you for exampe try to design something in 2D, you can do that quickly in BASIC.

So I think GOTO can be useful, especially for blockmarks. When you want to try two variants of some 2D commands, GOTO is the quick solution. You could also put them in functions, but it's already more work and you got to declare Globals and locals to make it work. These are simple things that you want to try in seconds, or skip it using GOTO, compare and finally delete all but the stuff you like.

I do agree, GOTO should not be part of your Program Flow Structure.

Nevertheless, you may use it here:
for x=0 to 100
 for y=0 to 100
  for z=0 to 100
   ...
   if b=1 then goto .myexit1
  next
 next
next
.myexit1


But you can also do this the "legal" way:

for x=0 to 100
 for y=0 to 100
  for z=0 to 100
   ...
   if b=1 then exit
  next
  if b=1 then exit
 next
 if b=1 then exit
next


where in my opinion version B is not only longer and slower, but also uglier. Probably RETURN could be used to do something like that, but then you need to put the for loop into a function, which would only complicate the structure.

So my conclusion is: there may be uses for GOTO, but they are really limited.


Yasha(Posted 2010) [#13]
Heh, JFK, I think you need to try some more languages if you're comparing Blitz3D to VC++... there's rather a lot in between (and to either side - yes there are faster prototyping languages even than Blitz).

Actually I'd go so far as to extend the point of the above post one step further: Goto is close to being an ASM instruction, because the one place where its use is fully justified is when (as in the above example) the language doesn't have the feature you actually want (and you want to structure the code as if it did, of course).

One nitpicky thing though as well from the above:

you got to declare Globals and locals to make it work


Using Globals is also generally considered bad practice, for the same reasons as using Goto: complicates control flow and hides actions off the track of execution.

That said, again its use in Blitz is generally excusable as Blitz3D doesn't provide any OO or functional features, so again, there are a rather limited number of ways to achieve some things. But Globals are massively overused by beginners (I blame the examples and tutorials). A beginner shouldn't need to use Globals for simple test programs at all.


Panno(Posted 2010) [#14]
i disagree with the nogo statement for the use of goto , its a simple Asm instruction jo,jno,jns,jbe,jl,jne and its fast if the cpu not reload the instruction cache ,or reload the pipeline .
if you ever disassembled a x86 file you see much jumps in the source ,
also esp.x86 cpu are desingned for .


jfk EO-11110(Posted 2010) [#15]
Hey, don't take my globals away :) I love them. Seriously, when there is a variable that several functions need to access, I would have to put it on the stack again and again, as function parameters. For me a global is some kind of passive parallel thread. I think sometimes efficiency must be paid with additional, complicating dimensions.


jfk EO-11110(Posted 2010) [#16]
Hi Panno. But you have to agree: GOTO may be used like JMP, but normaly you would use a conditional jump in ASM, like JLE or so. But in Basic you'd have to IF and then GOTO, resulting in many assembler commands, including register loading for every single comparation.

But I must confess, I was writing ASM programs in basic, using the peek poke goto equivalents. This way I was able to write complex programs in some sort of "interpreted ASM" without a single comuter crash, and I think you would agree that ASM coding normally is linked with tons of heavy crashes, such as complete freeze etc. Hey, why did none write an ASM Interpreter yet? At least I never heard of anything like that.


Panno(Posted 2010) [#17]
tons of crashs ?? MEGATONS !!


D4NM4N(Posted 2010) [#18]
i disagree with the nogo statement for the use of goto , its a simple Asm instruction jo,jno,jns,jbe,jl,jne and its fast if the cpu not reload the instruction cache ,or reload the pipeline .
if you ever disassembled a x86 file you see much jumps in the source ,
also esp.x86 cpu are desingned for .
true :D
although if you are using a HIGH level, structured (albiet non oop) language you still should have no excuses for a goto (except perhaps jfk's exit-exit-exit loop, but even then i would be cringing when i implemented it.

If evoulution were programming languages then goto would in the "goop" attempting to have a proper organism.

I have a -little- more respect for gosub because it is technically a parameter & scope-less function, but even so. Whats the point in using it when a language has functions, and structured logic implementation?

Last edited 2010


Ferret(Posted 2010) [#19]
I have never used these commands in blitz.
The last time i used them was in basic on the C64, a long long time ago :)

First learn about using functions, then learn about types.
Learning how types worked was hard for me, but once you get them they are magic.

Last edited 2010