09-09-2020 04:30 AM
Hi,
Everything is in the title, but I'll try to illustrate a bit.
I'm familiar with LVOOP concepts and I'm using both "by value" and "by refs" class but I saw recently someone use a "by value" class and store that the object in a DVR to work on it in different asynchronous process.
To illustrate this, I share a project with two examples:
- The first one is a by value class
- The second is a by reference class
I'm confused about what are the interests of using a DVR that's store an object instead of using a DVR as the private data of a class?
If I'm understanding well, with this method we lose the dynamic dispatch and cannot use directly the methods of the class... (But a property node works?! Wtf ?!)
Loïc.W
09-09-2020 05:19 AM
If the class is by value, at least you can use it as it should be used, by value.
If you really need to, you can put in in a DVR.
If the class is by reference, you can't use it as you should, by value... The class is ruined.
DVRs are almost never needed. LabVIEW is a dataflow language, and DVRs usually cause more problems than they fix.
Of course, this is heavily biased (towards proper wireflow practices) 😋.
09-09-2020 05:25 AM
@Loïc.W wrote:If I'm understanding well, with this method we lose the dynamic dispatch and cannot use directly the methods of the class... (But a property node works?! Wtf ?!)
You really loose DD at all, you just have to put your methods in a IPE structure to access the class from the DVR.
This is also the reason only property nodes work. Property nodes are supposed to be atomic actions, while methods could be blocking. That makes methods more likely to cause problems when invoked on a DVR. Especially when multiple methods are executed sequentially. So LV forces you to put those actions in a IPE structure...
09-09-2020 07:31 AM
wiebe@CARYA a écrit :
If the class is by value, at least you can use it as it should be used, by value.
If you really need to, you can put in in a DVR.
If the class is by reference, you can't use it as you should, by value... The class is ruined.
DVRs are almost never needed. LabVIEW is a dataflow language, and DVRs usually cause more problems than they fix.
Of course, this is heavily biased (towards proper wireflow practices) 😋.
I'm not sharing your opinion about DVR and referenced class but it is not what I wanted to discuss here...
There are a lot of pros and cons for both style and it is always biased ;).
09-09-2020 07:47 AM
But still...
A by value class can be put in a DRV to get a by reference class.
A by reference class will never be a by value class.
So if the class is intended to be reused and can be used by value, it makes sense to design it by value, and then either put it in a DVR or make a by reference wrapper. The other way around is not possible.
So if you have a by value class, and want to reuse it, you can either refactor it, or take it as it is and put it in a DVR or by reference wrapper.
That was what you where asking: why would you make a by value class and put in in a DVR...
09-09-2020 07:50 AM - edited 09-09-2020 07:58 AM
wiebe@CARYA a écrit :
@Loïc.W wrote:If I'm understanding well, with this method we lose the dynamic dispatch and cannot use directly the methods of the class... (But a property node works?! Wtf ?!)
You really loose DD at all, you just have to put your methods in a IPE structure to access the class from the DVR.
This is also the reason only property nodes work. Property nodes are supposed to be atomic actions, while methods could be blocking. That makes methods more likely to cause problems when invoked on a DVR. Especially when multiple methods are executed sequentially. So LV forces you to put those actions in a IPE structure...
Ok for DD I didn't think enough to realize that.
What I wanted to point here is that I see a lot of unpleasant stuff (As a developer) at develop a" by value" class and finally using it through a DVR.
But I recently saw someone do this and I'm asking why didn't he store his data in a DVR instead of using a referenced class directly? There is any advantage to doing this? (Excepted if a "by value" class already does the hard work and there it could be easier to just store it into a DVR instead of recoding it)
As a "by reference" style user, I think there both do the work and it only depend on user preferences...
But still open to read other opinion about it.
Edit :
But still...
A by value class can be put in a DRV to get a by reference class.
A by reference class will never be a by value class.
So if the class is intended to be reused and can be used by value, it makes sense to design it by value, and then either put it in a DVR or make a by reference wrapper. The other way around is not possible.
So if you have a by value class, and want to reuse it, you can either refactor it, or take it as it is and put it in a DVR or by reference wrapper.
That was what you where asking: why would you make a by value class and put in in a DVR...
Yeah, I thought about it as the same time as I wrote my response.
But coding a class, knowing that I'll have to wrap it to be used through a DVR is not really satisfying...
09-09-2020 08:02 AM
@Loïc.W wrote:
I'm confused about what are the interests of using a DVR that's store an object instead of using a DVR as the private data of a class?
If I'm understanding well, with this method we lose the dynamic dispatch and cannot use directly the methods of the class... (But a property node works?! Wtf ?!)
I kind of like the idea, it's very easy to create a sub-class of the data that a Child use and reuse most all of the code.
I'm assume you're using a class with a (separate) data-class as it's only attribute in this case.
You'll have dynamic dispatch of the 'wrapper' class and a DVR to make sure you use the data data regardless of wire splitting.
I guess you can inherit the data class and have dynamic dispatch on that too.
I Think i'll need to test it out.
09-09-2020 08:12 AM
@Loïc.W wrote:Edit :
But still...
A by value class can be put in a DRV to get a by reference class.
A by reference class will never be a by value class.
So if the class is intended to be reused and can be used by value, it makes sense to design it by value, and then either put it in a DVR or make a by reference wrapper. The other way around is not possible.
So if you have a by value class, and want to reuse it, you can either refactor it, or take it as it is and put it in a DVR or by reference wrapper.
That was what you where asking: why would you make a by value class and put in in a DVR...
Yeah, I thought about it as the same time as I wrote my response.
But coding a class, knowing that I'll have to wrap it to be used through a DVR is not really satisfying...
If I really needed DVR functionality, I'd put the DVR in the class's private data.
If I have a by value class, I'd never put it in a DVR, because I'd use other mechanisms (events, queues, or... a wire). But that's OT.
This is not so much about style, it's more that DVRs came to the party pretty late. They where a means to an end, but LabVIEW developers didn't really design it to be used intensively. This is why debugging them is much harder. If you'd propose an idea to improve working with DVRs, I'm pretty sure the reply will be: "you're doing it wrong".
I started OO around the same time DVRs where introduced. I made a fair share of DVR classes. I refactored all DVRs out by now. The fact that when I stop my code, I can't debug anything because the references are gone spoils it for me. I think OpenGDS avoids this by allocating DVRs in a central broker, but I've moved back to by value...
09-09-2020 08:40 AM
@Yamaeda wrote:
@Loïc.W wrote:
I'm confused about what are the interests of using a DVR that's store an object instead of using a DVR as the private data of a class?
If I'm understanding well, with this method we lose the dynamic dispatch and cannot use directly the methods of the class... (But a property node works?! Wtf ?!)
I kind of like the idea, it's very easy to create a sub-class of the data that a Child use and reuse most all of the code.
I'm assume you're using a class with a (separate) data-class as it's only attribute in this case.
You'll have dynamic dispatch of the 'wrapper' class and a DVR to make sure you use the data data regardless of wire splitting.
I guess you can inherit the data class and have dynamic dispatch on that too.
I Think i'll need to test it out.
A DVR data class isn't enough. There would need to be a locking mechanism. If you 'get' the data from the DVR, modify it than 'set' it, you'll have a race condition. The IPES would lock it, but you can't split up the 'get' and 'set' in subVIs.
Perhaps I'd need to see your idea first.
I've found:
* without significant amounts of duplicate code, wrapping everything, or data copies.
I've tried. I've asked others. It's hard with the tools we are given.
I did this in a ini file library. The parent is by wire, the child by reference. It involves reference counting, interlocking and data buffering.
I have an idea that would fix this all, but it would need additions to LabVIEW. And like I said, the reply will probably be "you're doing it wrong". That's the response I get a lot on the idea exchange.
There are classes that would be useful by value and by reference. For instance, a ini file reader. I'd like it by value, but it makes sense to have (an option to have it) it communicate over parallel loops. If only because the NI implementation does it like that.
Another example would be a current value table. I like it by value, but it would serve a purpose to make parallel loops communicate with each other.
For the record (but I think we're all agree on that) both by value and by reference would still mean by wire. I don't want Globals or singletons in OO of any sorts in my programs.
09-09-2020 10:29 AM
wiebe@CARYA a écrit :If the class is by reference, you can't use it as you should, by value... The class is ruined.
wiebe@CARYA a écrit :
For the record (but I think we're all agree on that) both by value and by reference would still mean by wire. I don't want Globals or singletons in OO of any sorts in my programs.
I'm a bit late about this but I do not understand why a "by ref" class cannot be used as the same way (for an end user) that a "by value" class.
But I'm totally agree about talking of "by wire»!
Example:
- I design a "by ref" class with DVR (So there is both Constructor and Destructor)
- I lock the access to the diagram for all method
- I give the API to a developer
- The developer uses it as a "by value" class without knowing that it is a "by ref" class
What's happen? The developer will not see that it is a "By ref" class and it will still work properly no?
Then if I tell the developer that it is a "By ref" class, he will use it as a "By refs" or a "By value" class depending on the situation. (/!\ race condition)
Wrong? (real question)
I don't understand why qualify as "ruined" a "by value" class
About the purpose of this topic, I see now some use cases for storing an object into a DVR, but I think that I'll never have a situation where I must do this because I mainly use "By ref" class. (Society template with scripting tool)