06-14-2006 10:35 AM
06-14-2006 11:02 AM
Globals are great in certain circumstances. If I have static data that must be shared between lots of VIs in my application, I'll use a global to store that data. The most common example is user-visible strings...If I have a pretty complex GUI that displays messages to users all over the place, I have a single global VI with all those strings, arranged on the panel of the global in alphabetical order (by setting the tab order, I get a nice alphabetized list when dropping the global on a diagram and selecting the control I need). This also makes it really easy if we localize this app, since there's a single VI that can be localized, instead of user-visible strings being scattered all throughout my app.
Another time I use globals is when I have a simple subpanel architecture where communication with the host VI is not required. In these cases, the VI in the subpanel updates a global variable, which is then read later by other parts of my app. Since no synchronization is required, and I always have one writer, globals are the way to go.
In my opinion, the time when globals should be avoided is when there are potentially multiple writers to the global. In these cases, the potential for race conditions is too great to risk significant debugging time in the future when things just stop working correctly.
-D
06-14-2006 11:24 AM
06-14-2006 12:02 PM
I am glad to see someone else besides me is willing to shed some light on the proper use of globals rather than just saying to avoid them completely. More emphasis on the proper use of globals should be given rather than the old "I'm afraid to get in trouble so I'll never use them" approach. Education is the key. Teach how to properly use globals, teach how race conditions are created and what to do to prevent them (besides avoiding globals).
I use globals mostly as constants. Like holding the values of GPIB addresses. They are created and never written to again. No possibility of race conditions here. Or producer consumer architecture, producer writes to the global, consumer reads it. In this scenario, timing is important so as to have the consumer check to see if the latest read is different from the previous read. In other words, the consumer can read twice before the global is updated, and this may not be desirable.
I feel the same way about local variables. There is a place for them, but care has to be taken to not have a problem. Teaching and understanding the problems that could arise and how to avoid them is the best approach by far, rather than just advocating a total ban on locals and globals.
06-14-2006 12:21 PM
06-14-2006 12:29 PM
06-14-2006 01:00 PM
@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.
06-15-2006 01:52 AM - edited 06-15-2006 01:52 AM
Message Edité par TiTou le 06-15-2006 08:54 AM
We have two ears and one mouth so that we can listen twice as much as we speak.
Epictetus
06-15-2006 02:05 AM
@TiTou wrote:
Are they THAT evil... I would answer : no, as long as you know the trick they can play...The point is that you have to know how they work to use them appropriately 😉
Use them but don't abuse them
Perhaps I was mistaken in the way I presented this. This came up following some thinking I did because of something I'm working on, and so I only presented the topic of what we tell users as a side issue. Since there now seems to be a general consensus here that globals are not THAT evil I think we should now move to the part where we create a standard passage which explains the topic properly and which people can put into their macro section.
I think this is important because we should not be telling new users "don't use it because it's dangerous" (which is very easy to say), because then they will end up either never using it or ignoring what we say and deciding we're not to listened to. Instead, we should take the harder route of clarifying the dangers and advantages (and the alternatives) and letting people make their own decisions. This thread seems to be a good place for this discussion and maybe I'll start putting something together when I have some time for it. I think that we can come up with a good passage in under a week.
06-15-2006 02:21 AM
Oh yes ! Once a week, just like Darren's nuggets !
tst a écrit:
This thread seems to be a good place for this discussion and maybe I'll start putting something together when I have some time for it. I think that we can come up with a good passage in under a week.
We have two ears and one mouth so that we can listen twice as much as we speak.
Epictetus
06-15-2006 08:46 AM
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!
06-15-2006 09:14 AM
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.
06-15-2006 01:57 PM
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
06-16-2006 11:39 AM
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
06-17-2006 09:56 AM
06-19-2006 08:05 AM
Hi tst,
Have we heard enough on this topic?
How would you like to proceed from this point?
Ben
06-20-2006 12:42 PM
Has it almost been a week already?
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.
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.
04-23-2010 08:21 AM
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
04-23-2010 08:28 AM
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
04-23-2010 08:52 AM
Ben wrote:
Globals are evil, globals are evil,...
Count me in as a devil worshiper then.
04-23-2010 09:02 AM
smercurio_fc wrote:
Ben wrote:Globals are evil, globals are evil,...
Count me in as a devil worshiper then.
Quoting myself from above;
"
No you don't have to listen to me but I am obligated to warn you.
"
Ben
04-23-2010 12:10 PM
I will repeat what I said a few weeks ago. Globals are NOT evil. Improper use of globals IS evil.
I have developed large apps in the test and measurement world. I use Globals to hold the GPIB address of all the instruments and the PXI names of all the PXI cards amongst other things. These globals NEVER get written to. Always read only. Now what exactly is evil or wrong with this use. Ben you are speaking from the perspective of your world. There are many different situations out there. In my world, Globals are sometimes a great necessity that makes programming much simpler. I equate my use of Globals to the use of Constants in C.
04-23-2010 01:51 PM
Ok.
I have softened my warning statement a bit but it still feels like I am leaving matches laying around.
Ben
04-23-2010 03:02 PM
Ben wrote:Ok.
I have softened my warning statement a bit but it still feels like I am leaving matches laying around.
Ben
Sometimes matches serve a purpose. I do agree that a stern warning should be provided with the use of Globals and Locals. I have been bitten before by the race condition syndrome, learned it the hard way. In my opinion, the only good use for Globals is as a Constant (read only).
04-26-2010 11:47 AM
In the odd condition that I would use Globals, I use them in the same way as tbob does.
Usually, they are used ONLY if they were previoulsy used in that manner by whoever wrote the original code.
I tend to use xml files to hold the configuration data instead of Globals.
04-26-2010 12:14 PM
I have used ini files and config files to hold config data, but it is cumbersone and slow to read the files every time I want to get a GPIB address of an instrument. If I use the files, I usually read the file at the beginning of the program and store the data into a Global worm (write once read many), or when using a state machine, in a local variables cluster.
04-26-2010 12:19 PM
I thought about this this week-end.
WORM globals - (Write Once Read Many) globals are a safe use of globals provided you and only you are the developer and you remember that you used globals and already used-up your allotment of write globals.
Ben
04-26-2010 12:26 PM
Ben wrote:I thought about this this week-end.
WORM globals - (Write Once Read Many) globals are a safe use of globals provided you and only you are the developer and you remember that you used globals and already used-up your allotment of write globals.
Ben
A very practical thought, Ben. I would never use Globals in any way other than as constants or worm globals. The trick is to get others, those who might inherit your code, to do the same.
Has anyone coined the term Worm Globals yet? Or did I just invent something new?
04-26-2010 12:33 PM
tbob wrote:
Ben wrote:I thought about this this week-end.
WORM globals - (Write Once Read Many) globals are a safe use of globals provided you and only you are the developer and you remember that you used globals and already used-up your allotment of write globals.
Ben
A very practical thought, Ben. I would never use Globals in any way other than as constants or worm globals. The trick is to get others, those who might inherit your code, to do the same.
Has anyone coined the term Worm Globals yet? Or did I just invent something new?
I'll call it yours. Maybe its time to spice up your signature.
"Inventor of the WORM Global" with a link to this thread.
Ben
04-26-2010 12:53 PM - edited 04-26-2010 12:54 PM
Ben wrote:
I'll call it yours. Maybe its time to spice up your signature.
"Inventor of the WORM Global" with a link to this thread.
Ben
Like this?
How do you point to a particular post instead of the first one on a page?
04-26-2010 01:02 PM
tbob wrote:...
How do you point to a particular post instead of the first one on a page?
Message Edited by tbob on 04-26-2010 10:54 AM
Good! It about time you build-up your "brag-list".
I can't say it works but what I do is...
1) Click on the number under your icon for the post you want. The screen will update and somewhere in the URL is will record the post #.
2) NOW copy the URL and prceed as normal.
Ben
04-26-2010 01:06 PM
Yep. That works. Thanx, Ben. I'm simply amazed at the fact that I seem to learn something new every day here. What a great group of guys.
04-26-2010 02:46 PM - edited 04-26-2010 02:47 PM
Ben wrote:I thought about this this week-end.
WORM globals - (Write Once Read Many) globals are a safe use of globals provided you and only you are the developer and you remember that you used globals and already used-up your allotment of write globals.
Ben
But how many times have you thought you were that person, and it ended up not being the case? Since Notifiers, lossy Queues, and AE's are so easy to use, I just don't think I'm on board. That global will be misused by someone. (Matches laying around )
04-26-2010 02:50 PM
04-26-2010 02:53 PM
Time for another idea submission...
Who gets this one? Broken Arrow or wormy tbob? 😉
04-26-2010 02:55 PM
Broken Arrow wrote:
Wait a minute. How about a true WORM Global that only allows one write? Subsequent writes cause a Broken Arrow.
Impossible due to the ability to dynamically load VIs.
In the past I've suggested a global read-only VI which would include a diagram which would run once when the code starts running, but this suggestion has its own issues.
04-26-2010 02:58 PM
tst wrote:
Broken Arrow wrote:
Wait a minute. How about a true WORM Global that only allows one write? Subsequent writes cause a Broken Arrow.Impossible due to the ability to dynamically load VIs.
In the past I've suggested a global read-only VI which would include a diagram which would run once when the code starts running, but this suggestion has its own issues.
I think it's a pipe-dream, but couldn't the global be registered on the computer? You would never even be able to name another Global the same again!
04-26-2010 04:12 PM
tst wrote:
Impossible due to the ability to dynamically load VIs.
That thought crossed my mind when Broken Arrow mentionned "broken arrow".
Now, maybe the folks at NI can come up with some sort of locking mechanism (not necessaruly a semaphore) that would allow to change once and then it is read-only.
It certainly would be a nice feature and then we would say Globals are good.
They do have a function called "First Time?", so maybe they could implement it using some similar mechanism.
Now back to Broken Arrows suggestion...
I was thinking that he meant that if you use a global variable and wrote to it somewhere in the project that the next time you select the global and tried to wire to it, it would give you a broken arrow and a broken wire. I don't know how that could be implemented, but we've seen other rabbits being pulled out of a hat, so maybe it is not so impossible to implement.
04-26-2010 04:36 PM
Well, C/C++ has constants. Why can't LV have constants in the form of Globals which cannot be written to from any block diagram. You would be able to create the Global variable using the standard method. All globals could be changed in the Global VI by the developer. But those globals would be read-only anywhere inside any block diagram. The Change to Write would be greyed out. It is not a WORM Global, but it would be a constant. 99% of my global uses are like constants. More people would use them if they were not writeable, and they are so much more easier than using Queues, Notifiers, or AEs.
04-26-2010 04:52 PM
tbob wrote:Well, C/C++ has constants. Why can't LV have constants in the form of Globals which cannot be written to from any block diagram.
You mean like this?
04-27-2010 07:00 AM
That's the idea..
See how great minds think alike.. It is possible to make a Global WORM, call it a CONSTant.
<punt ON>
Would it be referred to as "Global WORMing?"
<punt OFF>
04-27-2010 07:33 AM
Isn't this kind of easy to do with LVOOP?
A write function which allows only a single execution, otherwise returning an error?
Shane
04-27-2010 07:49 AM
Intaris wrote:Isn't this kind of easy to do with LVOOP?
A write function which allows only a single execution, otherwise returning an error?
Shane
I don't remeber which thread I posted this image too but YES!
Ben
04-27-2010 09:08 AM
Time for a Nugget guys....
04-27-2010 09:23 AM
Ray.R wrote:Time for a Nugget guys....
Owww!
Are you writing one?
BTW: Shared Variables have a single writer option.
Ben
04-27-2010 10:31 AM
Although I like the LVOOP idea, Globals as they are satisfy my need for constants, so I won't go through the trouble of creating a WORM Globabl using LVOOP. Well I might one day when I have some time on my hands (like next week). For me its OK the way it is because I am keenly aware of the troubles of misusing Globals. I have disciplined myself to never write to a Global in a block diagram.
But I like the idea of a WORM Global because I would be able to load the Globals from an ini file at the beginning of each program. This would really be a great feature.
04-27-2010 10:31 AM
Ben wrote:
BTW: Shared Variables have a single writer option.
Then that's the way to go if you want to do this.
BTW. How about a new feature where Local and Global variables can not be placed on the block diagram until you have two years of LabVIEW experience?
04-27-2010 10:41 AM
Broken Arrow wrote:
Ben wrote:
BTW: Shared Variables have a single writer option.
Then that's the way to go if you want to do this.
BTW. How about a new feature where Local and Global variables can not be placed on the block diagram until you have two years of LabVIEW experience?
There was an early version of LV where NI tried a "just in time help" function that was borderline as anoying as Clippy from MS.
I think that there should be a EULA associated with every instance of a write global that we have to agree to and Ni keeps on file.
Ben
04-29-2010 04:41 AM
I like these WORM globals. Two implementations come into my mind.
* LV2Global with the First Call prim to load the values from a ini file
* Using a SEQ with an enqueue as write (with timeout 0) but a preview for read
But I must confess, that I really do use those evil globals to pass data around. It's duct tape I use to fix things in the field. And I am very happy if I have the time back home and remove them again...
Felix
04-29-2010 05:28 AM