Help the ignorant! Variable Declaration/Scope/lifetime

G

Guest

*Hangs head in shame*

I've learned to do a number of things developing in access, but some of the
basics I'm still unclear about.....in this case: variable declaration.

I have several places in my project where I declare a variable in a
procedure and give it a value, only to do basically the same thing in another
procedure in the same module. In some cases, I've named it something else
(in the second procedure). I think in some I've actually used the same name.

I thought if I took the variable declaration up to the module (module behind
a form, in probably all the important cases) declarations area up top,
declared it and gave it a value, that I could then use it in any procedure in
the module.

I tried it and it didn't work. Why not? I'd really like to go through and
clean up my variables so I don't needlessly declare/value them numerous times
or have more than one variable with the same value.

Any info would be helpful.
Thanks,
CW
 
A

Albert D. Kallal

I have several places in my project where I declare a variable in a
procedure and give it a value, only to do basically the same thing in
another
procedure in the same module. In some cases, I've named it something else
(in the second procedure). I think in some I've actually used the same
name.

Actually, the real goal in software development is to isolate everything as
much
as possible. So, local variables, and NOT sharing them between pieces of
code
is actually a very good. The reason for this is that if you change some code
in one place, you don't accidentally cause something else to break.

Of course, if you need to share some data between routines, then the above
goal changes. However, you often seem someone ask a question how to
pass a value between forms, or return a value from a form, and the
suggestion is to use a global variable. however, that is bad choice IF YOU
can easily change your code, and NOT use a global var. If you avoid
globally shared variables, then you don't have to look in a zillion places
when trying to find a bug. Further, you can cut, or copy code between
different routines...and again since it more isolated, the resulting code is
more robust. And, further, you can copy code, or forms between
different applications, and again you don't have to remember to copy some
variable that was declared in a module. So, as a good rule, and concept,
you do want to avoid global variables.
I thought if I took the variable declaration up to the module (module
behind
a form, in probably all the important cases) declarations area up top,
declared it and gave it a value, that I could then use it in any procedure
in
the module.

Yes, the above is correct. Note that the variable will ONLY able to be used
by that particular form...other forms will not see that value. However, what
you
say above is correct, and I not sure why it not working.
I tried it and it didn't work. Why not? I'd really like to go through
and
clean up my variables so I don't needlessly declare/value them numerous
times
or have more than one variable with the same value.

Well, lets assume we have a form, and in the code module we have:

Option Compare Database
Option Explicit

-- note that you REALLY REALLY REALLY want to ensure that you ALWAYS use
Option Explicit. that option forces you to declare all variables..and if you
don't use it..then a simply miss-typing of a variable will NOT be found
until you run the code. with option explicit, then every time you make
changes to you code...you go debug->compile.

Ok, so, lets assume:


Option Compare Database
Option Explicit
dim i as interger


Sub Test1
i = 1

do while i < 10
i = i + 1
Call Test2
loop

end sub

Sub Test2

for i = 1 to 5

......
end sub

If you look at the above,we have instant bugs because the 2nd routine also
uses the variable i, and will mess up our first piece of code. So, that
problem you complain of having to declare variables over and over is not
such
a bad thing. The better approach is to use what we call local variables:


Option Compare Database
Option Explicit

Sub Test1

dim i as integer
i = 1

do while i < 10
i = i + 1
Call Test2
loop

end sub

Sub Test2
dim i as interger
for i = 1 to 5

......
end sub

In the above, you can see that each routine uses the "i" variable..but they
are self contained, local to the one routine, and also isolated from each
other. that means I can safely modify the code, but not have to worry about
a zillion other routines perhaps, or possible using the same variable.
Further,
I can freely cut and past that code into other parts of the applications,
and
even copy the code to other applications without fear of breaks. A very
large portion of developer time is wasted tracking down bugs...so, the more
you isolate your code, and avoid those global, then less chance of something
else breaking it..


So, the way things work are:

The so called "scope" form the top most all the way down is:

The variable if declared in the eh sub, or function is used. When the sub or
function exits..then he variables are discard. next in line is the forms
code modules variables..and when the form close..then all of those variables
are
destroyed. And, then the final bottom most is the standard code modules.....

