NauticalGent
Ignore List Poster Boy
- Local time
- Today, 04:19
- Joined
- Apr 27, 2015
- Messages
- 7,099
No, that is not what I was implyingWhy? That would make me wrong?
No, that is not what I was implyingWhy? That would make me wrong?
This is what I am trying to figure out...it allows you to use the best tool for the situation.
Do you find the long procedures clearer or compacter?... I would NEVER use a separate procedure if the code were to be used within only one procedure.
No way, as soon as it makes the code more readable and maintainable, I would use it.Do not discount using GoSubs without knowing what they are used for and how to use them.
This is a good example in my opinion. GoSub has improved the process. That is a good reason to use it.In my genealogy database, I had to use GoSub several times because of the potential for recursion in trying to establish generational differences between two people. Because it had a smaller stack footprint, it worked far better than the functions I originally used that, because of recursion, often "blew out" the program stack. ("Heap overflows stack" error. Or "Stack overflows heap", depending on which action revealed the dirty deed.)
Public Function Func1_WithGoTo()
Dim Var3 As Long
Dim Var2 As Long
Dim Var1 As Long
With CurrentDb.OpenRecordset("select field, done from table1 where done = false", ...)
Do While Not .EOF
Var3 = .Fields(0).Value
.edit
.fields(1).Value = True
.Update
If DCount("field2", "table2", "field = " & Var3 & " and outstanding > 0") = 0 Then
MsgBox "invalid Var"
GoTo SkipLoop
End If
'do a whole bunch of stuff
Do Until Var1 = Var2
' ...
Loop
.MoveNext
SkipLoop:
Loop
.Close
End With
MsgBox "Fin", vbSystemModal
End Function
Public Function Func1_WithGoSub()
Dim Var3 As Long
Dim Var2 As Long
Dim Var1 As Long
With CurrentDb.OpenRecordset("select field, done from table1 where done = false", ...)
Do While Not .EOF
Var3 = .Fields(0).Value
.edit
.fields(1).Value = True
.Update
GoSub DoSometingWithField
.MoveNext
Loop
.Close
End With
MsgBox "Fin", vbSystemModal
Exit Function
DoSometingWithField:
If DCount("field2", "table2", "field = " & Var3 & " and outstanding > 0") = 0 Then
MsgBox "invalid Var"
Return
End If
'do a whole bunch of stuff
Do Until Var1 = Var2
' ...
Loop
Return
End Function
Public Function Func1_WithSubProc()
With CurrentDb.OpenRecordset("select field, done from table1 where done = false", ...)
Do While Not .EOF
.edit
.fields(1).Value = True
.Update
DoSometingWithField .Fields(0).Value
.MoveNext
Loop
.Close
End With
MsgBox "Fin", vbSystemModal
End Function
Private Sub DoSometingWithField(ByVal Var3 As Long)
Dim Var2 As Long
Dim Var1 As Long
If DCount("field2", "table2", "field = " & Var3 & " and outstanding > 0") = 0 Then
MsgBox "invalid Var"
Exit Sub
End If
'do a whole bunch of stuff
Do Until Var1 = Var2
' ...
Loop
End Sub
@The_Doc_Man I regularly use GoSubs (when I don't have any plan to re-use them in other functions) and I don't see any of your Cons as a real con. Maybe only the memory stack one. (I don't understand that)
I see only two cons for GoSubs:
1- You can not shift+F2 a GoSub to jump to that specific section of program (Subs and functions give you this shortcut) It means you have to scroll up and down regularly.
2- You can't jump over them while debugging. If you have several subs and functions that are called in a procedure, you can shift+F8 them to execute them without stepping in. But you can not do this on GoSubs. While debugging, you have to go line by line, or put a break somewhere ahead and do a F5 to jump over them. And after a while your function is full of break points and you're lost between them.
Yet, I like them and use them as much as I can. (again, if that section is not going to be used by other functions)
I would use a Boolean variable to skip but stay inside the loop and what I do inside the loop, or use Exit For to escape the Loop.My old functions were serious pyramid code, often multiple nested if's deep, since then I've been using guard clauses and setting values/checking values though a series of separate if's instead of nesting, it's definitely easier to keep track of the "end" compared to nesting!
However I'm stuck when it comes to loops as there's no "continue" function to "exit sub" from that loop based on the guard clause, I suppose I could call the function repeatedly instead of it being a loop, but that wouldn't work for a nested loop that's relying on values from the main function, I know they could be passed but that's back to getting harder to read and jumping around more than "goto SkipLoop" would be?
I'm not bothered either way about goto or not goto, but the convention is there for a reason and I'm curious to have other opinions on best practice
DO UNTIL rs.EOF
IF not rs![OK] THEN GOTO SKIPSTEP
something else
SKIPSTEP:
rs.MoveNext
LOOP
....
DO UNTIL rs.EOF
IF rs![OK] THEN
something else
END IF
rs.MoveNext
LOOP
DO UNTIL rs.EOF
IF rs![OK] THEN
GoSub DoSomethingLineMarker
END IF
rs.MoveNext
LOOP
DO UNTIL rs.EOF
IF rs![OK] THEN
DoSomethingProcedure rs
END IF
rs.MoveNext
LOOP
Doc, most of the problems are because of poor Visual Basic editor that comes with Access, not the style of programming.Talking about IF pyramids 8 to 10 layers deep, you reach the point where the levels of the IF become very hard to read