Global Variables.

Regardless of the relative merits of Arrays vs Object. I would like to relay my 
dislike in general of Global variables. I have been working 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 ability 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]
**********************************************************************

Reply via email to