Jump to content

LabVIEW constant values change


Recommended Posts

I found a problematic issue with the behavior of LVOOP class constant values. LVOOP constant values get cleared when the default default value of the class private data is changed to the same value as the constant value.

Let's make some definitions:

Class default value: The default value of class private data

Default value class constant: LVOOP class constant, that has a specific default value flag. The constant behaves as by-reference object that refers to the class default value global. When the class default value is changed, the default value class constant is changed in synchrony.

Non-default value class constant: LVOOP class constant with non-default value. The value behaves as any by-value object. It has its own value that does not depend ony the default value of the class, except in the problematic case described below. The LVOOP class constant can get a non-default value when you paste a previously copied value to it using Data operations -> Paste from shortcut menu.

Class developer: An organization or developer that is responsible for developing and maintaining a class.

Class user: An organization or developer that is using the class developed by some class developer.

Consider National Instruments (class developer) has developed a class representing an IP connection to some IP address. Internally the class represents the IP connection with a IP address string constant in class private data. NI has initially set the "default value" of the class private data to be 0.0.0.0. Assume you (class user) as a non-NI developer have used a class constant of this connection class labeled loop back on block diagram and the value of it is non-default 127.0.0.1 representing a loop-back connection. Now NI decides they want to change the class default default value from 0.0.0.0 to 127.0.0.1. The issue here is that this change by NI will clear the value of your non-default value block diagram class constant and replace it by a default value class constant.Now NI decided that 127.0.0.1 is not a good default default value for the connection class and sets it to be 0.0.0.0 again. How this affects your program. Well, LabVIEW will not recover your initial value to your loop back class constant, i.e. 127.0.0.1, but instead keeps the default value. As a result, your loop back class constant no longer represents a loop back connection but a connection to non-existing IP-address 0.0.0.0. The behavior I expect would be that the value of loop back class constant on block diagram would always remain 127.0.0.1, even when the class private data default value is changed to the same value.

You can replace the roles NI and you with you and your client. The issue here is, the constant values should never be cleared. If they really need to be cleared for some reason such as the class private data having changed structure, LabVIEW should definitely warn the developer that the constant values may no longer represent the data they used to.

What happens here really is that when LabVIEW notices that a non-default class constant has the same value as the default value of the class, it replaces the constant value with a reference to the default value object. So the constant no longer is a constant representing its initial state but becomes a constant that stays in synchrony with the default value object. Once the default value object is changed, the constant value will also also changed.

I think that LabVIEW should follow the principles below

Theorem 1: A block diagram constant with a non-default value should always represent the same state that it initially had, irregardless of what changes has been made to the default value of the private data.

Initially a red apple should always stay a red apple and not implicitly become a green apple even though the default color of apples is changed to green. This is what is currently happening in LabVIEW. Apple block diagram constants explicitly specified to be red apples are turning into green apple constants under certain changes of the default value of the class private data.

Theorem 1 is broken by the fact that class constant state can change from red to green apples.

Theorem 2: Initial and final revision of a class A,call them A1 and A3, are identical, but an intermediate state of class A, call it A2, is not identical to A1 and A3. Code compiled using class revisions A1 or A3 should execute identically irregardless if the code has been compiled against intermediate state A2.

Theorem 2 is broken as you can revert the class to its initial state, still the changes in the class between initial and final state change the code using the class.

Theorem 3: There should be no difference if code using a class has or has not been in memory when editing a class, if the class interface does not change.Once the code using a class is loaded in memory together with the latest revision of the class, the code should be updated always to the same state.

Theorem 3 is broken as if code has been loaded in memory when a private data default has been changed twice, then the state of the code is different than the state of the code that has only been loaded into the memory when the class has reached its final state.

So what I propose is that a class constant always has either a default value or a non-default value. The non-default value can equal to the class default value, but as far as the constant is concerned, the value is still called a non-default value. That is the value of a constant does not change from a by-value state to a by-reference state, unless explicitly changed by the class user. When the default value of the class private data is changed, the values of block diagram constant remain untouched. That is constants that already contain default value still contain the default value in the future. The constants that contain non-default value still contain a non-default value even if the new class default value equals to the constant non-default value. The important thing here is that the constant with non-default value has been explicitly set by the developer to be at some state and this state should be persistent no matter what (possibly another) developer does with the default value of the class private data. Once you paste data to a constant, it automatically gets a non-default status. The same would apply to indicators, once LabVIEW have written data to an indicator(control), the value of the indicator (control) would be non-default irregardless if the value actually equals to the class default value. Only when you want to clear the value back to the class default value, there could be a right click menu option Data Operations -> Reset to class default value.

