Re: avoiding huge globals files
Posted in 1996
I missed the original post, so if I'm off the subject just ignore me and I'll likely go away. In <595i9t$hjs@gulfa.kuwait.net> rferdy@kuwait.net (Rudy Fernandes) writes: [Snip of stuff I couldn't argue with] >Also, if a library function is called more than once in a 4gi (as is >usual), the globals concerned are actually being reused (in a sense >different from what we've been meaning so far) and one is open >to possible inconsistencies (calling without setting, typically - but I >can think of others) >With locals, as they exist only in the function in which they are defined, >it is simple to track changing values. If they have been passed, the >backward path is very clearly defined. I dont believe that globals should be used within library functions. The whole idea of libraries is to simulate a detatchment from the specific application code. The libraries act independdan....indepand....by themselves, and always require (in my apps anyway) a full set of variables passed to them, and they always return the full results. Surely this is a standard laid down long ago by external calls to system libraries in C (and others). It maximises the reuse of the libraries, and minimises the knowledge required about the library function being called. Within the non-library code, however, globals are a must. You may be correct in saying that tracking of changing local variable values is simpler (although I have never found it so), but the code produced by the overuse of local variables is difficult to maintain and a nightmare to learn. I'm sure most people have seen code where variables are constantly being passed from one function to the next, all with the same meaning, and all with slight variations in naming as each function gets its grubby little paws on them. >>> 2) Reusability of a module which only uses local variables is hassle-free. >> >>Again, there is no difference here. >>With local variables, you have to: >> >> 1. Pass the correct parameters. >> 2. Return the correct parameters. >> 3. Use the returned parameters. >> >>With global variables, you have to: >> >> 1. Set the correct global variables. >> 2. Call the function. >> 3. Use the global variables. >> Here the difference in reuse is a non issue, provided that the globals file being used in the "new" program is copied from the old. Most people have a globals "skeleton" included in each new program which contains the most common variables, and building additional sub-globals specific to each program type (report, enquiry blah blah) is simple excercise. After that, its pretty much a nobrainer to pick and choose the globals files required for each new program Having a sensible naming scheme for globals that can be destroyed at will, and globals that need a bit of checking, makes the process easier, and tracking is not difficult within a program regradless of how large the globals file ends up being. >Let's examine this further. Let's say I want to use a library function NOT >PREVIOUSLY IN USE in my 4gi. >If the function used globals, I would need to do the following > 1. Define the globals in the calling 4gl (copy and paste from library) > 2. If the global definition already exists (how creative can naming > be?), change the variable name in either my 4gi or (ouch!) in the > library AND RIPPLE THROUGH all other 4gls. > 3. Set the globals (using variables existing in caller) One of the blessings of using globals is surely that this step is already done if a lot of instances. There is no need to declare another variable and then set the global from it. Just use the global from the outset. There are certainly times when a global value has to be saved off to another variable for fear of data loss, but if this occurs all the time, then your global variable is almost certainly being overused and should be split into a more management number. > 4. Call the function > 5. Use the globals (possibly setting variables to them) > 6. If I've added the globals to a 'global.4gl', re-compile all other > 4gls using it. Again, the idea of globals shared between libraries and specific application code is a little scary, and yes, if you do it, your variables management is immediately complex. >If the function used locals, I would do this > 1. Copy & paste the library function FUNCTION stmt into the caller > 2. Change the parameter list to reflect the variables already in > existence within the caller > 3. Add a RETURNING statement using variables (usually already in > existence in the caller). Not sure what you mean here. Why would you copy&paste a library function into the program? Wouldn't linking the library module be sufficient? >>> 3) A common function RETURNing a local variable rather than seting a global >>> has a better 'handshake' with the caller. >> >>Again, I see no difference. The one advantage of globals over local >>variables is the fact that you always have to send the same number of >>parameters. With globals, if they are not going to be used on that call, >>then you don't have to set them. >Funny, here was I thinking that the fact that you had to send a specific set >of parameters was an advantage in favour of 'locals'. I see this >'restriction' as a built-in check (runtime & sometimes, compile-time) to >ensure that the function has all the required info. to do its job. I would Not really. The sensible use of globals ensures that a function always has the info it needs, and there is none of the "S**t, I forgot I need such and such. Now I've got to go back and change all the calling functions to include the extra variable." >be a little suspicious of a function which uses a varying number of variables >(probably doing too many things and needs to be simplified into multiple >functions), but you could alwayes pass nulls. >There is no such check for a function using global variables. I could happily >call a function without setting the globals or worse, setting the wrong ones. True, but the only reason to use a global is when it is to be shared between modules. This being the case, there are only two reasons to declare a global. 1) Variables that are destroyed constantly and you can never count on their value. These never "set" before being passed and each function makes it's own use of it and doesn't expect its current value to be maeningful. A classic example is a variable to hold dynamic sql statements. 2) Variables that are common and meaningful throughout the program. In this case, the current value is always "correct" and each function treats it accordingly. If a function needs to save off the value before calling the next function, it does so, but this is not usually necessary, and it saves the constant passing-down-the-line of values that are known throughout the program. Again, sensible naming tells you whats what. I use gp_* for permanent values and gt_* for perishables. >Here is an analogy to show the 'handshake'. >Local call : I call the Mailman (called function) and hand over a letter > and money (params) to him. When he returns, he hands over to > me the postoffic