Welcome To The Home Of The Visual FoxPro Experts  
home. signup. forum. archives. search. google. articles. downloads. faq. members. weblogs. file info. rss.
GENERAL BEST PRACTICES >>  EVERYBODY TELLS ME THAT PUBLIC VARIABLES ARE NOT GOOD PRACTICE - WHY?

  Ken Murphy
  Where is Ken Murphy?
 Springhill
 Canada
 Ken Murphy



PUBLIC variables are visible throughout the application - this means that you can use a public variable when ever you need it and from where ever in your app - from a method, an event, from a function or procedure - surely this is good. Why do experienced developers discourage the use of public variables. There are two situations that can be used to describe why PUBLIC variables are frowned upon.

VFP will allow you to run the following code:

PUBLIC guMyVar

guMyVar = [Text]
guMyVar = .f. && boolean
guMyVar = 123 && numeric
guMyVar = NULL
RELEASE guMyVar


You can actually copy this code directly into the command window and run it without encountering an error.

Here is the problem. Lets say that in your Main.Prg, you declare your variable public and store an inital value to it.

PUBLIC gnMyVar
gnMyVar = 100


Throughout your app, you use this variable as a numeric value. You do things like:

ThisForm.MyTextBox.Value = lnSomeValue * gnMyVar


In one of your forms, buried deep within the bowels of the code, as part of a nested IF statement, you make a mistake. You issue something like

gnMyVar = .f.


Now, your user goes into that form and by sheer luck, stumbles upon the exact set of conditions that would change gnMyVar from 100 to .f. Now the user closes that form and opens up another form. This form expects that gnMyVar will be numeric and attempts to do some math with it. The app will pop an error message.

This is going to be one very difficult mistake to find. There is nothing actually illegal in any of your commands. It is perfectly legal for you to assign a boolean value to a numeric variable. Because the variable is PUBLIC, when the boolean value is assigned, you just made the variable boolean throughout your app.

The second scenario is also quite difficult to find.

In the .Init() of your form, you initialze your public variable to a value like 100 and your user changes this value using a spinner or textbox. The user changes this value to 50 but then the phone rings. The user looses track of what ever it was s/he was doing and re-opens that same form. "Oops, I have the same form open twice" so the user closes the second instance of the form and proceeds to work with the originally opened form. Unfortunately that value is now 100. Your user will come complaining that "I set that value to 50 and now it is 100!"

When the second instance of the form was opened, the .Init() will reset the value in that public variable to 100. Again, this will not be very easy for you to find. You won't be able to reproduce the error. Your user will probably not remember "oh yes, I did open that form twice." You are going to be in for a very difficult time trying to find out why this happened.

I often tell people that I HATE public variables and that I avoid them where ever possible. Actually this is only partially true. I hate public variables in MY CODE. Now if those public variables are found in other peoples code, I typically end up getting a phone call "Can you help our developer with this problem?" I say "sure, not a problem. Here is what it will cost you." Today, I read a post where Marcia said "My price goes up with every public variable found." This is a brilliant idea. I think I will adopt it.

FEEDBACK

Eric den Doop @ 12/7/2006 4:34:39 PM
if I need public access to a value, I usually store it in a property of a custom class which I add to _screen. This class also has methods to retrieve data from ini files and other lookups. For example:

DEFINE CLASS mysettings
myTitle = "Hello World"
FUNCTION dbPath AS String
RETURN readinivalue("dbPath", C_INIFILE)
ENDFUNC
ENDDEFINE

Ken Murphy @ 12/7/2006 6:19:04 PM
Eric,

I normally do a similar thing. There is almost ALWAYS a way to avoid the public variable.

Great feedback! If I could rate it, I would.

Bob Brook @ 12/7/2006 6:49:02 PM
All sounds like my old university professor banning the use of GO TO's.

But we all know that in practise they are wrong to be so dogmatic.

For a program can be shorter, quicker and more easily understood if a few GO TO's are used.

I believe the same of public variables.
Yes they can be abused, but good naming conventions and careful coding, so that most instances of use are assignments from or logic tests makes a program easier to write and maintain.

Their main advatange is that they are ALWAYS available not matter what objects are released; intentionally or otherwise. Especially when a system crashes.
This makes them good for tracking user paths through software and reporting under an On Error routine.

I use them to hold key data like:
- open company
- open financial year
- current e-mail address (customer/supplier/contact) of last accessed record

or any variable that is constantly being used.

I feel their pitfalls are no worse that other similar traps in VFP - like not declaring a local variable and then using/changing a variable of the same name in a higher procedure/function.

For me globals work well and make programs easier to read, type and debug, not the other way round.

All my globals begin with g followed by s/n/i/l/ etc.for its data type.

