Presentation is loading. Please wait.

Presentation is loading. Please wait.

Introduction to Basic LabVIEW Design Patterns

Similar presentations


Presentation on theme: "Introduction to Basic LabVIEW Design Patterns"— Presentation transcript:

1 Introduction to Basic LabVIEW Design Patterns
Elijah Kerry – LabVIEW Product Manager Certified LabVIEW Architect (CLA)

2 What is a Design Pattern?
Definition: A well-established solution to a common problem. Why Should I Use One? Save time and improve the longevity and readability of your code. … or else…

3 “This is honestly one of my favorite slides to show, because I think most of us here (myself included) can probably relate to seeing a diagram that looks something like this. In the spirit of not calling anyone out, we’ll assume that we’ve all inherited or been given these diagrams by people who aren’t in this room. Right off the bat, we should recognize a lot of major problems… there is no obvious design pattern, no documentation, no VI icons, wires crossing wires, etc. In spite of all that, the absolute worst aspect of this diagram, the thing I hate the most… is that this code actually runs. This program is actually a working program…. So what happens when someone hands us this program and says, ‘I need you to fix a bug or add a feature?’ It sounds simple to them, because they don’t realize how poorly written this code is and now it’s up to you to either work nights and weekends to figure it out, or convince them that the application really needs to be completely re-factored. This is why it’s so important that we be able to measure and analyze the quality of code, gauge the skill-level of our developers, and that we have established style-guidelines and coding practices within our team to enforce standard design patterns.” <<build slide>> “This diagram illustrates what our code should look like (it’s not totally perfect, but it definitely lends itself to reuse and longevity. It uses a highly-recignizeable producer/consumer design pattern, has a proper amount of documentation, it’s easy to follow the wires, VIs have icons, etc.. So the topics discussed in this presentation are intended to help us write code that looks more like this and recognize when someone writes awful code like we just saw in the previous diagram.” “One final note: I find that when someone writes a bad C program.. Everyone instantly knows that it’s the C programmer’s fault. However, when someone writes bad LabVIEW code, LabVIEW tends to get blamed. One very important thing to remember is that graphical code is a programming language just like any other, and as such, we need to be sure to apply the same software engineering practices.”

4 Examples of Software Engineering Debt (just some of the most common LabVIEW development mistakes)
No source code control (or Project) Flat file hierarchy ‘Stop’ isn’t tested regularly Wait until the ‘end’ of a project to build an application Few specifications / documentation / requirements No ‘buddying’ or code reviews Poor planning (Lack of consideration for SMoRES) No test plans Poor error handling No consistent style Tight coupling, poor cohesion The point of this slide is to get the audience to do a reality check regarding the level of sophistication of their own development practices. Keep in mind that it is in the introduction of other presentations, but in this case it serves as a preface to a discussion on architectures. That is why the ‘Lack of SMoRES’ bullet is highlighted, as it will be the stepping-stone for today’s discussion. For more information and technical resources on the other topics, encourage the audience to visit ni.com/largeapps. These are all common examples that can lead to the duct-tape and hot-glue diagram like the one we just saw. As engineers, we all appreciate the cost of cutting-corners or taking a short-cut… it may get us there sooner, but at what cost? In the world of software, there’s a concept known as ‘Software Engineering Debt.’ If we cut corners, we take on more debt, and these are all examples of how we do that. The more debt we take on, the more interest we accumulate over time, and as we’ve all seen in the recent years, that debt can quickly pile up and accumulate a mountain of interest, making it more expense the longer we wait. If we wait to pay down that debt until after we release a version of the software to our customer, it’s going to painful and the bugs will be much more costly than if we’d caught them up front. The practices we’ll look at in this presentation will help address most, if not all of these, but do want to mention a few right now. (I recommend picking a few to really emphasize… here is some additional information on each to allow you to decide No source code control (or Project) – if you’re not using it, you’re playing with fire. Even for a small project with one developer, these tools can save you a tremendous amount of time and heartache. Flat file hierarchy – ever had trouble identifying the top-level VI in an application? It’s not just an organizational problem, it indicates a lack of encapsulation and proper design. Use folders, encapsulate your code and make APIs obvious from private subVIs ‘Stop’ isn’t tested regularly – there are lots of ways to assess the health of an application, but this is an easy one that you should always be thinking about. A new feature is no good if it impedes expected behavior and one key indicator is whether or not the application still stops instantly when asked to Wait until the ‘end’ of a project to build an application – if you’re one of those that waited until you were ‘done’ to build an exe for the first time, you’re probably a long ways away from done. The reality is that, as with any language, a lot of things change in the RTE, and you need to test this on a regular basis Few specifications / documentation / requirements – this is perhaps the most common mistake and the easiest way to ensure that code is not reusable or maintainable No ‘buddying’ or code reviews – sometimes the mere act of explaining your code to someone else finds major problems or bugs… do it, and do it often Poor planning (Lack of consideration for SMoRES) – This acronym stands for ‘Scalable,’ ‘Modular,’ ‘Reusable,’ ‘Extensible,’ and ‘Simple.’ No test plans – you can’t test code if you don’t define how it should behave. Poor error handling – does it stop? Does it tell the user an error? Does it log the error? If you don’t plan for this early, a simple error can lead to even more problems No consistent style = not readible, not maintainable Tight coupling, poor cohesion – impedes reuse A lot of us are under pressure to get things done quickly and to hit aggressive deadlines, but there are a few practices that if we invest in early, will pay dividends down the road. Any are all of these are topics I’m happy to talk about in-depth. In fact, if you’re interested, we can arrange a presentation for you and your colleagues on any of these that you're interested in. ni.com/largeapps

5 Designing for SMoRES Scalable: how simple is N + 1?
Criteria for a well designed software application: Scalable: how simple is N + 1? Modular: is the application broken up into well-defined components that stand on their own? Reusable: is the code de-coupled from the current application well-enough such that it could be reused in a future project? Extensible: how painful is it to add new functionality? Simple: what is the simplest solution that satisfies all of the listed criteria and the requirements of the application? This should be fairly self-explanatory, but emphasize that our goal is to balance all of these criteria as we make design decisions about our code and our application.

6 You Should Already Be Familiar With..
Loops Shift Registers Case Structures Enumerated Constants Event Structures LabVIEW Classes This slide should be extremely quick. The audience is likely already familiar with all of these items, but we want to make sure everyone has these ‘tools in their toolbelt.’ The most likely exception to this are LabVIEW classes, but explain that we’ll expand on how these work later in this presentation. Build Loops – the two most common loops and the only ones we’ll need for this discussion are the for loop and while loop. The most significant difference is that the while loop iterates indefinitely until stopped, whereas a for loop always has a maximum number of iterations Shift registers – these are used instead of tunnels if you want to preserve data between iterations of a loop such as a for loop or while loop. On the for loop below I’ve used a set of stacked shift registers, which will remember values from previous iterations Case Structures – allow you to conditionally execute code depending upon an input, which can be a boolean, string, number, etc… if the input has infinite possibilities, you can set a default case. Enumerated constants – Allow you to enumerate integer values using words. This is commonly used to govern the case of a case structure instead of just a number. We’ll discuss these more later Event structures – are similar to case structures, but they interrupt data flow by responding to events that occur. We’ll talk more about this in a moment as well

7 Design Patterns Functional Global Variable State Machine / Statecharts
Event Driven User Interface Producer / Consumer Queued State Machine – Producer / Consumer We’ll start with a couple of simple design patterns and spend most of our time discussing the last two on this slide. I’ll try to go into low level detail on the last few and we’ll spend some time discussing variations of implementation and any other considerations.

8 Functional Global Variables
How do I share data across a application without using Global or Local Variables? For those of you who have taken LabVIEW training, or if you’re just familiar with good programming practices, we’re constantly advising customers to not use local or global variables. They introduce a number of inefficiencies that don’t scale well if used multiple times in a single application. However, sometimes you have to break data flow and you need to send data between independent processes, so how do you do it? Lets look at Functional Global Variables. They offer a number of advantages over local and global variables that will allow communication across your project without suffering from the same drawbacks as global and local variables.

9 Background: Global and Local Variables
Can cause race conditions Create copies of data in memory Cannot perform actions on data Cannot handle error wires

10 Breaking Down the Design Pattern
While loop Uninitialized shift registers have memory Case structure Enumerated control Before I show you a functional global variable I want to make sure that everyone understands a few nuances of the components that are required for a Functional Global Variable. We talked about loops and shift registers earlier, but functional global variables rely upon a property of shift registers that we haven’t yet discussed: Uninitialized shift registers can be used as a memory location When you assign a value to it, it doesn’t destroy or replace that data unless it is initialized or all callers are removed from memory Demo Open the “Explain Uninitialized Shift Registers.vi’ example program and follow the instructions on the block diagram FAQ they’ve been around since LabVIEW 2.0 Also commonly called a VIG (VI Global), Uninitialized Shift Register Global (USR Global), or Action Engine

11 Demo Uninitialized Shift Registers
From the Project Explorer run “Functional Global Variables >> 1 - Explain Uninitialized Shift Registers.vi” and follow the on-screen instructions Demo

12 Basic Actions Set the value of the shift register INITIALIZE
Now that you’ve demonstrated how uninitialized shift registers work, explain the basic working idea behind a fgv. This diagram shows how we can store a new value to the shift register INITIALIZE

13 Basic Actions Get the value currently stored in the shift register GET
Similarly, we can retrieve the value stored as shown GET

14 Action Engine Perform an operation upon stored value and save result
You can also output the new value ACTION Perhaps one of the most powerful aspects of a FGV is the ability to customize what actions are performed on the value stored in memory. The cloud in this diagram can represent any number of actions or computations that are to be performed upon any number of data-types ACTION

15 How It Works Functional Global Variable is a Non-Reentrant SubVI
Actions can be performed upon data Enumerator selects action Stores result in uninitialized shift register Loop only executes once A functional global VI is called as a subVI from your application. The only required parameter is the action to be performed. The initialize too can be passed in or be a constant Note that it only executes once because the stop button is always set to true

16 Demo Functional Global Variables
Uninitialized shift register has memory Loop only executes once Only used in Initialize case Functional Global Variables Action determines which case is executed Examples of other ‘actions’ Use the example VI to demonstrate initializing, incrementing and retrieving the value of a Functional Global Variable Demo

17 Benefits: Comparison Functional Global Variables
Global and Local Variables Prevent race conditions No copies of data Can behave like action engines Can handle error wires Take time to make Can cause race conditions Create copies of data in memory Cannot perform actions on data Cannot handle error wires Drag and drop We mentioned earlier in this presentation that FGV often make a good substit

18 Recommendations Use Cases Considerations
Communicate data between code without connecting wires Perform custom actions upon data while in storage Considerations All owning VIs must stay in memory Use clusters to reduce connector pane Using stacked shift registers will track multiple iterations If a single parent VI that owns the functional global is stopped, then the data in the USR is destroyed, even if other parents are still active in memory. If this is a problem, consider using a queue, which is not destroyed until all references to it are stopped. If using a FGR to manage complex data, use a cluster to reduce the amount of connectors used

19 State Machine I need to execute a sequence of events, but the order is determined programmatically

20 Soda Machine Soda costs $0.50 Initialize Wait Quarter Change Nickel
No input Wait Nickel Deposited Change Requested Quarter Deposited Dime Deposited Total < 50 Total < 50 Total < 50 Quarter Change Nickel Dime Total >= 50 Total >= 50 Total >= 50 Each state has decision making code inside of it. For example, if you consider the Quarter state, it examines the total amount of money that has been added. If it is equal to or greater than the amount owed, it sends the application to the ‘vend’ state; otherwise, it returns to wait Walk the audience through an example of execution of this application Total > 50 Vend Total = 50 Exit Soda costs $0.50

21 Background Static Sequence
Dynamic Sequence: Allows distinct states to operate in a programmatically determined sequence The diagram at the top is supposed to represent a diagram in which you always know the order of execution. The diagram below is meant to indicate that you will not know the order of execution until run-time. Each subVI has code inside of it that then determines what the next subVI will be. Allows you to execute code in an order determined at run-time

22 Breaking Down the Design Pattern
Case Structure inside of a While Loop Each case is a state Current state has decision making code that determines next state Use enumerators to pass value of next state to shift registers The standard LabVIEW state machine consists of a large while loop, a shift register to remember the current state, and a case structure that holds separate code to run for each state. (If you use an enum to pass around the value for the current state, the pattern becomes much easier to read – and if you use a typedef, you only need to edit the typedef once in order to add another state to the machine) Note that each frame in the case structure must contain code for deciding what state the process should go to next. I call this the “transition” code

23 The Anatomy of a State Machine
Transition code determines next state based on results of step execution Case structure has a case for every state FIRST STATE Step Execution Shift registers used to carry state Transition Code ? The state machine pattern is one of the most widely recognized and highly useful design patterns for LabVIEW. This pattern neatly implements any algorithm explicitly described by a state diagram (flow charts work too…). More precisely, it implements any algorithm described by a “Moore machine” – that is, a state machine which performs a specific action for each state in the diagram. (Contrast this with the “Mealy machine” which performs an action for each transition…) NEXT STATE FIRST STATE

24 Transition Code Options
Step Execution Step Execution Each of these case structures shows a different standard type of “transition code” – i.e. code that chooses the next state for the state machine. The top left code clearly shows that the “Init” state has only one transition, and hence goes directly to the “Power Up” state without making any decision at all. The top right code switches between two possible transitions – the “Init” state will go to the “Shut Down” state if the “Stop” button has been pressed, otherwise it goes to the “Power Up” state. The code at the bottom left is a little more complicated, but still a common LabVIEW construct. The code for this state returns an array of boolean values, one for each transition we could take. Along with that array of boolean values is another array of enum constants specifying the new states where each possible transition could go. The index of the first “True” boolean in the array corresponds to the index of the new state in the array of enums… (Well, almost, but you can figure out the details yourself – just remember that the “Search Array” function will return –1 if the value is not found). The code at the bottom right is functionally equivalent to the code to its left. It consists of a case structure embedded in a while loop. The case structure contains one diagram for each transition arrow that leaves the current state. Each of these diagrams has two outputs – a boolean value which specifies whether or not the transition should be taken, and an enumerated constant which specifies the state to which the transition goes. By using the loop index as input to the case structure, this code effectively runs through each transition diagram one by one, until it finds a diagram with a “TRUE” boolean output, and then outputs the new state to which that transition goes. (Note that it is important to make sure the last transition always outputs a TRUE value). Though this code may appear slightly more complicated than the code to the left, it does offer the ability to add names to transitions by “casting” the output of the loop index to an enumerated type. This allows you to add “automatic documentation” to your transition code… Step Execution

25 State Machine Run the example entitled “1-Coke Machine State Machine.vi” Use highlight execution to show how it moves between states in the same manner you illustrated earlier. In order to transition to the next design pattern, demonstrate how because it’s busy executing code, that the program can miss input (ie: rapid clicking on the dime will cause the program to piss the ‘depositing’ of several of the dimes) Demo

26 Recommendations Use Cases Considerations User interfaces
Data determines next routine Considerations Creating an effective State Machine requires the designer to make a table of possible states. State machines are common in applications that are basing decision making off of input from a user. Since your application can’t predict the next input from the user, a state machine can be implemented to go to certain states and thereby execute specific code based upon the input from a user while in a certain state.

27 Event Driven User Interface
I’m polling for user actions, which is slowing my application down, and sometimes I don’t detect them! The next design pattern is commonly used to interact with user input via the front panel. The concept of event driven programming is very important when developing large applications that have to be responsive to user input. Before we get into that, lets look at the alternatives to give us some background

28 Background Procedural-driven programming Event-driven programming
Set of instructions are performed in sequence Requires polling to capture events Cannot determine order of multiple events Event-driven programming Execution determined at run-time Waits for events to occur without consuming CPU Remembers order of multiple events Without the ability to respond to events that occur immediately, programmers are forced to use procedural-driven programming to regularly check for input or check the value of a control. This typically entails encapsulating code within a constant loop that monitors for a change in value and then executes code accordingly. Ideally, the loop would execute fast enough that it doesn’t miss any input. However, there are several significant draw-backs to this methodology: A constantly running loop consumes CPU time and takes away resources from other things you might want your application to be doing If an event is detected and code is still being executed while a new event occur, the new value may not be polled and therefore it would never be detected by the program Multiple changes in value could occur while one particular case is executing. When the loop iterates and polls the values it will not know which one was pressed first. Verbal example of when this might be a problem: Imagine a User Interface that has buttons for acquire, log to file and quit The user presses the acquire button, and while the data is being read clicks ‘log to file’ and then ‘quit’ If these values are detected by the polling at the same time it has no way of knowing which one occurred first and it essentially has to guess, which, as you can image, can easily lead to unexpected behavior

29 Breaking Down the Design Pattern
Event structure nested within loop Blocking function until event registered or timeout Events that can be registered: Notify events are only for interactions with the front panel Dynamic events allows programmatic registration Filter events allow you to screen events before they’re processed

30 How It Works Operating system broadcasts system events (mouse click, keyboard, etc..) to applications Registered events are captured by event structure and executes appropriate case Event structure returns information about event to case Event structure enqueues events that occur while it’s busy Events are broadcast by OS and responded to by applications Event structure enqueues events that occur while executing.. Hence why you know the order

31 How It Works: Static Binding
Browse controls Browse events per control Green arrow: notify Red arrow: filter

32 Event Driven User Interface
Demo

33 Recommendations Use Cases Considerations UI: Conserve CPU usage
UI: Ensure you never miss an event Drive slave processes Considerations Avoid placing two Event structures in one loop Remember to read the terminal of a latched Boolean control in its Value Change event case When using subpanel controls, the top-level VI containing the subpanel control handles the event Avoid using an Event structure outside a loop. Remember to read the terminal of a latched Boolean control in its Value Change event case. Use a Case structure to handle undo operations for a latched Boolean control. Use caution when you configure one case to handle multiple notify events. You cannot configure one case to handle multiple filter events with different event data. If a While Loop that contains an Event structure terminates based on the value of a latched stop Boolean control, remember to handle the latched stop Boolean control in the Event structure. Consider using the Wait for Front Panel Activity function if you do not need to monitor specific front panel objects programmatically. User interface events apply only to direct user interaction. Avoid using dialog boxes in an event case with the Mouse Down? filter event. When using dynamic registration, make sure you have a Register For Events function for each Event structure. When using subpanel controls, the top-level VI containing the subpanel control handles the event. Use caution when selecting between a notify or filter event. An event case configured to handle a notify event cannot affect if or how LabVIEW processes a user interaction. If you want to modify if or how LabVIEW processes a user interaction, use a filter event. Do not use the Panel Close notify event for important shutdown code unless you have taken steps to ensure that the VI does not abort when the panel closes. For example, be sure the application opens a reference to the VI before a user can close the front panel. Alternatively, you can use the Panel Close? filter event, which occurs before the panel actually closes.

34 Producer / Consumer I have two processes that need to execute at the same time, and I need to make sure one can’t slow the other down

35 Background I want to execute code in parallel and at asynchronous rates, but I need to communicate between them! I have two processes that need to execute at the same time, but I want them to be independent of one another, and I need to make sure one can’t slow the other down

36 Breaking Down the Design Pattern
Data independent loops Master / slave relationship Communication and synchronization between loops

37 How It Works Master Slave 1 Slave 2
One or more slave loops are told by a master loop when they can run Allows for a-synchronous execution of loops Data-independence breaks dataflow and allows multi-threading De-couples processes Slave 1 This gives you more control on how your application is timed, and gives the user more control over your application. Counterexample: Data-acquisition and data-logging in the same loop. It would be difficult to increase the rate of DAQ without increasing rate of data logging. If they are separate of each other then this is easier to do The standard Master/Slave design pattern approach for this application would be to put the acquisition processes into two separate loops (slave loops), both driven by a master loop that polls the user interface (UI) controls to see if the parameters have been changed. To communicate with the slave loops, the master loop writes to local variables. This will ensure that each acquisition process will not affect the other, and that any delays caused by the user interface (for example, bringing up a dialog) will not delay any iteration of the acquisition processes. Define data dependency: Loop B is dependent upon Loop A if any of Loop B inputs require values from loop A outputs Slave 2

38 Master / Slave: Loop Communication
Variables Occurrences Notifier Queues Semaphores Rendezvous Now that we’ve discussed the concept of having multiple loops for separate processes, lets talk about how we can bridge those loops in order to communicate without creating any data-dependency. There are a number of different mechanisms we can use depending upon the communication required. For synchronization and timing an occurance or rendezous are helpful. We’re going to focus on the use of queues Notifier Operations Functions Use the Notifier Operations functions to suspend the execution of a block diagram until you receive data from another section of the block diagram or from another VI running in the same application instance. Occurrences Functions Use the Occurrences functions to control separate, synchronous activities. Queue Operations Functions Use the Queue Operations functions to create a queue for communicating data between sections of a block diagram or from another VI. Rendezvous VIs Use the Rendezvous VIs to synchronize two or more separate, parallel tasks at specific points of execution. Each task that reaches the rendezvous waits until the specified number of tasks are waiting, at which point all tasks proceed with execution. Semaphore VIs Use the Semaphore VIs to limit the number of tasks that can simultaneously operate on a shared (protected) resource. A protected resource or critical section of code might include writing to global variables or communicating with external instruments.

39 Queues Adding Elements to the Queue De-queueing Elements
Select the data-type the queue will hold Reference to existing queue in memory De-queueing Elements Subsequent and repeated implementation of this same code will grab an existing queue reference of the specified name. This is typically done to give access of queue reference to subVIs which also avoids The typedef enumerated constant enlists your chosen names of the state machine cases in the consumer process. Each time a command is added to the queue, the enum should be set to the machine’s STATE name which will handle or process the command. Therefore, the type-def STATE items are like command names that designate which state name contains the relevant code for processing the command. Typical function enum state names: ‘INITIALIZE’, ‘IDLE’, ‘ERROR’, and ‘EXIT’ should be included. the need to wire a queue reference to the subVI. You must ensure that the enum constant is a copy of a typedef-based custom control so that you can add or remove command items from the enum and have your changes propagated to all instances of the typedef constant throughout your LabVIEW code. Dequeue will wait for data or timeout (defaults to -1)

40 Producer / Consumer

41 Producer / Consumer Demo

42 Recommendations Use cases Handling multiple processes simultaneously
Asynchronous operation of loops Considerations Multiple producers  One consumer One queue per consumer If order of execution of parallel loop is critical, use occurrences

43 Queued State Machine & Event-Driven Producer / Consumer
I need to enqueue events from a user that control the sequence of events in a consumer loop I want to execute code in parallel and at asynchronous rates, but I need to communicate between them! I have two processes that need to execute at the same time, but I want them to be independent of one another, and I need to make sure one can’t slow the other down My front panel freezes while my event structure is handling an event it received

44 Breaking Down the Design Pattern
Event-driven user interface design pattern State machine design pattern Producer consumer design pattern Queued communication between loops Before I show you a functional global variable I want to make sure that everyone understands a few nuances of the components that are required for a Functional Global Variable. We talked about loops and shift registers earlier, but functional global variables rely upon a property of shift registers that we haven’t yet discussed: Uninitialized shift registers can be used as a memory location When you assign a value to it, it doesn’t destroy or replace that data unless it is initialized or all callers are removed from memory Demo Open the “Explain Uninitialized Shift Registers.vi’ example program and follow the instructions on the block diagram FAQ they’ve been around since LabVIEW 2.0 Also commonly called a VIG (VI Global), Uninitialized Shift Register Global (USR Global), or Action Engine

45 User Interface Producer
How It Works Event-driven User Interface Producer Events are captured by producer Producer places data on the queue State machine in consumer executes on dequeued data Parallel SubVIs communicate using queue references State Machine Consumer Parallel SubVI 1 Parallel SubVI 2 Parallel SubVI 3

46 Queues Recommendations
Refer to queues by name for communication across VIs Use a cluster containing an enum and variant as data-type

47 This is an example of an implementation of the QSM-P/C Design Pattern
This is an example of an implementation of the QSM-P/C Design Pattern. I have an example to show you, but I wanted to blow out certain parts of the block diagram to help you understand how it works. (note: the actual block diagram may not fit on a projector screen)

48 Master Queue Main point: A queue entitled ‘Main queue’ is used to establish communication between the producer and consumer. The first state ‘initialize’ is enqueued when the program first starts.

49 Event-Driven Producer Loop
The Producer is driven by user events. Different states are added to the queue depending upon user input.

50 State and Data are Enqueued
Note that data is en-queued in the form of state and variant. When the consumer de-queues the cluster, it is responsible for interpreting the state and knowing what kind of data to expect in the variant.

51 State Machine Consumer
The consumer is a state machine, so the decision making code enqueues new data instead of using an enumerator.

52 Additional Queues (Q1 and Q2)
Because we want to have multiple consumers we need additional queues. This code uses a cluster constant that contains (amongst other things) the two additional queues we’ll use for communication with other consumers.

53 States ‘Produce’ to Additional Queues
The consumer adds data to Q1 and Q2 in states that need to communicate with additional consumers (ie: SubVI1 and SubVI2)

54 Queue Manager The Queue manager is used throughout the application to add events to a queue

55 SubVIs Consume Data from Q1 and Q2
We can pass information to the subVIs in this application without explicitly passing a queue reference. We accomplish this by referencing the queue by name in the subVIs

56 Queued State Machine – Producer/Consumer
Demo

57 Recommendations Use Cases
Popular design pattern for mid to large size applications Highly responsive user interfaces Multithreaded applications De-coupling of processes Considerations Complex design This is a very popular design pattern and we see variations of it used in a number of settings. It combines principles we’ve discussed in every previous architecture to yield a very powerful and extremely scalable design.

58 Adding Your Own Design Patterns
C:\Program Files\National Instruments\LabVIEW 8.5\templates\Frameworks\DesignPatterns

59 Resources Example Finder New >> Frameworks Ni.com/labview/power
Training LabVIEW Intermediate I & II White Paper on LabVIEW Queued State Machine Architecture Expressionflow.com

60 NI Certifications Align with Training
Developer Senior Developer Software Architect / Project Manager Certified LabVIEW Associate Developer Exam Certified LabVIEW Developer Exam Certified LabVIEW Architect Exam LabVIEW Core 1 LabVIEW Core 2 LabVIEW Core 3 Advanced Architectures for LabVIEW Managing Software Engineering in LabVIEW There is a close link between training and certification. Certification is a quantifiable way of ensuring individuals have developed the skills need to create applications. NI also offers certifications for LabWindows/CVI and TestStand "Certification is an absolute must for anyone serious about calling himself a LabVIEW expert... At our organization, we require that every LabVIEW developer be on a professional path to become a Certified LabVIEW Architect." - President, JKI Software, Inc.

61 Download Examples and Slides
ni.com/largeapps Software Engineering Tools Development Practices LargeApp Community This is the questions slide – keep this up to encourage them all to write down the URL at the top of the screen


Download ppt "Introduction to Basic LabVIEW Design Patterns"

Similar presentations


Ads by Google