I just realized that people are looking at these VIs and planning to use them for something entirely different from what I had assumed. What I saw as a useful tool for good I realized could be turned to darkness in the wrong hands.
If you haven't heard my position on by-reference data in LV before, it is this: References sometimes necessary -- rarely, and only in well-defined situations with extreme limitations on their use. I do not claim that references are always bad; I do claim that they are overused by today's LV programmers and generally references create many more problems than they solve. And, no, I don't think users are stupid. I think most references are dangerous in the most experienced hands, mine included. Now back to the topic at hand....
For sure references are harder to get right than by value/dataflow, but references enable us to do much more complete encapsulation and thereby code reuse. And belonging in the hard departement of programming is alot of other very useful stuff like inheritance, reentrancy, events, dynamic dispatching, polymorphism, recursion etc. I must say that I use all these techniques leisurely, and wouldn't want to go back to when they didn't exist (in LabVIEW nor in any other programming language). I also think I understand these techniques well enough to not be afraid of them, on the contrary I constantly find new uses for them.
I'm not sure how VIRegister classifies as a by reference component. What I need is an easy way to transfer signals (not data, since VIRegisters are lossy) between code segments that can't be connected by dataflow, e.g. parallel structures or even (sub)VIs. I most often use queues or events for this type of signalling. Named queues are convenient, since I then can skip the step of fetching an event refnum from some global storage. Since I don't want the restriction of purely hardcoded names, I combined the user supplied queue name with the VI instance name. Nothing new here, just fancy dressing for what NI (and common sense) recommends as signal transfer medium between the structure types I outlined above.
As I said, I have built for my personal use VIs that are fairly similar to these. And mine have a string input for "queue name", just like these do. But when I use my VIs, the name is ALWAYS wired with a constant. ALWAYS. They're full reentrant and store the underlying refnum. If I ever released the VIs, I'd probably add an assert that the name passed on each successive call was exactly the same name as the previous call and return an error if that wasn't true. In fact, if I ever got ambitious enough, I'd probably make "name" something to configure on the node, not an input.
That was my expected use case too, which is the reason for the 'release queue' bug in v1.0 of the VIRegister toolset - I didn't expect anyone to run through a list of register names in a loop, using the same VIRegister instance. That was also why I suggested a couple of posts ago to enter the register name into the node itself, but the official LV IDE does not allow me to create such a node - only stuff that fits within 32x32 pixels with a static icon (with a few exceptions). But why not allow the reuse of the node, with the name as input? It's not any different from the way we create hundreds, or even thousands, of queues or events.
I never really considered that someone would look at these as an API for creating a misbegotten by-reference lookup-table. I always forget that various people keep trying to strip LabVIEW of its major assets by turning it into a mush of procedural, by-reference code. Wired with a constant, VIs like this can become a great addition to LabVIEW. Debug tools can be built to track the start and end points of these "off diagram wires". And there a number of code correctness proofs you can apply. Wired with a non-constant, they introduce code maintenance problems that are very hard to debug.
Once you've tried to debug reentrant VIs on a Real-Time system you stop complaining about things-hard-to-debug
. No, seriously, sure they are harder to debug. One of the biggest advantages of dataflow programming, and therefore one of the major reasons for the popularity of LabVIEW when people get introduced to it, is how easy it is to follow the data around ("debug" it). It's also the Achille's heel of LabVIEW. I can't keep track of how many times I've been called in to rake experienced programmer's b*lls out of the fire because they've painted themselves into a corner with LabVIEW. "LabVIEW is so easy" they were told by the NI sales guy. BUT, any of the features I mentioned at the top of my post, well basically anything non-dataflow, is hard like that. And again, I don't see how VIRegister differ from ordinary named queues in this regard?
I know I'm not a full-time G programmer. I do theory more than practice when it comes to G. Those of you who actually have to produce working G code for your jobs are right to be suspicious of my opinions on topics like this. Most of the time, when someone who works G full time tells me they really need XYZ, I pay attention and try to see how LV could provide for that need. But when I read things like this idea -- Globals that can be created during run-time and accessed by name (i.e. native Current-Value-Table/VIRegisters) -- I just can't in good conscience help. That sort of architecture just should not be necessary. It might work. It might even work well sometimes. But my theory is that it will never work as well as building software that solves the problem in a more dataflow-like manner, and when it doesn't work, it will be much harder to figure out why than the comparable dataflow architecture. I really wish that all the time poured into tools to support references over the years could be poured into really nailing down dataflow-like architectures that scale. I know they exist.
I don't think you have to put hide your light under a bushel when it comes to G
. I usually tell people that LabVIEW is just syntax. Implementation may differ in the detail, but so does sunlight and shade, or the good idea, from day to day. Inside my head I don't see anything else but when I program in C++ for instance. I just have to do something different with the mouse and keyboard to make an application out of it. I agree that people with less experience sometimes take the sharpest tools and get hurt, but that doesn't mean the sharpest tools shouldn't be available - but maybe they should be licensed in some way?
. So, no, references are king (ever try TestStand?), but that aside I still don't see VIRegister as anything but a mighty fancy wrapper of named queues (did I mention that?).
I'd like NI to put this into LabVIEW, but with the ability to enter the name directly into the node. This just to get rid of the unnecessary input to make it even cleaner, alas you then lose the ability to create the name programmatically (you will probably then be able to set the name with a property node, even though I'd expect such a feature to cost extra because it'd only be available through a module like the DSC-module). I'm not too fond of the blocking-FG limitation of CVT, VIRegister is simply without these limitations; Shared Variables (which I still need to spot a decent use case for) needs the project for configuration and drags the SVE around, Locals are tied to the FP, Globals are tied to a file... I hate that. Well, VIRegister is tied to the queue name lookup table, but at least that's transparent to the programmer, and lives in the same code space as your VI, and it has worked fine over the years.
But of course, in the spirit of the main topic of this year's CLA Summit, we shouldn't headlessly create new communication APIs. So, implement VIRegister and TCPIP-Link, keep queues, events and locals - ditch the rest
(notifiers can stay too, but they are more like the evil cousin to VIRegister anyway).
Edited by Steen Schmidt, 30 June 2011 - 08:57 PM.