Note that in above, all of the routines (local subs, functions) and then the
forms module and then standard code modules CAN ALL have a variable declared
with the SAME NAME. So, the variable at the top most declare is the one
that has the scope.

If you don't declare the variables in the routine..then it
uses the next lower possible declaring for that variable. So, if you don't
declare it local to the routine..then the model level is used. And, if this
is form model..and the variable is not declare..then we go down further to
the
standard modules.

Note that if you declare a variable in a standard module like:


dim i as interger

Then ANY piece of code in that module can use the above variable. We
consider the variable LOCAL to that one module. If you want EVERY MODULE,
and
EVERY form module to be able to see and use that variable..simply declare it
as public

public i as integer
 
A

Al Campagna

Cheese,
It would have been helpful if you had given a sample of your Dim declarations, and a
few simple code samples involving the use of those variables, as they would appear in your
module.

Yes it should. Don't declare any values for the variables though... do that in each
event/function coding.
For example, you could set up all the variables you need for multiple MsgBoxes this way

Option Compare Database
Option Explicit
Dim Prompt, Title, As String
Dim Response as Integer
-------------------------------------------
Private Sub cmdXYZ_Click()
Prompt = "Prompt"
MsgBox Prompt
End Sub
---------------------------------------
Private Sub cmdGetValue_Click()
Prompt = "Do you want to continue?"
Response = MsgBox(Prompt, vbOKCancel)
If Response = vbOK Then
'do something
Else
'do something else
End If

No need to Dim those variables in each code section, just give them a value and use...
--
hth
Al Campagna . Candia Computer Consulting . Candia, NH USA
Microsoft Access MVP
http://home.comcast.net/~cccsolutions

"Find a job that you love, and you'll never work a day in your life."
 
G

Guest

Wow! What can I say, Albert, but thanks so much.

I feel a lot better about that now. At some point you go from wanting to
just "get things to work" to wanting to do things the "right way" ALL the
time. You're post was VERY helpful (and, sounds like I shouldn't go back and
do what I was thinking which saves me boring work!)

Thanks again!,
CW
 
G

Guest

Thanks for the response, Al.

I didn't think of that but it makes a lot of sense.

I guess it's too late, but my code looks like this...all in a module behind
a form:

Option Compare Database
Option Explicit
-----------------

Sub Private SomeSub()
Dim strMyVar
strMyVar = somevalue

- code -

End Sub
---------------
Sub Private SomeOtherSub()
Dim strMyVar
strMyVar = somevalue 'somevalue as in the same value as the sub above

-code-

End Sub
-------------

Sub Private SomeThirdSub
Dim strMySecondVar
strMySecondVar = somvalue 'Again, same value as the first two

-code-

End Sub
------------

Sorry about not being more detailed.

It almost seems like a reasonable option, based on what you're saying, to
declare a set of basic public variables somewhere that I could reuse in any
sub by just giving them a value, and do that at the beginning of any project.

Anyway, thanks a lot for the reply. Gives me something to think about.

CW
 
A

Al Campagna

Cheese,
If strMyVar is a string value in ALL instances in a single module, there's no need to
Dim it in each code section. But, for the sake of clarity you should establish the value
in each code section, so a code reader doesn't have to hunt through previous code to see
what the "last" value for the variable was.
Since you didn't declare a Type in your sample (String, Integer, Byte etc)...Variant is
assumed. I avoid the Variant type... for the sake of clarity in my code.
I would rather call a String a String, and a Integer an Integer, a Double a
Double...and not "mix" string and num values for the same Variant variable name.

And... Private comes before Sub (Private Sub...)

Option Compare Database
Option Explicit
Dim strMyVar as String, intMyVar as Integer
-----------------
Private Sub SomeSub()
strMyVar = "ABC" 'no need to Dim, the module knows strMyVar)
intMyVar = 412
- code -
End Sub
---------------
Private Sub SomeOtherSub()
strMyVar = "ABC"
intMyVar = 412
-code-
End Sub
-------------
Private Sub SomeThirdSub()
strMyVar = "XYZ"
intMyVar = 516
-code-
End Sub

--
hth
Al Campagna . Candia Computer Consulting . Candia, NH USA
Microsoft Access MVP
http://home.comcast.net/~cccsolutions

"Find a job that you love, and you'll never work a day in your life."
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top