Let us take still another example of the current behavior. We are developing an natural number class. Initially we set the class default value represented by integer to be 0. We add a method +1 to the class and implement it by adding a class constant with non-default value 1 together with input data using another class method Add. We then accidentally change the default value of the class private data integer to 1. Accidentally! This clears the non-defaultness from out constant on +1 method block diagram. The constant gets the flag default value. Now we immediately notice out accidental mistake and correct the mistake by returning the default value of the class to0. Immediately. But the harm has already been done. The +1 method no longer functions as expected but now becomes +0 method instead. Is this really what we want? No warnings. Nothing. Just somewhere under the hood things implicitly change and we know nothing at all that we just broke our code.

Everything that here applies to class constants applies to class controls and indicators, I think.

I want to raise discussion. Should current behavior be changed in LabVIEW or do you think the present behavior of class constants is correct?

  • Like 2
Link to comment

I want to raise discussion. Should current behavior be changed in LabVIEW or do you think the present behavior of class constants is correct?

Not much to discuss... you've laid out your case very well. I can see how the current behavior would lead to very nasty bugs.

Unfortunately it has gone unanswered on NI's forums

Someone at NI must have read your comment and lit some fires. laugh.gif

Link to comment

Internally the class represents the IP connection with a IP address string constant in class private data. NI has initially set the "default value" of the class private data to be 0.0.0.0. Assume you (class user) as a non-NI developer have used a class constant of this connection class labeled loop back on block diagram and the value of it is non-default 127.0.0.1 representing a loop-back connection. Now NI decides....

If you are the class user I'd say that you shouldn't be messing with the default value of the private data. That is, the class should be initialized explicity by the class user using the public accessor functions provided. Maybe I'm missing something, but your argument appears to assume the internal representation of private data would retain the same data type... What if the designer decides that the private data should be represented as a numeric instead of a string? At that point your default value on the original block diagram would be meaningless.

The implementation of the private data is, and always should be, at the discretion of class developer.

~Dan

Link to comment

If the class developer changes the private data default value, the constant on the class user's application gets reset under the above described conditions.

Why shouldn't it be reset, and why should the class user care? The data is private. I would expect the class user's to use the public interface privided by the class developer (e.g. Init.vi, DoThis.vi, DoThat.vi, SetThis.vi, GetThat.vi, Close.vi) and not should not be concerned with the class's internal data representation or the default value of private data. Isn't this is the whole purpose of encapsulation?.

If anything I'd suggest that LabVIEW be changed to not allow a class constant to be placed on the block diagram of a non-member VI.

~Dan

Link to comment

Would you ban class placing controls and indicators as well on the front panel?

Of course not, a non-member subVI should certainly be allow to access an object.

They are on the same role here.

I don't see them as being the same role. The constant declares an origin of dataflow. Controls and Indicators are used to pass data through the program.

Link to comment

If anything I'd suggest that LabVIEW be changed to not allow a class constant to be placed on the block diagram of a non-member VI.

Can't happen without major shifts in Labview's design. LV doesn't offer a class type primitive we can use on block diagrams. All we have are instantiated objects from which LV extracts the necessary type information. Remove class constants from non-member block diagrams and everything breaks. Plus, if you take away class constants from block diagrams every single class you ever wrote would need to have a factory "CreateNew" method implemented.

I would expect the class user's to use the public interface privided by the class developer and not should not be concerned with the class's internal data representation or the default value of private data. Isn't this is the whole purpose of encapsulation?

Private data defines the state of an object at any given time. The class user should not have to worry about how the state is represented internally, but it is perfectly valid for him to be concerned with its state--especially if a previously saved state can be unintentionally modified with no warning or indication to the class user.

Ultimately your argument boils down to the fundamental concepts of what it means to be data-based language. Every constant you drop on the block diagram represents one or more real pieces of data. How do you justify allowing some constants, such as strings or integers, to have non-default values stored internally while object constants cannot? From a more practical standpoint, saving non-default data in object constants is often very useful as it can eliminate the need for Init methods. I find this extremely useful because if a class has an Init method that must be invoked before the object will work correctly, classes that inherit from it usually must also have an Init method.

Link to comment

How do you justify allowing some constants, such as strings or integers, to have non-default values stored internally while object constants cannot?

Oh, I didn't say I could justify it biggrin.gif !

From a more practical standpoint, saving non-default data in object constants is often very useful as it can eliminate the need for Init methods.

Are you really eliminating the need for Init? Or just just doing it in a super-secret-implicit-sorta way ph34r.gif by defining a your own default value for the private data control of the class for which you have no control over.

My point is... the user should not depend on things which are not under his control. If you receive and updated version of the class you shouldn't be suprised upon a change to the private data types default value. While I agree that this logic may be a little disconcerning I don't see how it would be advisable to have a rogue class constant with its own default value which the user can't modify after the class is updated...

