Write your LabVIEW code so that it breaks

Posted on Tuesday 19 June 2007

broken_run_arrow.pngOne thing that I try to do when writing LabVIEW code, is to craft it in such a way that it breaks during just the right editing circumstances. I know that it might sound crazy, but it’s true.

You probably know that LabVIEW is a very strictly typed language. For example, when you try to wire two dissimilar data types together, the wire breaks. This is the LabVIEW editor telling you that the requested operation will not work. Now, aren’t you glad that LabVIEW tells you this while you’re editing the code, rather than when you’re running it! What if LabVIEW waited until you ran the code and then, only when the data flowed into the differently typed wire, a crazy error message popped up that said “runtime exception: illegal operation converting a Boolean to a cluster” (or something like that). And, what if this error didn’t show up until the code was shipped to the customer! Yes, LabVIEW’s strict typing is a great thing.

We can also use strict typing in clever ways that are not exactly obvious. One great way that we can use this behavior is to tell us when a code maintenance task is not complete. Here’s an specific example: let’s say that you have three types of hardware that are defined by an enumeration with values Serial and TCP-IP. In your code you have this enumeration wired to a Case Structure that switches between the two different frames — each frame handling the respective communication mechanism. And then, one day your customer calls you says that they just heard about this great new technology called Bluetooth and they just have to have support for it in their code. And you, being the agreeable developer, say, “Sure thing. I’ll add that right away.” So, you go and modify the enumeration, adding a third value called “Bluetooth” and you’re done, right? Of course not, now you have to go modify every location in your code that relies on the value of that enumeration to do the work of communicating via Bluetooth. But, where do you begin? You recall that you have a read function and a write function, so you go in there and you add the code. Are you done? Maybe, but maybe not. How do you know? Much much testing should you do? Do you ship the code?

enum_case.png

What if there were a way to know every location where you need to add code to support the new Bluetooth functionality? Well, there is a way. Simply write your code in a way that, when elements are added to the enumeration, something causes a break in your code in exactly the locations where you need to add new code. For example, if you have the enumeration wired into a Case Structure’s case selector terminal. If you define a default value for the case structure, then the default frame will automatically handle it. However, if you ultimately intend to add one case for every enumeration value, then what you have is a bug. If you had not defined any default case, then your case structure would have broken and LabVIEW would have shown you the error messages shown, below. This would mean that you would be able to let LabVIEW show you exactly where you needed to do the necessary changes to your code.

So, write your LabVIEW code so that it breaks on just the right occasions.

edit_time_error.png


11 Comments for 'Write your LabVIEW code so that it breaks'

  1.  
    Götz Becker
    June 19, 2007 | 3:09 am
     

    Good hint. I usually disable the “Default” flag at every Case structure I place. Which is a bit of a pain since every time I place a new Case in my code LV enables “Default”. An option to change this behavior would be nice.

  2.  
    June 19, 2007 | 6:59 am
     

    Götz: Yes, I wish there were an option to place Case Structures without default frames. That would be nice :) Thanks.

  3.  
    Ray Farmer
    June 19, 2007 | 7:28 am
     

    That’s a good hint.

  4.  
    Yen
    June 19, 2007 | 7:44 am
     

    That’s a shame, I wanted to make a nugget out of that idea. :-(

    P.S. Case structures without default frames – Create an empty VI, place a case structure into it, wire a numeric into it, remove the default case and the numeric, save the VI and use it as a merge VI. Job done (although you then have to manually set the structure’s size after you drop it).

  5.  
    June 19, 2007 | 9:06 am
     

    Yen: You should still write a nugget — there is a lot more that can be said, and you can reference this article, if you like :) That’s a good tip about the merge VI — I was thinking the same thing. Perhaps we need an OpenG Structures palette.

  6.  
    Yen
    June 19, 2007 | 9:10 am
     

    “Perhaps we need an OpenG Structures palette”.

    Yes.
    Although some of structures I added to my own structures palette are no longer needed because they already made it into the standard palette (disable structure, ************ [can't talk about that one]), some are still useful today. I wouldn’t mind contributing to that.

  7.  
    June 19, 2007 | 9:17 am
     

    Yen: I’ve created a discussion topic, here, on the OpenG forums for discussing the OpenG Structure palette idea. Let’s move this discussion, there — I’m looking forward to seeing where it goes :)

  8.  
    June 19, 2007 | 10:54 am
     

    Actually I think one should avoid software architectures where support for particular specialization of a general interface is spread around different parts of code. I prefer using OOP design to solve these kinds of development issues. So the trick was nice but the example you used enourages using bad software architectures.

  9.  
    Darren
    June 19, 2007 | 11:58 am
     

    There is at least one situation where removing the default from enum case structures is a bad idea…and that is when your code is using an enum maintained by someone else. I recently had a showstopper bug in one of my products (that I inherited from someone else) because another developer added elements to an enum that my code used…the previous owner of this code used a Case Structure with no default case, so this code that I own was broken as a result of someone else’s change to the enum. So when there’s a chance somebody else might change an enum that your (shipping) code uses, in my opinion it is best to have a Default case that gracefully handles situations where an unknown enum element is encountered.

  10.  
    June 19, 2007 | 1:03 pm
     

    Tomi: You are correct in that the communication bus (GPIB, Serial, Bluetooth) example would be much better served by OOP polymorphism. I even thought about this while writing the article, but I figured that it would be a good example that many people could understand. Also, maybe it would be a good candidate for a follow-up article on the topic of OOP polymorphism vs. Case Structure switching ;)

    Darren: I guess it depends on the desired outcome of what should happen when the enum changes. Do you want your code to generate a run-time error when an unknown enum is passed in? Then use a default case and raise an error from within the default case. Or, maybe you do not want to generate an error. Or, perhaps you want to actually handle the unknown enum value and you want your code to break when the enum changes. It really depends on the requirements and how you want to manage things. You’re right that there are a lot of different situations where any one solution is preferable.

  11.  
    moham
    March 30, 2009 | 9:15 pm
     

    hi i wnat blootooth toolbox plz help me
    i am in a trouble

Leave a comment

(required)

(required)


Information for comment users
Line and paragraph breaks are implemented automatically. Your e-mail address is never displayed. Please consider what you're posting.

Use the buttons below to customise your comment.


RSS feed for comments on this post |

 

Bad Behavior has blocked 668 access attempts in the last 7 days.