I always get amused whenever the discussion on the NUG turns to the evils of global variables. Lacking a computer science background most of the discussions in this vain go way over my head. I am a self taught 4D guy who over the years, for reasons I know not why, have taken a minimalist approach to writing code. To me it is like going to the tool shed for a hammer. I always look for the smallest hammer that will get the job done...
No hammer = no variables Finishing nail hammer = local variables Regular hammer = Process variable Sledge hammer = Global variable The only reason I reach for the regular hammer is if for whatever reason I am unable to pass around my local variables either as parameter values or pointers. I rarely need to use the sledge hammer. I have found them useful for constants that are set at login, to provide a means for one process to report status back to the process that created it, or to store process numbers when multiple process are running at the same time and need to be aware of each other. As for globals used as constants, they are like that great set of tools hanging on my peg board. Rarely used but are always there in the same place should I need them. My point is that none of the hammers are evil nor should any “be avoided like the plague”. Each has a place in my tool shed. I have a very basic understanding as to why a global variable can be problematic. For this simpleton it is all in one’s overall approach to the task at hand… less is best. My 2 cents John > On Jul 20, 2017, at 10:22 PM, Nigel Greenlee via 4D_Tech > <[email protected]> wrote: > > Global Variables. > > Regardless of the relative merits of Arrays vs Object. I would like to relay > my dislike in general of Glol variables. I have been work with 4D since > before the concept existed-since 4D V2(Globals came in with V3). Yes i am one > of the old boys. > > Back then we did not have multiple processes and when V3 arrived we were all > amazed and in awe of the abilityich to have multiple processes and I think we > all went mad for interprocess(global) variables.(i think we all had singing > dancing palettes on the screen doing fancy things to update themselves from > other processes). > > Now if we were working in Javascript the concept of a global variable would > very much be considered something to be avoided like the plague. Global > variables are extremely useful but also extremely prone to problems, and over > the past couple of years-any javascript tutorial tells you to try and avoid > them, in 4D I have really cut down on my use of them. > > In my opinion a global variable should in general only be used for two things. > 1) You want to set a value(or group of values) and through the life of the > programme they do not change once set(so here you are using them like a > constant) > 2) You want to maintain an array that will be written to by multiple > processes. > > With point 2 you must protect the arrays with semaphores so only one process > alters the arrays at any one time-and often where these are used there might > be other ways to do it. > > I have just this week been dealing with 2 different structures where the > liberal use of interprocess arrays has lead to problems. Problems that do not > show up in testing and probably show that that the way the routines has been > used has changed over time. In both cases-different companies-different > programmers-different stuff an error shows up just occasionally. In one of > those systems discussion with the client shows that the usage of interprocess > variables has caused ‘strange’ unexplained un-investigated things to happen > where process A is changing the contents of <>Variable just at the point when > process B is about to send the contents of <>Variable that process B had set > to a document (‘sometimes we get a situation where the same order document is > created twice’!!)..and they have just restarted the machine to get rid of the > problem in the past(a practice that means you think the problem is 4D not the > way the code is written). > > Simply protecting the handling so only one process at a time can modify the > interprocess variables and arrays would have avoided all this. I suspect the > original programmer never intended the functionality to be running in > multiple processes at the same time and used interprocess arrays to (I think) > make it easier to display the data on a form that is in a different process. > Beyond the idea of a form in a different process i don’t see any purpose in > the arrays in this case being interprocess-they are being constantly changed > and as such should at best have been process arrays, In fact in a modern > context(this was written way before that) where we have been able to pass > pointers to local variables since 4D V11(??-maybe it was before that) I would > generally argue that programming using locals is much better-and that could > be local objects or local arrays. These really show that an interprocess > array was used for convenience where it was not really needed and changes to > code did not include a proper assessment of the impact-just because you can > do something and it works once does not mean it is tested or fit for purpose. > > In most of my code over the past few years I have moved so far away from <> > variables that if i have more than a few-maybe a variable holding the user > name or something like that which does not change(and even there I use a > function ..UTIL_GetUser(“Name”)..). I have even moved largely away from > process variables and arguable could move further from them by not using > variable names on screen objects. Convincing clients to let me change their > code and actually changing it is not easy-in one case about the changes to > the code are on a live system running uncompiled and this morning i am going > to be attempting to apply a knife to this code. > > > Most code i write now is ‘self contained’ -I attempt to set all values used > in the method is passed in to the code -either as parameters or an object or > a pointer to something so that i end up with something more like a javascript > function. Myreturn:=MyMethod(something;something;something). Using this style > of coding means i am far more likely to get an error if there is one EVERY > TIME rather than a head scratching randomly appearing one and my code does > not rely on the perceived value of a variable. > > Consider > > If(<>SOmething=1) > //do something > end if > > as soon as you have more than process where <>something is set you run the > risk that at some point process A will set <>something to 1 and before it > tests if <>something =1 process b changes <>something to 0 so you put a > semaphore to stutter your code.. > > if you write > > if(something=1) > //do something > end if > > //now process B can do whatever it likes with something and process A will > not be affected but you still run the risk that somewhere you call this > function before you have C_Longint(something) and something is not > initialised. Even if ‘something’ should be initialised to the value of > '<>something' this should be done at the start of the process and never use > '<>something’ in the code. When i find code that uses '<>something' or > ‘something'i have to look to see where something is set what changes it and > work out everything about it. > > if you write > C_LONGINT($something) > if(Count parameters>=1) > $something:=$1 > end if > > if($something=1) > //do something > end if > > You have code that is not dependent on the value of a variable it is only > dependent on a value being passed in, and that might mean that the calling > method also can use a local. This means i only need to see where my code is > called and check that it is passing a relevent value to the code-much easier > to track down a fault. > > This is a simple ‘one step’ example but I frequently see code chains like > this. > > Methoda sets var-calls-method b-calls-method c-calls method d-and method d > has if(var set in method a), and that is really where this chain of handling > becomes a mess-we have method and the variable is set 3/4 levels up or worse > set at startup in the code. > > If you pass an object the concept can become of course much more flexible, > and slowly i am trying to adopt an object passing approach > > C_OBJECT($Something) > If(Count parameters>=1) > $Something:=$1 > end if > > if($Something.setting=1) > //do something > end if > > Becomes much easier to read(no unpacking the object here). > > After all its used extensively in javascript where passing json normal and > with V16 now using dotted notation for getting at object item is a big > encourement to utilize this(yet to test that out myself). > > > > Are other people taking this approach to the use of variables. How easy are > you finding it retro-fitting it to existing code? > > > Nigel Greenleee > > > > > >> On 18 Jul 2017, at 16:29, Chip Scheide via 4D_Tech <[email protected]> >> wrote: >> >> Long ago - and I am pretty sure the code has been lost to time - >> in v2.2.3 (I think) I wrote code to do binary searching on a selection, >> as at that time Search Selection (the old command name) was sequential, >> but sorting the selection was indexed. >> >> Even with the overhead of managing the pointers, and stepping through >> records to find all matching records in the selection, as memory >> serves, it was faster (interpretedly) to use the binary search on a >> selection size of beginning at 6-8 records. >> >> For those who care, an outline of a binary search (on records in >> selection) >> The following was written off the stop of my head, in the email editor, >> BUT it gets to the basics of a binary search on a selection in 4D. >> >> - get size of selection ($Selection_Size). >> - make sure it is sorted on the field you want to search on. >> >> repeat >> $Current_record:= int($Selection_Size/2) >> >> repeat >> goto selected record([table];$Current_record) >> case of >> :($Current_record>=$Selection_Size) or ($Current_record<=1) >> $Not_Found:=true >> :([table]field = Value) // found it create collection of >> matching records >> add to set([table];"Matching") >> $previous:=$Current_record >> $Next:=$Current_record >> >> repeat >> $previous:= previous-1 >> goto selected record([table];$previous) >> >> if ([table]field = Value) // found it create collection of >> matching records >> add to set([table];"Matching") >> else >> $previous:=0 >> end if >> until($previous=0) >> >> repeat >> $$Next:= $Next+1 >> goto selected record([table];$Next) >> >> if ([table]field = Value) // found it create collection of >> matching records >> add to set([table];"Matching") >> else >> $Next:=Selection_Size >> end if >> until($Next= Selection_Size) >> $Mo_More_Matches = true >> :([table]field > Value) // Not found current record value > >> search value >> $Current_record:=int((1+$Current_record)/2) >> :([table]field < Value) // Not found current record value < >> search value >> $Current_record:=int((Selection_Size+1+$Current_record)/2) >> end case >> until ($Not_Found)) or ($No_More_Mathes) >> >> At this point the set "Matching" contains all records matching the >> criteria, or nothing. >> >> On Tue, 18 Jul 2017 22:16:18 +1000, David Adams via 4D_Tech wrote: >>> >>> And, lest anyone forget, you can use binary search logic on sorted >>> selections with GOTO SELECTED RECORD. Why not? >> --------------- >> Gas is for washing parts >> Alcohol is for drinkin' >> Nitromethane is for racing >> ********************************************************************** >> 4D Internet Users Group (4D iNUG) >> FAQ: http://lists.4d.com/faqnug.html >> Archive: http://lists.4d.com/archives.html >> Options: http://lists.4d.com/mailman/options/4d_tech >> Unsub: mailto:[email protected] >> ********************************************************************** > > ********************************************************************** > 4D Internet Users Group (4D iNUG) > FAQ: http://lists.4d.com/faqnug.html > Archive: http://lists.4d.com/archives.html > Options: http://lists.4d.com/mailman/options/4d_tech > Unsub: mailto:[email protected] > ********************************************************************** ********************************************************************** 4D Internet Users Group (4D iNUG) FAQ: http://lists.4d.com/faqnug.html Archive: http://lists.4d.com/archives.html Options: http://lists.4d.com/mailman/options/4d_tech Unsub: mailto:[email protected] **********************************************************************