Maybe I just brought myself around there. Perhaps the change in LV should be that a class constant value can be able to be set on BD sorta like a subVI node. Maybe if the constant is setup for a non-default value and the datatype of the class changes the vi should break. Of course, if the datatype has not change the value is retained.

Nope. this still seems like playing with matches since your giving the user direct access to private data.frusty.gif

Edited by Dan DeFriese
Link to comment

Are you really eliminating the need for Init? Or just just doing it in a super-secret-implicit-sorta way by defining a your own default value for the private data control of the class for which you have no control over.

Yes, it really does eliminate the need for an init method and yes, it is by changing the default values of a specific object on the block diagram. I'm not sure why you consider that a "super-secret-implicit-sorta way" of avoiding the requirement to use an Init method.

My point is... the user should not depend on things which are not under his control.

The default value of data containers on the block diagram are under the user's control. That's why this is a problem. The class developer owns the class. When I drop it on the block diagram it's no longer a class, it's an object, and it belongs to me. Once an object has been instantiated it has a unique data space. In principle, changes to default data in the class definition would affect newly instantiated objects but not pre-existing objects. Labview kindly simplifies the workload by automatically updating an object's default data when the developer has not overridden the default values. That kindness just goes a little too far right now.

Think about text languages. Suppose you write a program that creates an object, sets it up in some state, and saves that object to disk. Then the class designer modifies the default value of private data in the class definition. Wouldn't it strike you as incorrect behavior if when you reloaded your object, the data you had specifically set and saved to disk had been overwritten? That's essentially what is happening.

Maybe if the constant is setup for a non-default value and the datatype of the class changes the vi should break. Of course, if the datatype has not change the value is retained.

Changing the data type is a different discussion. Tomi is talking about simply changing the value.

Nope. this still seems like playing with matches since your giving the user direct access to private data.

Class users never have direct access to private data. Labview doesn't allow it. Class users only have indirect access provided by methods the class developer implements. I think you're getting too hung up on the private data angle. Look at it in terms of the object's state, or better yet, the object's publicly accessable state information. If I've put the object in a specific state, Labview shouldn't be overwriting my state behind the scenes.

Link to comment

How does someone go about setting the default value of a LVOOP constant? Can the value of the LVOOP constant be determined from the BD without running the VI?

You are mixing two terms namely value and default value. One can set the value of LVOOP constant by simply pasting (right click -> data operations -> paste ) a value to it at development time. Before pasting a value to it, you need to copy (right click -> data operations -> copy) the value from somewhere else such as a LVOOP indicator where you have written a value by executing a VI. Default value of LVOOP constant is something set by the class developer and it is the initial value of the LVOOP constant when you drop it to block diagram.

Link to comment

One can set the value of LVOOP constant by simply pasting (right click -> data operations -> paste ) a value to it at development time. Before pasting a value to it, you need to copy (right click -> data operations -> copy) the value from somewhere else such as a LVOOP indicator where you have written a value by executing a VI. Default value of LVOOP constant is something set by the class developer and it is the initial value of the LVOOP constant when you drop it to block diagram.

