[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now


VFP Public Variables

Posted on 2012-09-14
Medium Priority
Last Modified: 2012-09-16
Hi all. This program I am working in assigns nearly 60 public variables during startup. They are not released until the program closes.

I was wondering if this is normal/typical, and if there could be any problems associated with this many variables being held in memory.
Question by:formadmirer
  • 5
  • 2
  • 2
  • +3

Assisted Solution

peterhupp earned 400 total points
ID: 38400215
This is common in Foxpro applications although not recommended.  There should be no issues with memory or anything like that.
LVL 30

Assisted Solution

by:Olaf Doschke
Olaf Doschke earned 400 total points
ID: 38400294
If a framework is used, the only common public variable is goApp, the instance of an application object.

No, this is not common, you don't need public variables in VFP.

There are all the issues with public variables, for which you also avoid them in other languages.

And there is one buggy unwanted behaviour:
If you pass a PUBLIC variable to a procedure OR a function by reference, then the PUBLIC variable becomes hidden (see example code below).
(quoted from http://fox.wikis.com/wc.dll?Wiki~DisappearingPublicVars)

It's an ill usage of a public variable to pass it on as a parameter, but it happens, if a developer comes in late and doesn't know this is a public var.

There are some public variables you can't avoid: System variables. The mostly are settings which partly could also be environment variables as set with the SET command. For the one or other reason there are settings and sysvars, VFP is a historically grown language with a big emphasis on downward compatibility in favor of cleanness.

Bye, Olaf.
LVL 43

Assisted Solution

pcelba earned 400 total points
ID: 38400449
I don't see any cons against public variables set at one place in program init. The memory consumed is marginal because you can have hundreds of variables and thousands of properties.

The problem could be public variables created and changed at various places in the code. Such variables are hard to maintain.

Od course, the issue described at Fox wikis exists from the beginning and experienced developers know about it. Same rule applies for PRIVATE variables as well. And less experienced developers are able to learn this feature easily... If you name public variables properly (e.g. giving them Gx prefix - x describes the data type here) then you can avoid public variables incorrect usage.

New trends in OO programing were trying to suppress public variables but the code base already written in older FoxPro versions and still working under VFP is the main reason why public variables are still used.

If your program works correctly then no reason to change it exists.
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!


Author Comment

ID: 38400530
I was not previously aware of the issue regarding a public variable 'disappearing' when passed to a Procedure or Function.

AFAIK we've never had any issues with the use of these public variables in our program, and they are all preceded with a lower case 'p' to safeguard their use throughout the program.

I just wasn't sure what kind of memory each of these variables was likely to consume, and didn't know if that was something to be concerned about or not.

They are mostly used to store path and file locations, and I added a few like one that holds my MySQL connect string.
LVL 12

Accepted Solution

jrbbldr earned 400 total points
ID: 38400769
Public variables can be passed to a Procedure or Function where they are received as PARAMETERS which most often are local to that piece of code

Or they can be used as-is (not passed) within those pieces of code.

The use of PUBLIC variables was once very common, so if your code is older, it is not un-expected.

However more current programming approaches discourage the use of PUBLIC variables.

Regardless, they should work for you if you want to use them.

If you have questions regarding if their use in a PROCEDURE or FUNCTION is modifying their content (or not modifying it), just put in code to debug your development (Breakpoints and/or SET STEP ON commands) and test the results.

Good Luck
LVL 30

Expert Comment

by:Olaf Doschke
ID: 38401137
Usage of public vars is no go for me. tT seems I'm the only hardliner here. What I agree is, that the memory usage and the amount of them is not a problem. VFP allows infiinite array elements, the memory is your limit, nothing else (in previous versions there was a limit of 65000 elements per array). From that perspective 60 public vars are a small number.

Just take some third party module from a developer having had the same idea about a name of a poblic var and you have a problem. That's the hardest problem of public vars. Another side of them is, you have to know their names, Have goApp.oConfig.property = value and create this goApp during development time and you can find your config properties via Intellisense. Even just that would speak against such public vars and in favor of a goApp object you extend with subobjects.

Also you don't need a connection string public, you just will have one central class connecting to the server, and only that needs to know the connection string. So in this sense the need of public vars show a lack of centralising code.

In regard of config, create a DBF or INF or XML file with simple name/value pairs, configpropertyname, eg data dir and configvalue, eg path to data. Read that into an EMPTY object.

Use config (config dbf has fields property and value)
   Addproperty(goApp.Config,config.property, config.value)

Open in new window

That's that  in very short, you can add code checking for double properties, invalid property names, you can also use a primary index to avoid double names.

It's all about better organising yourself and better describing the scope of things.

All I really need in any place is an identifier for the currently logged in user and the currently selected lanmguage, if my app is localised. I may need some paths, but that is having a smaller scope, eg only reporting modules need to know location of frx files, if I leave them external for dynamically changing them at runtime. But the whole application doesn't need top know their path.

And from that perspective 60 is a huge number, you can have the same overview about your config values in a config.dbf and then add some more fields to denote a type and usage or whatever to organise yourself better.

Bye, Olaf.
LVL 30

Expert Comment

by:Olaf Doschke
ID: 38401144
One more thing you can do to avoid a name overlap, even in such a common name as goApp.Config is, just create a subobject goApp.MyApp or goApp.MyCompany, and add everything else at that level. There is no need to avoid a name conflict of goApp, as you will not really be able to make use of two frameworks at the same time. Even if there would only be the need to merge their application class. Therefor it's also good as a framework developer to keet that application class itself very lightweight and let modules dock to it.

Bye, Olaf.
LVL 27

Assisted Solution

CaptainCyril earned 400 total points
ID: 38401222
FoxPro evolved over the years and yes there are many coding techniques.

In the beginning memory variables were name m.variable.
Later there were types and visibility and types.

nNumber, cString: n = Numeric and c = Character
lnNumber, gcString (l = Local and g = Global).

Open in new window

You can also do without public variables.

Once someone mentioned using over 1000 public variables. FoxPro will still run fast since today computers are extremely fast and have much larger memory compared to two decades ago.

I personally would advise to restrict the use of Public Variables to the minimum: Ex. UserID, Settings Ini File in case you have many like I do (Customizations).
LVL 43

Expert Comment

ID: 38401512
Olaf, if you are so strict in public variables usage then you should not use even the goApp :-)

goApp is just "hardcoded" reference to the "application pyramid top" which is not good practice. Each application should have its own reference named ThisApplication and this object should be visible just in the application thread...

So you should not use goApp as a public variable but you should create private variable in a main program/form and name it ThisApplication. This will ensure compatibility even in multithreaded environment when it will be implemented to VFP language. :-)

