LabVIEW Idea Exchange

cancel
Showing results for 
Search instead for 
Did you mean: 
BrianGShea@NGC

Class Override Template

Status: New

When creating VIs in a class that are meant to be overridden, it would be nice to have a template VI that will be used as the template. The easiest way I though of to accomplish this is to create an Override template that has the same name as the VI but with an extension like .OVIT (Override VI Template). 

 

An new item can be added to the context menu when right-clicking on the class to Create New Template for Override VI, which will give you basically the same format as a new vi from dynamic dispatch template, but will include the call parent VI followed by an error case structure.

 

This will allow an architect to create a template for coders to use and place any useful information on the Front Panel or Block Diagram. When the override vi script runs to create the new override VI from MyOverride.vi, it can search for MyOverride.ovit and if found replace the base class' type with the child class' type. Otherwise you get the default VI which has the call parent method.

 

I know this idea has been pass around before, but I thought I would respire it.

 

My goal is to allow architects to give more meaning full information to other developers and more complete starting points for overridden class VIs.

 

Issues that can arise

What if the VI is renamed? Then the maintainer of the class will need to also rename the template VI, but it would be nice if LabVIEW did this automatically.

What if the VI is removed from the project? The OVIT would also be removed.

What if the OVIT is broken, ie. won't execute? Like all class VIs, it should not be broken, the template should contain working code or disable parts that need to be implemented. It would be nicer if the OVITs were ignored for borken code and not allowed to be place on the block diagram for execution.

 

 

 

 

Brian G. Shea
Certified LabVIEW Architect
14 Comments
AristosQueue (NI)
NI Employee (retired)

We already have a template to follow -- the parent's VI. The new VI has to match all the conpane settings, the execution settings, and generally wants to match the icon settings. We copy lots of other aspects (like grid size and panel colors) because those are usually in keeping with the overall theme of the project. Blending two templates would be difficult, and I would be loathe to suggest that we should attempt to do so, since it would be so easy for the conpane contents of one to drift out of sync with the diagram contents of the other.

 

I'm not suggesting that your idea is bad, insofar as having some template code is a good idea. But the particular implementation of having a separate .vit file seems like the wrong approach. I'd be more inclined to suggest that the parent VI should have two block diagrams, one that is its own diagram and the other that is used as the template, thus the two diagrams can be checked against each other, kept up-to-date with each other, etc.

 

Now, having said all of that, template code means copied code, which means maintenance problems if you ever have to change that template. That's generally a bad thing for software, and needing a template for your override VIs is generally frowned upon. Most software engineering texts I've seen say that when you have to have overrides having any common templated code, there's generally a better way to have written your parent class methods in the first place. The Channeling Pattern ( https://decibel.ni.com/content/docs/DOC-13725 )often suffices to eliminate all of that copied code.

 

So I'm open to conversations about how to provide such templating, but with the caveat that I would like to know how many people are hitting that need, and of those, how many are hitting that need because they have not been shown the superior way to avoid generating duplicate code. Those percentages would go a long way to telling me what the right way to answer this request would be.

BrianGShea@NGC
Member

Locking the conpane and VI properties of the template VI is one way to eliminate the issue. But I see your point, how to keep the VI and OVIT in sync when things change. For that matter when changing the VI the entire chain of the overridden VI must change, and that's why we must vet our APIs before jumping into implementation.

 

The default template offers the inputs/output wired to the parent. The reason for overriding a method is to extend or provide alternate implementation of the method. Starting from a blank slate is more difficult than starting from a partially completed slate that can guide the developer and give visual/textual instructions as to what must happen.

 

Granted all this can be completed by providing an external API document and copying code or using VIT's and ensuring the VITs stay sync'ed with the Override method.

 

