Programming Logic for stopping events from occuring (1 Viewer)

GBalcom

Much to learn!
Local time
Yesterday, 22:46
Joined
Jun 7, 2012
Messages
459
For the sake of brevity, I'll be as abstract as I can. If you need more details, I'll be happy to go deeper.

I have developed a medium sized application where I have a flow of 3 main events. 4,300 lines of code and 15 modules (6 are classes) so far. I've tried to make the code modular and reused where appropriate. Each main event is taken care of by several modular pieces of code, which are called by sub-events. Most of them are boolean functions which return a value of true if successful. In some cases this is 3 or 4 levels deep and honestly, it just seems clumsy.

It dawned on me this may be much cleaner if I had a global boolean variable that I just set to false in the event of an error that I didn't' want to proceed with other processes. Does anyone use this type of approach? Or maybe a different approach they prefer?

This isn't about error trapping per se (On Error GoTo, etc.), but stopping events if something upstream didn't work as intended. I look forward to any and all feedback.
 

jdraw

Super Moderator
Staff member
Local time
Today, 01:46
Joined
Jan 23, 2006
Messages
15,379
I haven't tried any of this, but my initial thought.
I would try a TempVar, since it would be available across the application.
TempVars do not lose their value when an unhandled error occurs and because they can be referred to directly from within queries. Additionally, I can set the value of a tempvar item in the immediate window and can immediately test the performance of a query, form, or report.

If you set it on any error condition, and each routine checked the tempvar value, I think that represents the logic you described.

As I said -untested. And it my just be a duplicate of your thoughts....
 

GBalcom

Much to learn!
Local time
Yesterday, 22:46
Joined
Jun 7, 2012
Messages
459
Thank you Jdraw!
I wasn't aware of the issue with unhandled exceptions and global variables. One question -- what exactly is an unhandled exception? Every single function or sub in my application has the "On Error GoTo Proc_Err" with a this setup at the end:

Code:
PROC_EXIT:
    Set Options = Nothing
    Set wo = Nothing
    
    Exit Sub

PROC_ERR:
    MsgBox Err.Description, vbCritical, "mStatusChangeActions.RunWoStatusOptions"
    Resume PROC_EXIT
    Resume

So, would I have the possibility of an unhandled exception?
 

jdraw

Super Moderator
Staff member
Local time
Today, 01:46
Joined
Jan 23, 2006
Messages
15,379
I found this in a discussion on UA re unhandled errors.
.....the primary reasoning behind using TempVars over Global variables is that if there is a code rest, TempVars do not lose their value; whereas Global variables do lose their values when the code resets. (Of course, you stated you know that part already.)
So, if the code ever breaks and throws the user an error, all global vars are emptied. Not so with TempVars. Ergo, the use of TempVars being the better practice.
Jack's suggestion for the use of Public Properties is also superior to Global variables, just a bit more to 'bite off'. For Access 2003 and lower versions, I prefer the Public Properties method. For Access 2007 and up, I use TempVars. And because Public Properties work well in all versions of Access, I use that method for multi-versioned deployments.
Yet another tried & true method is to use a USysTable for storing important/global session variables.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:46
Joined
Feb 28, 2001
Messages
27,131
what exactly is an unhandled exception?

An "unhandled exception" is a signaled error that occurs when there is no declared error handler. Actually, it is more specifically a signaled error that occurs when YOU don't have a validly declared error handler, but there is ALWAYS an error handler from Access itself, called the "Last Chance" error handler. (That's where the "Debug,Reset" message box is issued.) You state that you have scrupulously defined error handlers so that should be rare for you. Note that there are unsignaled errors such as (but not limited to) those that occur in SQL that would return #Error or #Name or #Func for some field rather than trapping the whole query.

There is a lot to consider regarding how to track errors and what to do when you have them. If things get to the point that a user gets a "Retry, Debug, Reset" box (or even only the "Debug, Reset" case), you don't want them to continue anyway because something is badly hosed. I used a set of app status flags in a public module. After a reset, they would be erased, but my forms tested them often enough that if they found that a reset HAD occurred, they would ungracefully force the app to quit and the user would have to start over. I always used a modal-dialog, OK-Only message box to say "We have detected crap hitting the fan, time to clean up and get out of here." (Or words to that effect.) Then when the user clicked OK, it was "Hasta la bye-bye baby."
 

Mark_

Longboard on the internet
Local time
Yesterday, 22:46
Joined
Sep 12, 2017
Messages
2,111
To me, it sounds as though you are putting a cart in front of random animals...

I would not be checking to see if there is an error, rather I'd simply make sure each piece had completed properly before doing the next step. I'd assume failure unless proven otherwise.