OK, more seriously now: To refactor debugged and working code designed in FoxPro 1/2.x is waste of the time. And almost everybody has such code in a drawer... You can

To avoid problem with hidden public variable (which is also valid for private variables) you may simply enclose the variable name in parenthesis when calling a function or procedure:

llResult = MyBadFunction( (m.gcGlobalPath), m.AnotherParam)
LVL 30

Expert Comment

by:Olaf Doschke
ID: 38401593
Application pyramid top, Well, that's how it is, I don't see any difference if declaring aprivate var in main or a public var somwhere in a factory or  whatever is taken to create object. I can live with this one hardcoded reference, as I can make use of goApp.MyApp.translate() or goApp.MyApp.userid or goApp.MyApp.nMySQLHandle. I don`t follow you, how a private variable would be visible in multiple threads and public vars not.

You can also argue this is really not just reducing the number of public things, it's just using properties instead of variables. But it's all about the namespace(s) and the hierarchy you build with it.

If it ain't broke, don't touch it. I mainly agree, but you can put some effort in it, you don't need to do it in one go, and it will help if you use third party code to incorporate this into the "application pyramid".

Bye, Olaf.

Author Closing Comment

ID: 38402695
Evidently this is a hot topic and one that often leads to somewhat heated debates, as I saw on the fox. wikis.com page.

All I needed to know is if the code I am working on is OK in it's current state with using 60 public variables during the startup process.

I now know that maybe this isn't ideal coding practice by today's standards, but also that it is not unheard of and that actually 60 public vars isn't all that many, and won't have a negative impact on system memory available.

Thanks to everyone for their input!
LVL 30

Expert Comment

by:Olaf Doschke
ID: 38402760
> 60 public vars ... won't have a negative impact on system memory available.
How do you get that idea, at all?

Public variables don't take more memory than local, they just have a global scope, they don't release.

The impact on memory is of course depending on what is put into them. But a path is just a few bytes, magnitude 100 perhaps. If that's the mean memory usage we talk of 6KB. Public vars don't effect memory or performance.

And the main question can also be answered: If it works, then it works. And it's not probable the 60 public vars were introduced just in the last few days. I assume the app ran quite some time and so that already answers that anything you find can work. But that's not answering the question if it's good practice, if it's usable, maintainable, understandable, extensible. There are many aspects of code that should be pushed to an overall better quality.

In larger and longer running projects you can often see the effect code quality degrades over time, an application wears out, get's less extensible, has too many dependencies and side effects of changes and is less good to refactor.

You can detect errors in variable scope definitions quite easy. If some value get's passed to very many methods of a class, then it's a sign that parameter should rather be a property of the class, püerhaps. As public vars don't need to be passed on this bad design will not be revealed.

http://fox.wikis.com/wc.dll?Wiki~PublicAndPrivateVariables lists some more interesting characterisitcs of public vars and their redifinition: If you create a public var in main.prg and redefine it somewhere via PUBLIC you don't get an error. Sounds nice, but a redefinition of it indicates that programmer doesn't know it's a public var already and most probably has another usage of it. Surely it will not only be redeclared, but also set to another value, and that then breaks code at other places depending on the initial value. Those are hard to understand and debug errors. You'll first look into main and see the value assigned is correct and then scratch your head, until you finally will perhaps use Code References to see where else this variable is set.

And defining variables as private in main doesn't change that.

The answer in my oppinion is to change from public informations as you have in public variables to available application modules not only holding the information but also being able to work with them. Your oop design can reflect the real world, implementing colleagues having a certain job and knowing all the needed rules. And you rather delegate tasks to them then just ask them for the infos needed to do something at the caller level.

That thought keeps you from reimplementing the same code more than once and that makes use of the most important pattern of modern development: loose coupling. Keep close together what belongs close together and loosely couple these objects to work with related objects. Rather program in a way "do this form me", than "give me the information I need to do it my way".

A database manager class for example will connect to the database and all any other component may need is the succcess of connection or an error level, if there is, and the connection handle.

Keep these jobs or roles small, eg a database manager should manage database connections only, perhaps, and leave data access to dataaccess classes, which can all inherit from a base class and all make use of the database manager, so the database manager can also log and do statistics on how many components request a connection and if it's perhaps a good idea to make more connections and load balance or jsut use one connection, to keep it opened or close it at times of very low usage. This is not the job of the single dataaccess objects anymore. And a public variable may hold the connection handle, but can't do that kind of logic, it's just a dumb variable.

Bye, Olaf.

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Microsoft Visual FoxPro (short VFP) is a programming language with it’s own IDE and database, ranking somewhat between Access and VB.NET + SQL Server (Express). Product Description: http://msdn.microsoft.com/en-us/vfoxpro/default.aspx (http://msd…
Will the future of mobile app development include the same trends as those most relevant today? Find out by checking out the 7 trends of the future.
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
Is your OST file inaccessible, Need to transfer OST file from one computer to another? Want to convert OST file to PST? If the answer to any of the above question is yes, then look no further. With the help of Stellar OST to PST Converter, you can e…
Suggested Courses

872 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question