Here is one example; Idon'twanttoputinmybaseclass' overrideVIawhileloopandeventstructure, IwantthedevelopertooverrideaVIanddothat. Alongwiththat, Iwouldlikesomeaspectsofthefrontpaneltobemaintained, suchasscrollbarsbarsandtoolbars visible indevelopment, buthiddeninruntime. UntilLabVIEWallowstheseparameterstobeconfiguredseparately, IhaveafewVIsthatarecalledtosettheappearance based on the execution engine (thisisoneexample). Ifthedeveloperisnewtotheproject, (s)hemaynotknowtoplacethesesubVIsontheblockdiagram. Byprovidingatemplatethatcontainsadefaultimplementationofwhattheusershouldbedoing, itwouldallowdevelopmenttoprogressmorequicklyandwithfewererrors.

 

A second example; If the parent call returns an error due to some issue, it would be nice to place an Error Case directly following the call parent with instructions to the user to abort what their VI should be doing. In the past, I have seen inconsistent implementation, of where the developer places there code in relation to the call parent. Minimal instruction on the block diagram would have saved time and rework.

 

Ilikethetwoblockdiagramidea, itsimplifiesthings!

 

For now, I have created VIT's and do this manually, it has been working well, and I'm able to communicate the needs of the functionality and provide default behavior.

 

For the simple cases of an override that just extends the functionality of the parent's VI, this is not as useful. But in cases, were the base class is only Abstract and provides no real code, a template would be invaluable starting point.

 

 

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)

> But in cases, were the base class is only Abstract and provides no

> real code, a template would be invaluable starting point.

 

Ah... but that's exactly the issue. Look at the code that you would put into that template. Anything that belongs on ALL of the override VIs should not be on the override VIs at all, it should be on the parent VI with a core subVI that the children override. In other words, if you're starting with anything *other* than a blank VI or just a call parent node, then there's probably a bug in your design. 🙂 The good use cases are, in my experience, that rare. You mentioned handling an error from the call parent node. In general, a child that gets an error from the call parent node should do only one thing -- pass that error out. The caller of the function is the one who reacts to that error. Sometimes a child will modify the error, but that's ona child-by-child basis, not something you could template.

 

The only two acceptable copied code scenario that I know of is when the child is going to call a series of parent VIs (not the call parent node but other APIs) and supply a set of constants that are unique to each child. This often happens when initializing some value. There's a second scenario when you set up a series of structures, like going ahead and putting an event structure in a while loop, because the override is for a UI display. This is the other case that you mentioned.

 

So they do exist, but they're pretty rare, at least in my experience. But knowing exact use cases might suggest how best to go about putting the templates into play.

fabric
Active Participant

+1 for the UI use case...

 

Subpanels are a good example where the child class UIs have unique visual elements, but which can benefit greatly from a common structural layout. The best I have been able to manage is to strip the UI code to not much more than an event handler and to use shared sub VIs for all the boilerplate stuff...

BrianGShea@NGC
Member

(Odd I just noticed that my previous post had most of the spaces removed from my example)

>> Rewrote this for clarity (with spaces)

>> Here is one example: I don't want to put in my base class' override VI a while loop and event structure, I want the developer to override a VI and do that. A
>> long with that, I would like some aspects of the front panel to be maintained, such as scrollbars and toolbars visible in development, but hidden in runtime.
>> Until LabVIEW allows these parameters to be configured separately, I have a few VIs that are called to set the appearance based on the execution
>> engine (this is one example). If the developer is new to the project, s)he may not know to place these subVIs on the block diagram. By providing a
>> template that contains a default implementation of what the user should be doing, it would allow development to progress more quickly and with fewer errors.

Brian G. Shea
Certified LabVIEW Architect
BrianGShea@NGC
Member

AristosQueue
>>"Ah... But that's exactly the issue. Look at the code that you would put into that template. Anything that belongs on ALL of the override VIs should not be on the override VIs at all, it should be on the
>> parent VI with a core subVI that the children override"