This means you have code that says "IF step A completed properly, do Step B, else scream in pain". By only progressing when you KNOW something finished correctly you avoid a lot of issues. Same with state machine structures, on error it drops out of the normal processing and highlights the error.
 

The_Doc_Man

Immoderate Moderator
Staff member
Local time
Today, 00:46
Joined
Feb 28, 2001
Messages
27,131
Mark_ is not wrong in his comments. It depends on what exactly was meant by

in the event of an error that I didn't' want to proceed with other processes

If you are looking for PROCEDURAL errors because someone didn't dot an "i" or cross a "t" then that is one thing. If you meant "An Access signaled error" occurred during a process then it means something else. Mark_'s answer is about procedural errors. My comments were about signaled errors.
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 06:46
Joined
Sep 12, 2006
Messages
15,634
if you run a sequence

Code:
call task1
call task2
call task3
etc


then get each task to return a function result - boolean is probably sufficient.
this sort of thing, with appropriate error messages

Code:
if not (task1) then exit sub
if not (task2) then exit sub
if not (task3) then exit sub
etc
 

GBalcom

Much to learn!
Local time
Yesterday, 22:46
Joined
Jun 7, 2012
Messages
459
Thanks guys,
Marks comment got me thinking. It was procedural, but I was missing an important step.

This is a snippet of my previous code:

Code:
Public Function RunProgram() As Boolean
    ' Status:  In Devlopment
    ' Comments:
    ' Params  :
    ' Returns : Boolean
    ' Created : 06/10/19 13:20 GB
    ' Modified:
    

    On Error GoTo PROC_ERR


   
    If Not RunWoStatusChanges Then
        MsgBox "mAppLogic.RunWoStatusChanges failed.  "
        RunProgram = False
    End If
    
    If Not RunWoTgtFinDateChanges Then
        MsgBox "mAppLogic.RunWoTgtFinDateChanges  failed.  "
        RunProgram = False
    End If
    
    'setup shadow table for next time
    If Not RefreshShadowTable() Then
        MsgBox "mShadowTable.RefreshShadowTable method has failed."
        RunProgram = False
    End If
    
    
    RunProgram = True


I realized after Mark's comment that I wasn't stopping the program flow if something messed up. Now I've got this:

Code:
Public Function RunProgram() As Boolean
    ' Status:  In Devlopment
    ' Comments:
    ' Params  :
    ' Returns : Boolean
    ' Created : 06/10/19 13:20 GB
    ' Modified:
    
    On Error GoTo PROC_ERR

    Dim blnError As Boolean
    blnError = False
    
   
    If Not RunWoStatusChanges Then
        MsgBox "mAppLogic.RunWoStatusChanges failed.  "
        RunProgram = False
        blnError = True
    End If
    
    If Not blnError Then
        If Not RunWoTgtFinDateChanges Then
            MsgBox "mAppLogic.RunWoTgtFinDateChanges  failed.  "
            RunProgram = False
            blnError = True
        End If
    End If
    
    
    'setup shadow table for next time
    If Not blnError Then
        If Not RefreshShadowTable() Then
            MsgBox "mShadowTable.RefreshShadowTable method has failed."
            RunProgram = False
        End If
    End If

    RunProgram = True

PROC_EXIT:
    Exit Function

PROC_ERR:
    MsgBox Err.Description, vbCritical, "mAppLogic.RunProgram"
    Resume PROC_EXIT
    Resume


End Function

So, the difference was adding a boolean variable that is carrying down the result of previous calls. Feedback Welcome

One more thing. I think I do not have to set blnError to False in the beginning correct? Doesn't it start off as false?
 

gemma-the-husky

Super Moderator
Staff member
Local time
Today, 06:46
Joined
Sep 12, 2006
Messages
15,634
as you aren't going any further after an error you may as well do this, which is similar to what I suggested. There isn't any need to go further.
Code:
runprogram= false
exit function
 

Mark_

Longboard on the internet
Local time
Yesterday, 22:46
Joined
Sep 12, 2017
Messages
2,111
Another way of doing the same would be to have EVERY call return FALSE if succeeds, and an error code if it fails. then you code look like

Code:
If RunWoStatusChanges() Then GOTO ProcFail
If RunWoTgtFinDateChanges() Then GOTO ProcFail
If RefreshShadowTable() Then GOTO ProcFail

RunProgram = True

PROCFail:

RunProgram = FALSE

more elaborate would be to save the passed value to handle outside of the called function, but my preference is to have each function clean up after itself.

This can all be wrapped inside of a SELECT CASE if each called function returns the value for the NEXT function that needs to deal with something.
 

Users who are viewing this thread

Top Bottom