Jump to content

Has anyone ever felt the desire to restrict a field to a single method?


Recommended Posts

I don't officially work on LV classes any more, but I still sketch out syntax ideas from time to time. Tonight, I had something weird happen when I combined a couple of futuristic ideas. Has anyone ever felt the desire to declare fields of a class that are private to a single method of a class? I came up with a syntax that would let me declare fields of a class as part of writing a VI that used that field, but it would be restricted to only that single VI. I couldn't think of any use case for such a thing, but then, I've never had a programming language that would let me declare such a thing. Maybe if I had it, I would have used it and found it invaluable. So I'm asking... suppose you could write a method of a class and in that method declare "this is data that is local to this VI but it becomes part of the state data of the object overall such that if the wire forks, this data would fork too." It's kind of like a local variable, but instead of being part of the VI, it's part of the object.

 

Like I said, it's weird, and it just sort of came about as a result of some other strange syntax ideas I was playing with. I was wondering if anyone felt it was worth me exploring further.

Link to comment

I've done this, though there's always a pair of accessor VIs attached. I'm one of those people who litter my classes with accessors and never touch the cluster data except in said accessor VIs. It's just too darn convenient when you need to find where a field is used.

 

That said, I'd be against the idea because now you can't get a good idea of what your state data is by looking at the class control-- it becomes scattered about in several places. Maybe I'd like it if somehow the field automagically also appeared in the state control, but somehow was greyed out and not selectable outside of the VI. Maybe. But then I imagine automatically placing such fields could make for absolute havoc if on unbundle nodes.

Link to comment

I can see the need of this, but since I try to keep classes small-ish, I normally remember that I should always access that attribute through the public/private helping method.
But I still prefer referenced object and I can easily solve this with that design :-)

Link to comment

Well, recently I've been working with a class that does a lot of simple tasks, but a sub-group of them have become increasingly complex and sensitive. Now I would like to further isolate that set of properties from the rest of the class VIs to be sure no old and forgotten code messes it all.

 

I'm going to add a new class inside the old class and move the critical fields to it, but that will force me to implement some encapsulation in the original class (to allow the external code call those methods). Your suggestion would be a step in simplifying the problem, but what I'd really need is a "this field can only be modified by this subset of VIs".

 

Saludos,

Aitor

Link to comment

Flarn wrote:

What exactly do you mean by "(you) came up with a syntax"? Is it just something normal that anyone can do, or are you referring to LabVIEW's source code? I just haven't heard the term 'syntax' used in the context of dataflow programming.

All languages have syntax. Dataflow isn't special in that sense. What does a For Loop look like? How do you declare "repeat this chunk of code over and over"? Compare the Shift Register to the Feedback Node. They both express the same concept but in very different syntax. To some degree, the Select node and the Case Structure are the same semantic meaning but very different syntax.

 

My primary job over the years has been the syntax of LabVIEW: what visual elements constitute the block diagram of LabVIEW and how do we translate those elements into a semantic meaning. Let's take recursion as an example. Someone said, "A block diagram should be able to express a function calling itself." That's the semantic meaning that a LV user should be able to express. How do they express it? There's one approach of just putting the VI's own icon on its own block diagram. I argued strongly that it should be a structure node, not a simple function call node. Here's the syntax I wanted for expressing recursion:

 

post-5877-0-19946000-1358523553.png

 

The structure reflects multiple calls to itself. New terminals are automatically added to the inner "recurse node" every time a tunnel appears on the structure node. That would be a very different way for a programmer to express a recursive function, but it has some major advantages (one, for example, is that the compiler has the ability to check the correctness and eventual termination of the recursive function because the decision of whether to recurse or not is broken out explicitly and the structure guarantees the existence of a base case). There's more to the proposal than just this single image (handling multiple interrelated functions, for example), but the point is this could have been the syntax of recursion in LabVIEW. And I still like it better as a model for recursion. What finally won was that a direct subVI was what everyone was expecting because that's what all other languages have, for good or for ill.

 

So the syntax of LabVIEW is any visual element that has meaning to the programmer and to the program. I can make it easier to express things by changing the syntax of LabVIEW. The dynamic dispatch subVI is a syntax element representing a call to many possible subVIs. We could have represented that differently. We could have made it look nothing like a regular subVI node. An Express VI, with it's halo, is a syntax element, mimicing a subroutine call, but with additional configurability separate from the normal configuration abilities of wiring constants to the terminals. Although LabVIEW does not have a textual parser, there remains the human *visual* parsing of a diagram.

 

Back to the topic at hand...

