So, I am having to deal with seemingly archiac language (called PowerOn) where I have a main method, a few datatypes to define variables with, and has the ability to have sub-procedures (essentially void methods) that does not return a type nor accepts any arguements. The problem here is that EVERYTHING is global. I’ve read of these type of languages, but most books take the aproach “Ok, we use to use a horse and cariage, but now, here’s a car so let’s learn how to work on THAT!” We will NEVER relive those days”. I have to admit, the mind is struggling to think outside of scope and extent.
Well here I am. I am trying to figure out how to best manage nothing but global variables across several open methods. Yep, even iterators for for
loops have to be defined globaly, which I find myself recycling in different parts of my code.
My Question: for those that have this type experience, how did programmers deal with a large amount of variables in a global playing field? I have feeling it just became a mental juggling trick, but I would be interested to know if there were any known aproaches.
15
You’ll need some kind of mental bookkeeping tricks (naming conventions, etc) in order to keep it straight. Also, document, document, document. Since all variables are globals, have a single document with all of them listed, if you can.
Try to have a small number of variables that you always use for temporaries, and remember that THEY ARE TEMPORARY. By constantly re-using the same ones, you’ll get into the habit of keeping track of where they are valid or not.
Also, you want to look at the documentation and make sure you know how long variable names can be, and how many characters are actually unique. I know NOTHING about PowerOn, but if it’s archaic enough to have only global scope, then it’s possible that it’s got a limited uniqueness length on identifiers.
I’ve seen things before with long identifiers, but whose identifiers were only unique in the first 8 characters. So you could have RonnyRayGun and RonnyRayBlaster and they are actually the SAME variable. In such cases I recommend keeping variable names under the ‘unique’ limit so that you’re less likely to accidentally collide.
1
Data dictionary.
In a central repository (usually the lead programmer’s office), there was a looseleaf binder, that contained one page for each and every global variable. The page gave the name, its definition, its purpose, and which routines set or used it.
Early embedded systems with microscopic RAM had a similar problem, and a similar solution. The lead programmer maintained the master RAM map, down to the individual bytes, showing what RAM was used by which modules for which purposes. Programmers who needed a dedicated RAM allocation went to the lead programmer, who, after discussing the matter, made the appropriate notebook entry and gave the guy his RAM. (You did not want to be in the shoes of the programmer who took a RAM byte without clearing it with the lead programmer. Trust me on this.)
This problem also showed up when programmers had to build large systems in early versions of BASIC. It showed up for me personally while using a very primitive “database” manager called Info (product of Henco, Inc. of New Jersey – HOPEFULLY now long gone!). Both of those languages had a very limited variable name vocabulary.
3
The rise of programming languages with block scope coincided with the advent of faster, larger machines, and that is no coincidence. Early computers had RAM measured in MB, kB or even in bytes; there was simply no opportunity to even have so many variables that they would be confused when the program got large, because programs never got that large. Advances in programming languages were usually made when people recognized that their old programming habits didn’t scale up when the arena got much larger; block scope was invented as a mechanism of defense for programmers against their own limited memory.
Computing was also a much more rarefied and exotic activity when comoputers were fantastically expensive, and it may well be that only particularly mathematically inclined and ingenious individuals became programmers in the first place (although such comparisons are impractical to test, and certainly politically incendiary). In the early days, software was usually shipped for free with a computer in order to convince people to buy it in the first place; the thought that institutional users would even attempt to write their own programs was unknown at first.
4
My gosh, that is many years ago (bubbling memories :)).
I don’t know the language you refer to, but in general we adapted to what we had. It wasn’t really a huge issue. You needed to pay more attention to var names which often contained (in short form, in those days number of bytes was precious) reference to sub or function, like mIORead1
if you had a handler to read data from a file 1, or you had various counter vars like i, j, k etc. which by your own system you knew what they were for, if they could be reused and so forth. It was more hardcore (no helmets or gloves back then) 🙂
This is pretty similar to PLC programming, though modern PLCs now allow you to have “tags” (aka variables) that are local to a program. Still, a lot of people just program using all global tags.
I’ve found, if you’re going to do that, you need to use a structured naming convention. For instance: Motor1_DriveContactor_Run
. If your language happens to support structures (sometimes known as user-defined types) then you can also use those to create a structured data hierarchy, such as: Motor[1].DriveContactor.Run
.
That keeps everything organized, and usually the intellisense is decent enough to help you along.
I actually learned to program in a language called Authorware, where everything was global. Luckily, it did have Arrays and after a certain point something called Lists, which were similar to generic objects.
An Authorware program actually had a physical structure (Authorware was based on a flow-chart metaphor), and its scripting language was based on old-style Pascal. What we did was to relate the physical structure to the indices in an Array, and often the Array indices would contain Lists that we’d treat as a local object for the physical piece we were using.
Authorware was designed for eLearning, so one of the icons we had was a Page. Pages would be attached to a Framework. So, for Page 1, we’d look in some Array at index 1 (Authorware was 1-indexed) and pull out the data for that page, which would be stored a List that would act as a pseudo-object. The Page would then have logic that would pull out the “properties” of the object by name. If you don’t have anything like Objects, but you have Arrays, you can simply have a convention of what data goes where.
It’s not really that different from what we do when we retrieve data from a database and perform dependency injection, except that everything’s really global, and you’re simply choosing to put everything into little boxes and only look at the one(s) you’re concerned with right now.
Depending on what you’re trying to do and what your language supports, this might help you at least break things down into more manageable chunks.
2
When I was at university we were taught at length about “The Global Variable Problem” – a collection of bugs and code maintainence problems caused by lots of global variables.
Some variables are more dangerous than others.
Safe: Variables which do not affect the flow-of-control e.g. LastName
Dangerous: Any variable which affects the flow-of-control of the program e.g. DeliveryStatus
Most dangerous first:
- Compound status (mode and sub-mode)
- Compound values (total, sub-total)
- Single status (mode)
- Single values (count)
To avoid the “global variable problem” you need to
- Document each variable and function.
- Keep related variables close together (with code which uses them) in the same section of the source code.
- Hide the “dangerous” variables, so other programmers do not know of their existance. Avoid using them directly, especially in other sections of the code.
- Provide functions which read/write dangerous variables (so other programmers do not need to).
To structure your code, when no structure is available in the language, use comments and naming conventions:
/* --------------------------- Program mode ------------------------ */
var Mode_Standard = 1; // Normal operation (SubMode unused)
var Mode_Backup = 2; // Backup mode (SubMode is backup device)
var BackupMode_Disk = 1; // SubMode: Backup to disk
var BackupMode_Tape = 2; // SubMode: Backup to tape
var MainMode = Mode_Standard;
var SubMode = 0;
function Mode_SetBackup(backupMode)
{
MainMode = Mode_Backup;
SubMode = backupMode;
}
function Mode_SetStandardMode()
{
MainMode = Mode_Standard;
SubMode = 0;
}
function Mode_GetBackupMode()
{
if (MainMode != Mode_Backup)
return 0;
return SubMode;
}
/* --------------------------- Stock Control ------------------------ */
var Stock_Total = 123; // Total stock (including RingFenced)
var Stock_RingFenced = 22; // Ring-fenced stock (always less than total)
// Adds further ring-fenced stock
function Stock_AddRingFenced(quantity)
{
Stock_Total += quantity;
Stock_RingFenced += quantity;
}
/* ------------------------- Customers ----------------------- */
var Customer_FirstName = "Tony";
var Customer_LastName = "Stark";
Don’t know how they did.
But I think that modern OOP languages had a very similar problem regarding the naming collision.
The solution is adopting namespace. It is an abstract concept, but widely adopted by several implementation (Java packages, .NET namespace, Python modules).
If the language you are using has not too narrow limitation about naming lenght, then you can apply the namespace to a good variable naming.
So the variable name also represents the variable scope.
Try to define a naming pattern like this: order_detail_product_code
, order_detail_product_unit_price
. Or for the temporary counters or swaps: tmp_i
, tmp_swap
.
In languages were all variables are global (I have used a couple) we used to use a variable naming convention. For example: if I actually wanted to use a variable as global I might use “m_” or “_” prefix. Of course this still relies on the developers to have this discipline