How does the class user determine what the current value of the constant on the BD is without running the VI? (I mean when more than 5 minutes have passed since copy-paste. And No, a free label comment on the BD doesn't count!)

Edited by Dan DeFriese
Link to comment

You don't...

Exactly, and when I take over the project 6 months later... The Mr. CutnPaste has moved onto bigger and better things, and now I'm stuck with some magic LVOOP constant on the BD that I can't modify when the requirement changes.

In my opinion, its not the resetting of the LVOOP contant's value that's dangerous. It's that by not resetting it you're leaving it in unknown - to anybody other than Mr. CutnPaste - state. Now that's dangerous!

I can see how the ability to cut and paste an LVOOP indicator to an LVOOP constant would be useful (e.g. debugging a section of code). However, my vote is for resetting the LVOOP constant value to the class's default value each time the VI is loaded... not just if the class default value changes.

Link to comment

Exactly, and when I take over the project 6 months later... The Mr. CutnPaste has moved onto bigger and better things, and now I'm stuck with some magic LVOOP constant on the BD that I can't modify when the requirement changes.

Why can't you modify it? Copy the constant to a new vi, wire up a few class methods, and you've got your new settings.

In my opinion, its not the resetting of the LVOOP contant's value that's dangerous. It's that by not resetting it you're leaving it in unknown - to anybody other than Mr. CutnPaste - state. Now that's dangerous!

It's only unknown until you probe it--just like every other object constant on the block diagram. Setting my own default values for an object constant doesn't make the information it contains any less available, it's just slightly more inconvenient to view and change.

As far as being dangerous, I don't see how fixing an object constant in a known state is more dangerous than using a default object and setting all the properties at run time. In both cases you end up with an object in the same state. I'll point out that using an object with my own default values is less dangerous than using a default object and only setting those properties that need to be changed. The former stores the entire state of the object; the latter is effectively a diff against the class' default values, which you have no control over.

Link to comment

Why can't you modify it? Copy the constant to a new vi, wire up a few class methods, and you've got your new settings.

Its more dangerous in that it will likely cost more money to maintain the code in the long run. I think your assuming that the maintainer will have the intimate knowledge of the class to determine how the constant got to its current state or the ability to do so. In a future environment that state may no longer have meaning... (The data type change issue).

Where I work, I occasionally get pulled to make minor updates to existing code. Some of which are >25 years old. The only reason I can make these updates is that the original author coded it cleanly with nothing hidden. I can make these updates even while having only a novice understanding of the languages (e.g. C\C++, Java, even QBasic).

If you need to execute code to get an object in a given state, I think its best to leave that code in the program. In my eyes a preset constant just isn't worth the headache I'm gonna cause myself (or someone else) in the future.

I'm not sure I'm getting my point across. I'm not always that good at the whole putting words together and having them come out right.

In the end, I don't really have a dog in this fight since I don't LVOOP. It just seems to that this resetting of the constant's value is the least of the class user's worries when I step back and think about what your're doing... and where it would go if some goof like tried it.

Anyway, thanks for letting me debate.

Link to comment
Exactly, and when I take over the project 6 months later...
Someday we'll be able to get the data view mechanism working so you can see the values of those constants (and default/operate values of controls and indicators). Unfortunately, that feature keeps getting pushed back for a long list of reasons, not the least of which is it is hard to make usable.
Link to comment

Someday we'll be able to get the data view mechanism working so you can see the values of those constants (and default/operate values of controls and indicators). Unfortunately, that feature keeps getting pushed back for a long list of reasons, not the least of which is it is hard to make usable.

That would certainly make me take back every word. I imagine this would be a pretty daunting task. I'm just imagining what the report generation toolkit LVOOP constant would look like if it were full ohmy.gif ... best luck.

Have a great weekend...

~Dan

Link to comment

If you need to execute code to get an object in a given state, I think its best to leave that code in the program. In my eyes a preset constant just isn't worth the headache I'm gonna cause myself (or someone else) in the future.

I don't have an issue with your approach as a matter of personal preference or coding style. I object to the proposal that NI remove the ability to set alternative default values for objects. IMO there are valid reasons to use it and disabling that feature because it can be misused is throwing out the baby with the bathwater.

I'm not sure I'm getting my point across. I'm not always that good at the whole putting words together and having them come out right.

Funny... I was thinking the same thing about me. biggrin.gif

In the end, I don't really have a dog in this fight since I don't LVOOP.

Here... try this Kool-Aid. It's really good. shifty.gif

not the least of which is it is hard to make usable

Can you expand on this comment?

Edited by Daklu
Link to comment
  • 9 years later...

Sry for thread necromancy. However this thread perfectly describes the problem (especially Daklu's, Dan DeFriese's and AQ's comments) so its suitable place to continue...

After 1 year of my LV app framework development I hit this problem of editing non-default value of LV class constant. Has the problem progressed anyhow ? Do we (LV) have any LV class instance initial value editor?
 

My framework ended with 1 main object including some constant properties and nested objects (with their constant properties and eventually more nested objects - more levels hierarchy). So the problem of setting initial non-default data values is more complicated. I'm trying to develop some own procedure to view/set initial non-default values but no full success. The setting is definitely made during development so I can use scripting or other methods available in development phase only.

Any ideas? Recommendations? Tools? Thanks.

Link to comment
On ‎9‎/‎24‎/‎2009 at 4:51 PM, Dan DeFriese said:

Do we (LV) have any LV class instance initial value editor?

Nope.  AFAIK the only way to set a class constant value is to write a VI setting the object's value, then copy the object with the desired values from an indicator and paste it onto the block diagram.

 

9 hours ago, Petr said:

Any ideas? Recommendations? Tools?

I (as most developers I know) generally avoid using class constants on block diagrams and have adopted something more like what Dan suggests.  Good ideas win out...

For example, all my classes have a "Create <MyClass>" method that more or less acts like a constructor.  The only time I ever drop a class constant on a block diagram is for typing operations (eg: upcasting or downcasting an object) or inside the class' Create method.  You can use either parameters passed into the Create method or accessor methods to set the value of the object--it's a design decision.

I quit using class constants to instantiate objects (other than in the Create method) primarily because it reduces flexibility.  When I see an object wire on a block diagram, I want to know that object it going to work correctly.  If a class has a reference-based construct--such as a queue--as a member, then an object instantiated from a class constant is not going to work until I call a method (eg: Init) that obtains the queue and stores it in private data.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.