What I've been playing around with is different ways of expressing data communication on the diagram, both intradiagram and interdiagram (both two diagrams on the same VI (i.e. between two loops) and diagrams on different VIs). As I've tried different ways of expressing such communication, I've looked at how would a programmer express "I want this communications path open from this diagram to that diagram and ONLY that diagram". As such, there's a degnerate case where the send and receive diagram are the same diagram. When I combined that with some of my ideas for changing the syntax of objects such that a single dataflow diagram can express both references and values (a way futuristic project that I'm not prepared to get into for a long while), I ended up with a syntax that would naturally and easily express "this is a field of the object that is only accessible on this one VI".

 

Jack wrote:

Can you give a concrete example? For this new feature, do you envision restricting fields to exactly 1 class method, or a defined subset of class methods?
Not really... that's kind of what I'm fishing for here. Functionally, it would be like having a class "MyThing.lvclass" that has a private data control containing an integer X and X is restricted so that only "MyThing.lvclass:ThisOneVI.vi" could bundle or unbundle that variable. It would be so restricted that it wouldn't even show up in the private data control itself. It's state data that would only be usable within "MyThing.lvclass:ThisOneVI.vi". If you deleted that VI from the class, without having to make any modifications to the private data control, that field X would disappear from the objects. Such a field raises some interesting questions for serialization -- it could be serialized by the LabVIEW prims that have access to all the data, but writing something like my Serialization Library would be impossible because no other function would even know about the field.

 

 

fabric wrote:

 

Could this syntax be adapted to specify certain class data as protected or community scope? That would probably be of more interest to me...
No. This would be the opposite... *uber* private, where not even the other methods of the parent class know about this data. Protected and community scope data is an abomination against nature. Flog yourself with your mouse whenever you find yourself desiring it. This will either beat the desire out of you or at the very least destroy your mouse so you cannot contaminate your fellow programmers.

 

 

Aitor Solar wrote:

 

but what I'd really need is a "this field can only be modified by this subset of VIs".
Yeah, that seems to be where I end up when I think about uses for this.
Link to comment

Playing devil's advocate here, what use would this be that couldn't be achieved through inserting step(s) in the inheritance tree?

 

The only problem I see is to use inheritance you'd potentially have a chain of relatively simple, unrelated, and nonsensical classes where the only use is to restrict access to state data. Generally speaking I use object oriented design to take advantage of polymorphism, not for such esoteric shenanigans.



Also let me be clear, I don't think using inheritance to solve this problem is a good design, I'm just asking if it would be a functional equivalent. Solving this issue with inheritance brings along quite a bit of baggage in my opinion.

Link to comment
Has anyone ever felt the desire to declare fields of a class that are private to a single method of a class?

 

Here's a direct copy-and-paste from a note I wrote a couple years ago on the "potential IdEx Candidates" list:

 

 

 Ability to set property of a wire to "locally scope" the wire. That way, it could not be run into SubVIs. Or, perhaps, some other method of disallowing developers to wire a wire into a SubVI (e.g., state data from a State Machine being passed into a SubVI en masse)

 

The gist is to truly scope data to the BD of a single VI, discouraging abuse of exposing data across a SubVI (or even structure) boundary where it does not belong. Is this idea kinda like what you're proposing? Or an alternate solution to solve the same problem? (One obvious difference: this declaration would be held at the VI level, not the object level)

Link to comment
No. This would be the opposite... *uber* private, where not even the other methods of the parent class know about this data. Protected and community scope data is an abomination against nature. Flog yourself with your mouse whenever you find yourself desiring it. This will either beat the desire out of you or at the very least destroy your mouse so you cannot contaminate your fellow programmers.

Community scope. Meh. Still don't really understand what that is for. However. Protected? I don't desire it. I demand it.

In other languages I never declare "private". I always declare "Protected".

The reasoning goes like this.......

If someone is going to use my class then it must do what they want it to do (not necessarily what I think they might want to do or what I have designed it to do). If I declare a private function.(or variable for that matter) then I am denying them the option to make it work the way they want it (and don't talk to me about "FINAL"). However. Regardless of me making it private, they will hack the class to bend it do their will and, ultimately, modify my code (which I have spent a lot of time testing). At this point we get into arguments since the onus is always on the supplier to prove that the problem isn't with their code.when things go wrong. Eventually you figure out they have hacked it and you get into the ....... "You shouldn't have modified it because.....I modified it because.... You modified it therefore I'm not fixing your code" .... ad nauseam.

 

Declaring as "Protected", however, does not deny them the opportunity of modifying the bahaviour of my class and, more importantly, if they want to modify it to bend to their will; can inherit and not trash my clean and tested code to do it (we'll ignore the fact you also end up with multiple variants of subtly different code). Sure, they can break the functionality that I have carefully considered. But that is a problem with their code, not mine and I can prove it by making them go back to the original without overrides/extends etc. If they then say that they modified it. I can tell them they should have overridden so go away and try again.

Edited by ShaunR
Link to comment

Wait, I missed that. Are you saying you think overriding protected accessors is bad? I completely agree community data is mostly bad, but there several use cases I've adopted which come to mind for protected:

  1. Derivative classes need to apply more restrictive bounds checking to the write methods.
  2. I also have a derivative classes which implements a Read Timeout() override such that in certain states it will return a calculated value rather than the field stored by the parent state-- it needs to get something done after so many seconds and if the parent is returning a longer than necessary timeout, it returns the appropriate smaller value.
  3. Also some of my accessors are really just VIs that return constant values. While these aren't strictly accessors since the default implementations return VI scoped static data, the intention is derivative classes might wish to return state fields or data calculated from state.

Link to comment
Shaun: That whole argument is why you would use protected *accessors*. Those can be overridden to provide alternate behaviors. Fields can't be.

Accessors, fields, data or lemons. It doesn't matter. The point I was trying to make is that if a user wants to modify/abuse my code to get the desired behaviour; they should be able to without editing it. By making it a protected rather than private lemon, they can and is making a conscious decision to do so by writing additional code rather than messing with mine.

 

By all means "hide" data and functions. But don't lock them away so they need a crowbar to make it do what they want.

  • Like 1
Link to comment
NI could learn from this...

On topic? No.

:frusty: Flarn, I get that you don't like that we only release features when they're actually finished and that you loathe the fact that we only promote APIs for the purpose they were intended and that we don't have a raw pointer to memory exposed on every diagram. Shaun, I get that you have little use for object-oriented programming, that you don't use the vast majority of its features and you hate what it does to the programmers around you. You've made your opinions known. Really. I don't mind the occasional snark, but can it please be accompanied by a response on the topic?

 

I missed Jack's question earlier...

The gist is to truly scope data to the BD of a single VI, discouraging abuse of exposing data across a SubVI (or even structure) boundary where it does not belong. Is this idea kinda like what you're proposing? Or an alternate solution to solve the same problem? (One obvious difference: this declaration would be held at the VI level, not the object level)

Jack, yeah, the object level makes it significantly different. I don't think it would solve your problem.

Link to comment
Jack, yeah, the object level makes it significantly different. I don't think it would solve your problem.

 

I'm not necessarily looking for a resolution of a problem; rather just comparing notes to what seemed like a similar scoping construct -- mine was one of those ideas that has never graduated past a 30sec stream-of-consciousness dump onto the LV IdEx Google Task list :-)

 

It would be interesting to hear more about the specific context in which you originally envisaged this feature.

Link to comment

It's just back-of-napkin stuff at the moment. I'm looking at Pi-Calculus notations and actor encoding languages and trying to wed them to the object models of programming. One expresses elegantly "data goes from here to there". The other expresses elegantly "data changes here but not there" and "this maintains similarity to that, with the following adjustments". That lead me in the direction of "What if data is not static on a wire? Suppose it were actually doing something as it traveled down the wire?" In other words, package up a still running state machine and send it, as it is running, down a wire to be transformed. Can we express that visually and, if so, what computationally interesting things fall out of it? Well, if a VI sans subVIs becomes something that other VI can act on -- and I don't mean act on as in scripting, I mean act on as in trigger or adjust its running environment -- then the local variables within that VI is object data. Does such an expression buy us anything? As Mje pointed out, no, not really, unless you can make it a set of VIs. Ok... so... oh, crap, ran out of space on the napkin. :-)

 

If all this sounds like near nonsense, it might be. A lot of the time I spend trying to weld ridiculous ideas together and see what sort of chimera comes out. Most are genetically non-viable, a few are mules, useful for hauling but not reproducing on their own, and one or two turn into new unique species valuable in the environment.

 

And about half the time, I lose the napkin, get bored, or move on to the next topic just because there's so much to explore and so little time.

Link to comment
but can it please be accompanied by a response on the topic?

It was in response to your comment on protected (should be flogged etc). It is stating that private (generally) is not a "good" thing IMO for the fore-mentioned reasons. You are wishing to make fields "uber private". If that is off-topic then so is Jacks.

What you don't get is that I do use OOP extensively. I use it in PHP and delphi. I just don't like it in LV. So I am a little bemused that my thoughts invalidate any comment because I'm a classical LV programmer..

 

So back to "Any proposals for utility for private-to-one-VI fields of an object?"., Yeah. If you're going to do it (I can't see a use case apart from bringing it in to line with other languages in the same sense I can't see the need for a static equivalent). Make them protected not private or give us a choice how to scope them with protected being an option!

Edited by ShaunR
Link to comment
Make them protected not private or give us a choice how to scope them with protected being an option!

Protected wouldn't make any sense in this case since it really would be just *one* VI, and protected implies at least two. So I think you're vote is the same as mine that there's not much use in a feature like this coming into the language. Like I said, it was something that cropped up when I was playing around, and I was trying to figure out if it had any utility. None so far.

Link to comment
Protected wouldn't make any sense in this case since it really would be just *one* VI, and protected implies at least two. So I think you're vote is the same as mine that there's not much use in a feature like this coming into the language. Like I said, it was something that cropped up when I was playing around, and I was trying to figure out if it had any utility. None so far.

Well. On a slightly more esoteric point. You say in the OP that that it is like a local variable. Here you are talking about a single VI.

I think you need to define the context of what you think a VI represents.

 

For example. you can have multiple methods in other languages and they do not require a single file per property/method.to access the storage In labview you must have a VI (file) per method/properties that you wish to manipulate from the cluster (storage).

 

Taking my previous statement about "static". In other languages I could put a static variable in one of the methods to count the number of times that method/function had been called. This would translate (I think) into a single VI method with local (to that VI) storage outside the purview of the cluster (i.e. only accessable inside the function but could be exposed via a terminal of that VI - the return value in other languages). Is this a similar scenario to what you are describing here? Or am I really out there in my understanding?

Edited by ShaunR
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.