BreakPoint

cancel
Showing results for 
Search instead for 
Did you mean: 

Are globals really THAT evil?

Even in text based programming concepts like encapsulation and abstraction tend to discourage the use of global variables: it seems that the ideal structure is the one for which if a function needs a variable it must receive it from the caller. Nevertheless, even in these environments there indeed is a limited and reasonable use of global variables, mostly in the concepts already depicted here: one writer-many readers or in general for elements generally used throughout the whole program and not subject to change.

I always stayed in this path: a configuration function at program start or a "parameters setting" function run when no process is running and no acquisition is in progress define a proper set of globals that are sort of framework for the rest of the applicaton. This general concept is reasonable and can be inherited in whichever programming environment we are using.

On the other hand, while it's obvious that the world is NOT black-and-white, I understand that the first approach to a language can be nearer to that end, maybe leaving a gradual approach to grayscale- and color- view to a following step, the usual "Advanced programming techniques" chapter of manuals. In this respect I can understand that there be some sort of criticism against globals to limit the potential risks connected to their (ab)use, but I consider this as part of a general criticism against bad code: a correctly used and well documented global can have an honourable place in a good application!



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Message 11 of 89
(14,255 Views)


tst wrote:

tbob wrote:
When using producer consumer and queues (I prefer queues to variables also), timing can still be an issue.  The consumer loop can run faster than the producer and you could try to dequeue from an empty queue, so you sometimes have to check for this.

When I do that I either use the default -1 timeout, which means the loop won't iterate if there's no data, or check the timed out? terminal. That was why I specifically mentioned a single writer where you will always want only the latest value and I don't care if I lost intermediate values. I was rethinking this because of an application I'm doing now which constantly reads a single piece of data from a serial device. The VI talking to the device runs all the time and puts the most current data into the global and other VIs needing the data can read it from the global - single producer, multiple consumers and no data lost.


I'm developing more of a habit of using Notifiers for situations with multiple consumers.  Usually there's just one producer, but in cases like a "global" shutdown notification, there may be several potential producers.

With Notifiers, your consumers have options.  They can retrieve the most recently updated value, whether or not they've already consumed it previously.  This is just like a global.  Or they can wait for un updated value without bogging down CPU or polling.  This you can't do with a global.  A queue can only do this with a single consumer.

They're also useful for setting up a protocol to launch little processes with VI server.  The little process will create a named notifier when it starts and destroy it when it completes.  The calling program can launch the process (Run VI with 'Wait Until Done' = F), then enter a loop where it tries to retrieve the named notifier with 'Create if not found?' = F.  When it succeeds in finding it, I know the launched process has actually started.  Later when the launched process destroys the Notifier, all 'Wait on Notification' and other subsequent calls will return immediately with an error.  This informs the app that the process has completed.

Lately I keep finding a good use for an architecture where I have a single process performing all the data collection from data acq boards or external instruments.  Here the data is written to both a Notifier and a Queue.  A file storage process is the single consumer of the Queue'd data, but there may be multiple user displays that are consumers of the Notifier data.

Of course, I sometimes still use a (LV2-style) global to define the *name* for the Notifier...

Back to topic: I think that overuse of globals is a much more real and present danger than underuse.  IMHO, any standard text should largely advocate the various alternatives to globals, with their various pros/cons/quirks.  I'd save the discussion of real global variables until near the end of the text.

-Kevin P.

ALERT! LabVIEW's subscription-only policy came to an end (finally!). Unfortunately, pricing favors the captured and committed over new adopters -- so tread carefully.
Message 12 of 89
(14,247 Views)

Sorry about coming in late on this topic. I can not elaborate to much but here are my main concerns.

1) Data copies

2) Thread usage

3) They are "OK" if single writter and multi-reader BUT this forces the developer to make SURE there is only one writter. This is rough when your app's climbs up over 800 VI's some of which are dynamically loaded.

4) Flexibility. If you start with a LV2 you are safe to add another writter if required. In large app this could be  a real headache.

5) Performance. A LV2 can re-use buffers. Globals can not.

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 13 of 89
(14,224 Views)