You are correct, however, you failed to see the solution to the problem that was being solved. The VI that is placed on the block diagram is overriding VI Appearances and therefore requires the reference to the VI. I cannot include references to VIs that contain the Class type, it is also difficult to access the reference of the "CORE" vi because I do not know where it is in the call chain. If I were to pass the reference into the parent as a required conpane terminal then all overrides would be required to have the conpane terminal, thus leading to a flawed API because only the parent of the child needs the reference passed in and not child itself. There may be a better solution to this, however, at this time I don't know of an elegant one other than the one I presented.

The point in my examples was I could create a template that contains the while loop, event structure, and any dynamic events that are part of the API. Provide contextual documentation in the event cases and block diagram to point the developers in the right direction. I specifically chose NOT to implement this aspect of the code using AF due reasons beyond the scope of this discussion.

>> "The only two acceptable copied code scenario that I know of is when the child is going to call a series of parent VIs (not the call parent node but other APIs) and supply a set
>> of constants that are unique to each child. This often happens when initializing some value. There's a second scenario when you set up a series of structures, like going ahead
>> and putting an event structure in a while loop, because the override is for a UI display. This is the other case that you mentioned."

This is also a good use case for templates, as the developer of the API you would be able to create template with these calls and provide documentation on the block diagram instructing other developers.

Even with Actor Framework, it would be nice to override the AF Actor class with a new Actor Core and provide a template to implement a UI.

Fabric, you have hit the nail on the head, as implementation progresses the VI will be embedded into subpanels, the VIs that muck with the VI attributes will be replaced (internally) by the code to position the front panel and hide all controls not to the left and below the origin. Again, I could have done this in the parent, however, gaining access to the VI ref is not straight forward. I chose this flawed architecture for it's simple solution.

I could have chosen a less flawed approach and spent several hours working out the quirks of figuring out the VI reference in the call chain, however, I chose a simple approach to solve a simple problem.

Lets focus on the use cases for the templates and not minor "Flaws" in the examples presented. There are no perfect solutions, only solutions with the fewest flaws. (Nirvana fallacy)

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)

Ok... all of our good examples are all orbiting around "this method defines a user interface" in some form or fashion. Does that suggest any way that the template should be defined? Is it perhaps just setting a flag on the parent class that says "this is a UI dynamic dispatch VI" which means that a particular template should be provided when overriding? Or is that too limiting and we're still looking for a general solution?

 

Also, are you imagining this template as something that could not be deleted on the override VIs -- i.e., that children MUST use -- and which would somehow be updated when you changed the master copy? Or is this just a framework that children MAY use and there's no link back to the parent template?

BrianGShea@NGC
Member

I would say it is a framework that children MAY use.

 

I like the flag idea, so long as i can muck with the default template much like I did for the default template for Static and Dynamic Disptach VIs. However, that would mean that i need to distribute that template on a project by project basis (worst case) to other developers. 

 

If i had a wish list for this it would look something like this:

It would be NICE to define a template on a VI by VI basis. 

It would be NICE to define them in the class

It would be NICE to choose to use the template

 

Brian G. Shea
Certified LabVIEW Architect
AristosQueue (NI)
NI Employee (retired)

If you need to be able to modify the template then the flag idea is out because it wouldn't match the template used by everyone else for their new override VIs. The flag only works if there's a universal template.

fabric
Active Participant

Just throwing this one out there....

 

What if the dynamic UI elements could be defined in the class somehow, such that they could be overridden? Classes already let us override methods... What if we could also override certain data?? (A possible syntax would be to allow the class private data ctl to be expanded into sub-elements.)

 

A specific example:

  • Imagine we have a special UI method defined in the parent class. (In the context of AF it could be our actor core.) This will serve as our template VI.
  • Now imagine that this VI has a visual element (typedef cluster) called "Settings". This special cluster is defined in the parent class (and is quite possibly empty) but it has a fixed, pre-defined size and position on our UI.
  • Child classes can override this typedef cluster with their own implementation. Any methods that operate on this data will use the child version of the data. (Obviously such methods would have an implied "must override" requirement.) 
  • Note: To achieve the "template" behaviour the child classes would NOT override the UI method itself... They would only need to override the visual elements and methods that use them.

Could this work?