To download NI software, including the products shown below, visit ni.com/downloads.
When talking about computer programming, a design pattern is a standard correct way to organize your code. When trying to achieve some particular result, you look to the standard design patterns first to see if a solution already exists. This sounds a lot like an algorithm. An algorithm is a specific sequence of steps to take to calculate some result from a set of data. Generally algorithms can be written once in any given programming language and then reused over and over again. Design patterns are rewritten over and over again. For example, in house cleaning, consider this algorithm for vacuuming a carpet: “Start in one corner, walk horizontally across the floor, then move to the side and continue making adjacent parallel stripes until the whole floor is vacuumed.” Compare this with the design pattern for cleaning a room: “Start cleaning at the ceiling and generally work your way down so that dirt and dust from above settle on the still unclean areas below.” Design patterns are less specific than algorithms. You use the patterns as a starting point when writing the specific algorithm.
Every language develops its own design patterns. LabVIEW has patterns such as “Consumer/Producer Loops” or “Queued State Machine.” These are not particular VIs. Many VIs are implementations of queued state machines. When a LabVIEW programmer describes a problem, another programmer may answer back, “Oh. You need a queued state machine to solve that problem.” Starting in LabVIEW 7.0, LabVIEW has had VI templates for many LabVIEW design patterns available through the File>>New… dialog. With the release of LabVIEW Object-Oriented Programming, we need to find the new patterns that arise when objects mix with dataflow.
The seminal text on design patterns appeared in 1995: Design Patterns by Gamma, Helm, Johnson and Vlissides. This text is colloquially known as “the Gang of Four book.” This text focused on object-oriented design patterns, specifically those that could be implemented using C++. Many of those patterns are predicated on a by-reference model for objects. As such they apply very well to classes made with the GOOP Toolkit (or any of the several other GOOP implementations for LabVIEW). LabVIEW classes, added in LV8.2, use by-value syntax in order to be dataflow safe. This means that the known patterns of object-oriented programming must be adapted, and new patterns must be identified. This document describes the LabVOOP-specific patterns I have identified thus far.
Stephen Mercer,
LabVIEW R&D
Design Patterns
Application Examples
Those are the design patterns thus far. I hope to update the list as time goes by, both with more patterns and with better examples for the existing patterns. Pay attention to the code you write – when you find yourself following the same routine over and over, try giving a name to the pattern. See if you can clearly identify when it is useful and how best to do it.
Exploration of these patterns helps us design better code. Using the patterns is using the learning of previous developers who have already found good solutions. In studying the patterns, we can learn what good code “feels” like, and we are then more aware when we create an unmaintainable hack in our own programs.
When we follow the standard designs it helps others looking at our code understand what they’re looking at. If a programmer knows the general pattern being used, he or she can ignore the framework and focus on the non-standard pieces. Those points are where the program is doing its real work. It is akin to looking at a painting in a museum – the painting is the interesting part. The picture frame and the wall are just there to hold up the art. If either the frame or wall is too decorative, it pulls the viewer’s focus.
I do not talk about any anti-patterns in this document. Anti-patterns are common attempts that look like good ideas but have some generally subtle problem that will arise late in development. Some anti-patterns in other languages are sufficiently detectable that a compiler could even be taught to recognize them and report an error. Perhaps these exist in LabVIEW. We should be cataloguing these as well.
Let wire and node
gently flow into a world
of class and method.
– LabVOOP
Reference:
Design Patterns. Gamma, Erich, et al. 1995.
Addison Wesley Longman, Inc.
Description-Separate-2Example code from the Example Code Exchange in the NI Community is licensed with the MIT license.
After reviewing the Rabbit Squad class, I now understand why NI password protects many of their block diagrams--self documenting code at its finest!
What happened to the Observer Pattern? I'm sure it used to be listed here....
I removed it. The implementation given was one that I would never recommend anyone use. Someday I'd like to get back to that project, working with the engineer who created it, but it fell off my radar.
Why was the link to Observer removed in rev 24?
See previous comment
Great central point for agregating the various design patterns.
Just noticed this page elsewhere on the forums.
https://decibel.ni.com/content/docs/DOC-21531 for a take on the MVC (Model View Controller) Pattern
AristosQueue wrote:
I removed it. The implementation given was one that I would never recommend anyone use. Someday I'd like to get back to that project, working with the engineer who created it, but it fell off my radar.
Hi Aristos,
when you say that you would not recommend the implementation, are you referring to this one?
https://decibel.ni.com/content/docs/DOC-20182
Could you tell us why would you not recommend that implementation or even the one that Michael suggested? I am working on a project where the observer pattern would really suit, but I'd like to know why it is not recommendable before I get into troubles.
Thank you
Hi all,
Maybe it's not the good place to talk about that ...
My concern is about object based framework.
LabVIEW give us since ... I don't remember when it appeared ... the Actor Framework, which is certainly powerfull, but just unreadable.
When I conduct Core3 training, I'm tempted to show what could be object based framework in LabVIEW, then I remember how the actor framework looks, then I decide to make my trainies continue to use LabVIEW, and finally I don't show the actor framework.
When will NI provide a SIMPLE object based framework in the templates ?
Something like the command patern exposed here by Elijal Kerry :
or in a the test executive example of the PTP sequencer :
http://www.ptpartners.co.uk/ptp-sequencer/
I personnaly use the "old" QSM (please Daklu, don't bite me), for sure it is not an ideal solution...
I love objects, I used them in my code, but not in for my high level code.
Any links ?
Thanks,
SebastienM
> When will NI provide a SIMPLE object based framework in the templates ?
Your question is confusing to me. I'm going to try to lay out the reason for my confusion... perhaps you can then post a response to clarify your request.
To me, it sounds the same as asking, "When will NI provide a simple polyVI-based framework in the templates?" You don't have a template to demonstrate the language features. You have a template to solve a particular kind of problem. We might have a polyVI in a template if it were approrpriate, but we wouldn't have a template for using a polyVI.
We have examples in the Example Finder for OO. Examples are where we demonstrate features. Check out the board inspection LVOOP example.
Do you just want a template that has a project with nothing but an empty class in it? That was something I thought should be in the templates list but got overruled.
But beyond that, I don't know what you're asking for. Frameworks are meant to solve problems, generally large problems. You don't build a framework for small stuff. The AF tackles a particularly hard problem in LabVIEW (or any programming language). If you are teaching in Core 3 how to build applications that include multiple parallel and intercommunicating processes, you should be teaching the AF or one of the other user-developed-but-freely-available frameworks, as they are all far simpler than trying to code on your own. But last I checked, you're not doing that in Core 3, so you probably shouldn't be teaching AF.
But template projects for "OO" generally doesn't make sense to me. You don't template language features. You template solutions to problems.
As for the command pattern that you mentioned from Eli -- that's *exactly* what the Actor Framework is an instance of. No more, no less. The command pattern as a pattern is not something you can template -- patterns are things that recur in software and you build from scratch each time and they follow a particular form of development but the details are totally different each time. If they could be formalized, they would become a framework or library. The trick is that to make a generic command pattern into to a standalone thing, you need the environment that gets the commanded thing running and the controls for stopping it.
So, instead of asking for an OO-based framework in the templates, tell me a problem that you think has a generic solution worth templating, and then we can discuss using classes to solve that problem. That would be a template that uses OO. But we need a simple problem first.
Do you see the difference? Do you see why even asking the question is confusing to me? Have I missed the point of what you were hoping to see?
I agree with and echo Aristos' comments.
Hi SebastienM
as Aristos mentiones, it makes not that much sense of just having a object framework in the template without a problem to solve just to show the features. But you can find some libraries like the Configurator Editor Framework (https://decibel.ni.com/content/docs/DOC-37225 ) or the Tag Bus Framework (https://decibel.ni.com/content/docs/DOC-41721 ) which are object based frameworks, for solving specific problems. When you install the VIPMs they will add templates of this implementations to LabVIEW.
Best Regards
Hi,
First, thank you all for your time, I did'nt expect that LabVIEW stars like you would answer to that
Second : unfortunatly I did a cross post so the conversation was plit in half :
http://forums.ni.com/t5/LabVIEW/SIMPLE-Object-Based-Framework/td-p/3107317
Up, now it's here :
http://forums.ni.com/t5/LabVIEW/SIMPLE-Object-Based-Framework/td-p/3107317
Sorry about my OOO msg... deleting it
I appreciate all of this effort. I have been personally been working on doing what you have done on my own, and have struggled. I have read this LVOOP overview article and this discussion concerning the reason for the OOP design choices that were made, and I still find myself in the category of in this quote from that last article of, "<Constructors, being> so fundamental to the language cannot be so completely hidden, and the person feels either ashamed for not being able to find it or angry at us for making it so hard to find!"
From the way I am looking at this code, this does not reflect the Strategy Pattern correctly. In the Strategy Pattern, you have a Behavioral interface with specific implementations of said Behavior. So, "HeatBehavior" could be a interface and the implementations would be, "Bake", "Boil", "Broil", "Microwave". The HeatBehavior would provide a "virtual" function, "cook", and each implementation would then implement that function accordingly.
Then, you have a Client interface that is composed of a Behavior object. The Client interface would provide a public function, "doCook", which would call the Behavior object's "cook" function. So, in text language, it would look like (ignoring memory leaks and whatnot):
class KitchenDevice {
private:
HeatBehavior* m_heatBehavior;
public:
void setHeatBehavior(HeatBehavior* hb) {
m_heatBehavior = hb;
}
void doCook() { m_heatBehavior->cook(); }
};
You then create implementations of "clients" of the "KitchenDevice"
class Oven : public KitchenDevice {
public:
Oven() { setHeatBehavior(new Bake{}); }
// NOTE: the "Bake" class implements HeatBehavior with it's own behavior
};
If you are in a rush, you implement the "Microwave", and cook. If you have more time, create the Oven and cook:
void performCook(KitchenDevice* kd) {
kd->doCook();
}
int main() {
Oven* oven = new Oven{};
Microwave* mw = new Microwave{};
Broiler* b = new Broiler{};
performCook(oven); // performs baking
performCook(m); // performs microwaving
performCook(b); // performs broiling
return 0;
}
The potential power of this pattern in LabVIEW becomes clear with, let's say, a power supply.
1. Create behaviors common in interacting with a power supply: SetVoltageBehavior, SetCurrentBehavior, etc
2. Then provide implementations for those: some power supplies communicate via SCSI, some via direct voltage communication. You could even have a 5V supply via a digital switch. All of those will implement the SetVoltageBehavior, SetCurrentBehavior, etc in their own way.
3. Then, create a base client: PowerSupply with implementations of these.
4. You essential create a library of "PowerSupply" implementatins. Whenever you get a new one, you just 1. create a new implementation of the Behaviors and then an implementation of the PowerSupply client.
Ok, (writing much more than I intended)...
Having said that, I have been unable to create a LabVIEW class hierarchy that can do this. I won't get into the issues (I've typed enough), but if anyone can provide the above format in LabVIEW code, I'd appreciate it.
Also, if it is already included within the code and I have missed it, apologies.
Thanks
I discovered where I was going wrong.
I'm sure this isn't very easy to follow, but I did want to follow up and mention that I found a solution to my problem.
If anyone knows of a better way than this, particularly that of having to create "constructor" vi's, I'd like to know.
Hi Elijah,
The last link in the "Application Example" is a broken link (Hardware Abstraction Layer). I'm not able to find it on NI's website.
Would you please update it?
Regards
I believe that most of the links above moved to the LabVIEW Development Best Practices Documents page here:
https://forums.ni.com/t5/LabVIEW-Development-Best/tkb-p/7305
the link for pattern gives me error. Are there any new links?