The LAVA forum has a FAQ on LV2's that can be found here.

http://forums.lavag.org/index.php?showtopic=273

They touch on some of my points listed above.

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 14 of 89
(14,193 Views)
I agree with many comments.
 
I typically use Globals as a holder of static values, such as IP addresses.
I wouldn't call Globals evil, as I do use them... Unlike their evil cousin "Local Variables".... 😉
Message 15 of 89
(14,174 Views)

Hi tst,

Have we heard enough on this topic?

How would you like to proceed from this point?

Ben

 

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
Message 16 of 89
(14,150 Views)

Has it almost been a week already? Smiley Surprised

Anyway, here's an initial draft for a standard text we can use. I will be happy if people add/modify it, but I only request that it be done by using a font of a different color to make it clear where the changes were.


There are several ways to pass data between VIs.

First, you can wire data through the connector pane. This is the most efficient method, the safest and the easiest to understand, but it does not help when you want to pass data to the VI while it is running.

Second, there are the built in LV global variables. This is the fastest way to transfer data between VIs, and it has the benefit of making it easier to find the places where you manipulate the data. The main isadvantages are that globals create a copy of the data for each global and that they are prone to race conditions. Also, when reusing code, the files holding the globals need to be probably structures to make it easy to move the code.

Third, there are the LV2 globals (named after the version in which they were introduced), also known as functional globals or USR globals. These are made of a subVI with a loop which only iterates once. This loop has an uninitialized shift register (USR) which has an important property - it holds the value put into it between different runs. If the VI is not reentrant, it can be called from multiple places and they will all share the same data. The advantages are that only one copy of the data is made and that it has some locking built in.
Another advantage is that these can be enhanced by adding additional code in them, and this is very useful because the VI can hold its own data.

Fourth, there are queues (in the advanced palette, along with some other synchronization tools). The basic queue has the advantage of keeping all the data which is produced. Other than the regular usage of the queue, it can also be used as a standard global by creating a queue with a single element. If each call to the queue starts by removing the element to the queue, every other place calling the queue will have to wait until the first caller places the modified element back into the queue. These are faster than LV2 globals, but slower than regular globals.

Points for consideration when using globals -

1. Breaking the data flow. This is an important point, as it will make it harder to understand your code and also harder to debug it.

2. Race conditions. An extension of the last one. When writing from multiple places, it is easy to run into a case where you lose data. This can also happen if you expect data to be available and it hasn't been written yet.

So, which global is appropriate where?


I don't feel like writing the last part at the moment.

Other additions might be a reference to shared variables and maybe a link to the LAVA FAQ. Molly can obviously add it to her FAQ as well.


___________________
Try to take over the world!
Message 17 of 89
(14,118 Views)

Ben wrote:

Sorry about coming in late on this topic. I can not elaborate to much but here are my main concerns.

1) Data copies

2) Thread usage

3) They are "OK" if single writter and multi-reader BUT this forces the developer to make SURE there is only one writter. This is rough when your app's climbs up over 800 VI's some of which are dynamically loaded.

4) Flexibility. If you start with a LV2 you are safe to add another writter if required. In large app this could be  a real headache.

5) Performance. A LV2 can re-use buffers. Globals can not.

Ben


I am bumping this thread because I saw someone say that globals are not evil.

 

Globals are so dangerous to large app development and future enhacements that I fell justified in beating this old drum again.

 

Globals are evil, globals are evil,...

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 18 of 89
(12,455 Views)

A here is yet another issue from the "Global Protection League" 

 

For a case study of how even a simple use of globals can kill an app see this thread where I never did get a good answer as to why one global would read slower than another.

 

No you don't have to listen to me but I am obligated to warn you.

 

Ben

Retired Senior Automation Systems Architect with Data Science Automation LabVIEW Champion Knight of NI and Prepper LinkedIn Profile YouTube Channel
0 Kudos
Message 19 of 89
(12,452 Views)

Ben wrote:

Globals are evil, globals are evil,...


Count me in as a devil worshiper then. Smiley Very Happy

0 Kudos
Message 20 of 89
(12,443 Views)