LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Help improve my style and quality of LabVIEW coding



Mark Yedinak wrote:

OK, I did take a look at the code now. HEre are some additional points to consider.

  1. Document, document, document. None of your controls or indicators are documented. Also, document your code more to help someone looking at it to actually understand it better.
  2. Definitely avoid the use of all of the local variables. Thing of a design pattern that separates the processing tasks from the UI. If you have one task handling the UI you really don't need to use local variables.
  3. Avoid unnecessary bends in your wires.
  4. Definitely get your block diagram to fit on a smaller screen. These days it shouldn't be larger than 1600x1200 or close to that.
  5. Modularize your code. Use more subVIs
  6. You have a classic off by one error in your code. All of your loops use the stop button to exit. However you always check the value at the beginning of the loop iteration therefore you will execute the loop one more time than necessary.
  7. Avoid unnecessary frame structures. You have a frame structure in the second loop that does nothing for you. Everything down stream of it will execute in the correct order because of the data dependencies. The frame structure serves no purpose here.
  8. Try to avoid deeply nested case structures. Once I start to see that happening in my code I rethink my logic. At a minimum I would build an array of the various Boolean values and convert them into a number and use that to chose the appropriate case to execute rather than nesting three or more case structures.

How can I accomplish all the tasks in my application without the use of local variables? I admit, this is the main reason I opened this thread ... Because I have tried to imagine a design architecture that would work without local variable, but was unsuccessful. Can someone please explain in detail how to do this on this specific application.

  • Learn to use the different design patterns. A state machine with shift registers can eliminate the need for lots of local variables. Create an API between parallel tasks and use appropriate structures to pass the data such as queues or action engines. Local variables couple your code together and make it much more difficult to reuse. In order to reuse it you have to bring all the necessary local variables along. They may not make sense in a different application. Their names may be meaningless. If you create an API it is much easier to reuse the code or tasks. It also makes it easier to modify one side of it such as the user interface but still reuse the processing tasks. For very large data sets an action engine works well since you only have one copy of the data. However it provides some protection so you avoid some of the race conditions that can occur with local variables.

I will try, but I make my block diagram to the width of my screen, but vertically I do not limit its size - so I can easily scroll up and down to move around.

  • If you can't see the code you can't really understand it all. If you have to scroll things around just to see the whole picture you can't really see the big picture. It makes it more difficult to understand and debug. My rule of thumb is if I do scroll it is only in one direction and any single concept of the code visible is fully visible. For example the top level VI for a user interface may scroll horizontally but is comprise of three main parts. The screen would be the initialization code. Then scroll over and the main body of code would be visible. Scroll again and it would be the cleanup or exit code. I can position the block diagram to have all the related code visible on one screen yet the overall block diagram is larger.
I try to create as many subVI as possible, but only on code that is reusable on other projects. Is also better to have a lot of single use subVIs with every project? Doesn't this add unnecessary overhead and slows the application?
  • You can create a subVI for more than reuse. A subVI allows you to encapsulate some piece of functionality so that your higher level block diagram becomes more readable. A well named and documented subVI helps to make the calling block diagram more readable. Hover over it and the context help gives a brief description of what is being done. I may not need to see the details. If I do though I can open the subVI. Also, the more you use subVIs the more you can build up a library of reusable code. However, don't create the subVI only to reduce the block diagram size. It should perform some useful and defined task. Create the subVI (even if it won't be used often) to encapsulate some specific functionality to make the calling code more readable and easier to understand. Let's say I have some piece of code that needs to iterate over some data set and pick out certain pieces. I only use this in one place but the code is fairly complex. At the higher level a subVI with the name "Filter x records" or "Select Y Records" easily tells the person looking at the code what is happening and takes only a small part of the block diagram. If this functionality is in the middle of other complex tasks the overall block diagram becomes to cluttered and difficult to understand. By encapsulating the various pieces of functionality the code is much more understandable.
  • Another concept to consider is to use LVOOP. Objects are a great way to describe a system and a well defined class helps to make the overall application easier to understand. The work being performed is encapsulated in small units.

What would be the correct way to stop the application?

  • In this particular case it was not so much that you used the local variable but when you actually checked the value. Yes, it was placed in the lower right hand corner and you may think since it is on the right side you read the value after the main block of code. However 99.99% of the time it is one of the first things done when you enter that loop. The easiest way to solve this problem is to simply put the local variable in a single frame and wire the error out (or some other output of the main block of code within the loop) to force checking the value of the stop button to occur AFTER the iteration has completed. This will avoid executing the loop one too many times.
  • An even better solution is to define a very small library specifically for controlling the exit of parallel loops. An action engine is a good choice here. A LVOOP class is another. By doing so you now have a nice reusable piece of code for your other applications and your code becomes more consistent. Anyone looking at your code starts to recognize common methods of doing things and they can then focus on looking at the specific application and not your methods of controlling parallel tasks. Your applications have a consistent way of doing that since you use your library.


Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 11 of 13
(420 Views)

Thank you MARK!

One kudos does not seam sufficient to congatulate you on that article!  Well stated!

 

"If you can't see the code you can't really understand it all"  belongs in the proverbs thread


"Should be" isn't "Is" -Jay
Message 12 of 13
(412 Views)

@Jeff Bohrer wrote:

Thank you MARK!

One kudos does not seam sufficient to congatulate you on that article!  Well stated!

 

"If you can't see the code you can't really understand it all"  belongs in the proverbs thread


You're welcome Jeff. Always glad to lend a hand.



Mark Yedinak
Certified LabVIEW Architect
LabVIEW Champion

"Does anyone know where the love of God goes when the waves turn the minutes to hours?"
Wreck of the Edmund Fitzgerald - Gordon Lightfoot
Message 13 of 13
(407 Views)