Better method than GoTo for Guard Clause at the start of a loop? (1 Viewer)

spaLOGICng

Member
Local time
Today, 10:29
Joined
Jul 27, 2012
Messages
127
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
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.

I would use GoTo's or GoSub ... Return if I need to handle many sub routines inside the same sub procedure or function. If those sub routines can be used elsewhere, I will just create function to handle it. I would prefer a separate function before a Gosub ... Return.

Tip: Before I ever write any VBA I try to determine how much of what I am about to write can be accomplished in a query or series of queries. Why? Because if the DB will ever be migrated to SQL Server, it is a lot easier to migrate queries to VIEWS than it is VBA to Stored Procedures.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:29
Joined
Feb 19, 2002
Messages
43,296
GoTo's are the path to spaghetti code. GoSub's are not. They are different. GoTo (bad). GoSub(good).

Because if the DB will ever be migrated to SQL Server, it is a lot easier to migrate queries to VIEWS than it is VBA to Stored Procedures.
If you understand how Access and SQL Server work together and how to create bound forms that don't retrieve excess data, you should have very few instances where you need to create stored procedures.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 12:29
Joined
Feb 28, 2001
Messages
27,192
It is exactly this problem that causes me to not be a fan of Niklaus Wirth, "father" of PASCAL. Wirth advocated NEVER using a GOTO but instead exclusively using IF-nesting. Talking about IF pyramids 8 to 10 layers deep, you reach the point where the levels of the IF become very hard to read - yet if you program in a "pure" PASCAL environment, that is exactly what you have to do.

When you have a decision to make and an action to take, there is nothing quite like an "IF decision THEN action" clause. Some languages support a verb to terminate an iteration of a loop by using, e.g. END DO to end the loop at point X rather than going down to the end. (VBA does NOT have this option. I checked the syntax reference.) But in the greater scheme of things, we should consider what is compiled.

Code:
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

If you consider these two options, they should produce near identical code. In one case you skip via GOTO. In the other case you skip via an IF nest. But internally the code is the same anyway. Now if you have MULTIPLE causes to skip, things get more complex but the concept is still the same. Whether you nest via an IF pyramid or use a single-line IF ... THEN GOTO ... to maneuver will be a matter of aesthetics and personal style.
 

Josef P.

Well-known member
Local time
Today, 19:29
Joined
Feb 2, 2023
Messages
827
.. and if "something else" requires more lines of code (possibly with further loops):

Code:
DO UNTIL rs.EOF
    IF rs![OK] THEN
        GoSub DoSomethingLineMarker
    END IF
    rs.MoveNext
LOOP
or
Code:
DO UNTIL rs.EOF
    IF rs![OK] THEN
        DoSomethingProcedure rs
    END IF
    rs.MoveNext
LOOP
 

KitaYama

Well-known member
Local time
Tomorrow, 02:29
Joined
Jan 6, 2022
Messages
1,541
Talking about IF pyramids 8 to 10 layers deep, you reach the point where the levels of the IF become very hard to read
Doc, most of the problems are because of poor Visual Basic editor that comes with Access, not the style of programming.
When I programmed in PHP, I used Zend (Eclipse) ide. It was a powerful editor with a lot of abilities. One of those was a small plus sign it gave you for most statements that spread through several lines. You can use it to Expand/Collapse them if necessary. Or even simply double click If/For Each/For……. To Expand/Collapse them.

It gives you the ability to go how many deep you want in your loops and IFs without being lost. Just hide others and take care of what you’re working on.
Something else that I loved about it was when the cursor was within a loop or IF, the background color of the group was changed. So you could easily concentrate on the most inner loop/IF.



A78D7AEB-5F4B-4E5B-8671-9FF273B55ED6.png


As far as I remember even Notepad++ (freeware) has this ability. But not Access. What a shame.
 
Last edited:

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:29
Joined
Feb 19, 2002
Messages
43,296
The key to not having to resort to GoTo's is to decide whether you want to do something before you get into the procedure as Josef showed rather than after you are in the procedure where you then use the GoTo to exit prematurely. If you think about what you need to do before you start coding, you won't fall into the trap of having to use GoTo's to get out of code you shouldn't be in to begin with.
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 18:29
Joined
Sep 12, 2006
Messages
15,658
I really don't think there is anything inherently wrong with a goto, judiciously used. If you want to terminate an iteration and continue with the next iteration, goto the loop point. The goto can be be a simple way of cutting the Gordian knot without tying yourself in complex conventions. (and tortuous code simply to avoid using a goto statement). Note you might need to clear some variables/structures before the goto.

What is the assembler instruction? Unconditional jump. I expect some code might compile into an unconditional jump even if you don't explicitly use the goto command, but I may be wrong.

FWIW, I just got this from ChatGPT (Q: is it acceptable to use goto when programming).

The use of the `goto` statement in programming is a topic of debate among software developers. While `goto` can provide a way to transfer control to a specific location in code, it can also make code harder to understand, debug, and maintain. As a result, many programming languages, such as Python, Java, and C#, either discourage or completely prohibit the use of `goto`.

When code relies heavily on `goto` statements, it can create "spaghetti code," where the flow of control becomes difficult to follow. This can make it challenging to reason about the behavior of the program and introduce bugs that are hard to track down.

Modern programming languages offer alternative control structures, such as loops, conditionals, and functions, which provide more structured ways to control program flow. By using these constructs effectively, you can generally avoid the need for `goto` statements.

However, it's essential to note that there are a few situations where the use of `goto` may be acceptable or even necessary. Some legacy codebases or specific programming domains might still rely on `goto` for performance reasons or to work with existing code. Additionally, certain low-level programming tasks, like implementing state machines, may benefit from limited and careful use of `goto` statements.

In general, it is best to avoid using `goto` unless you have a compelling reason to do so and thoroughly understand the potential consequences. Striving for code clarity, maintainability, and readability should be the primary considerations when deciding whether to use `goto` or alternative control structures.
 

Pat Hartman

Super Moderator
Staff member
Local time
Today, 13:29
Joined
Feb 19, 2002
Messages
43,296
I really don't think there is anything inherently wrong with a goto, judiciously used.
"Judiciously used" is the operative term. That is as fluid as gender these days. Everyone who uses GoTo's always uses them "Judiciously".

I remember a post from a few years ago where the code posted was rife with labels and all transfer of control was done using GoTo. I have never seen a worse example of spaghetti code, EVER😱 I don't even remembe what the problem was or if I was able to help.

You have to use a GoTo to handle errors. Beyond that, they just enable you to be sloppy and avoid refactoring code to make the decision in a different place. I've seen very little code in my many years of reading code where the use of GoTo's didn't result in the use of branching "back" (which is the spaghetti code syndrome) and that includes error handlers. Even my error handlers branch "back" so when they exit the procedure, they exit at a label and the code that follows the label does clean up. I don't use them (except as forced by the error trapping logic) and haven't suffered from their lack in my 50+ years of writing code.
 

Users who are viewing this thread

Top Bottom