Andy Kramek @ 12/7/2006 9:27:26 PM
Bob, I am afraid that you are incorrect in your assessment. The real objection to PUBLIC variables in an OOP environment is that they break the fundamental rule of object programming - i.e. that an object should encapsulate its data and methods. A public variable (by definition) breaks encapsulation and is, therefore, bad practice in an OOP environment.

In procedural programming the situation is different. In that case there is only ever a single thread running through the application and it may be perfectly safe to do as you suggest and use PUBLIC variables. But as soon as you move into a true Event-Driven, or Object Oriented, environment public variables are an accident waiting to happen.

Eric Moss @ 12/8/2006 3:36:42 PM
Yes, andy would be correct. The 'Textbook' Reason for public variables being bad is data sensitivity reasons. However, programming problem as you bring up are also pertinent to consider when deciding to use a public variable or not. All in all, i agree with the school of thought that "a little bit goes a long way" which is why i support using them only when neccessary, and sparingly at that. But that's my opinion.

Bob Brook @ 12/8/2006 11:12:23 PM
Andy,

The fact that I am not an OOP purest is of no concern to me!

VFP allows public variables.
I use public variables.
They work.

For me, any programming language is a tool to get a job done, not an exercise in remaining pure in thought and deed to some ideology.

I will use all and every possible element of that tool to get a job done in the simplest and quickest method that suits my not so limited understanding.

If I ever get round to writing in a true Event-Driven environment I will use the tools of that environment. Until such time I do not see the need to apply artifical barriers to my work.

Andy Kramek @ 12/11/2006 1:00:01 PM
Bob, I am pleased that your code works for you and you can write your code any way that you please.
However, the fact that you CAN do something is not an argument for saying that you SHOULD. The problems with Public Variables are not just theoretical - they are very real and cause major issues (especially for inexperienced programmers).
That you understand them and can use them successfully in your specific environment does not alter that in any way. Sounds to me like you are trying to defend the indefensible!

Benny Thomas @ 12/29/2006 10:40:14 PM
After reading this FAQ and its feed back, I am confused. In my appliations, I declare all varialbles as public in the load of the form and issue CLEAR MEMORY EXTENDED in the Unload. If I don't declare variables, while running the form often I get errors like "Variable does not exist.
What to do in such situation.

Benny

Ken Murphy @ 1/2/2007 5:34:33 PM
Benny,

As Andy and Eric suggest, the best way to handle this is to use object properties instead of public variables. For example, inside your form, you can create as many custom form properties as you need. These properties are visible from anywhere in the form and can be accessed from within the form using ThisForm.MyCustomPropertyName. If you are working outside of the form, you can add a custom class containing all of the custom properties that you need to _SCREEN. You can then address these as _Screen.MyCustomClass.MyCustomPropertyName as Eric suggests.

By using custom properties rather than public variables you are following good OOP programming practices - the properties belong to (and are therefore encapsulated in) the objects that will use them. If you use a public variable, it can be accessed and modified from anywhere - it is not encapsulated in the object that uses it.

Give it some thought and you will understand what I mean.

Ken

Hugo Ranea @ 3/28/2007 12:04:59 AM
I think that _Screen.MyCustomClass.MyCustomPropertyName is just a complex way of writing yet another public variable (which is what _Screen is after all), it solves no problem at all, other than making the code longer, but in truth, nothing stops me to make the same mistakes I can do with a public variable. You can even easily change your code to remove Public variables with something like

#define gnMyVar _Screen.MyCustomClass.MyCustomPropertyName

which shows the point I was trying to make.

Of course, as Eric points out, you can add methods to "MyCustomClass" to add functionality, but as long as the properties are public I do not see much difference

Hugo Ranea @ 3/28/2007 12:35:00 AM
I pressed submit too soon...

I do not see much difference if you use it without this added functionality, and I would even prefer the properties in this custom class to be protected with the respective set/get methods (or Public with assign/access methods, but I like set/get better, but that is just me :)

Thomas Bähr @ 8/13/2007 1:02:51 PM
Sorry but I dont see reasons here ...

Scenario 1:
has nothing to do with PUBL Vars but with bad coding theras PUBL Vars is not the Bad coding ...
e.g. cFirstName as a Publ VAR for the firstname .. stated that it is a CHAR and should be used likewise ...

and about setting different type of values like String, Logial again I say its bad coding but no point against PUBL vars because it will happen with all other kind of methods like OOP Approach as well .. no difference there ...

Scenario2:
very bad coding .... and again .. even the OOP Approach would come to the same result ...
why would one Create a PUBL VAR in an Init of a Form which could be called more than once !?



Your Name: 
Your Feedback: 

Spam Protection:
Enter the code shown: