Random Ramblings on LabVIEW Design

Community Browser
Labels
cancel
Showing results for 
Search instead for 
Did you mean: 

Your Block Diagram Should Be "At a glance readable"

Active Participant

Hello My Beauties,

This ol' blog is approaching a 1/3 million views now, which is a daft number.

 

A while back I tweeted the following

Tweet.png

The point I was trying to make was that some terms are used in software engineering that are not testable. So code must be readable, maintainable blah blah blah. But how do we quantify them? Let's look at readable. 

 

"Code must be readable", unless you make everything invisible, code is always readable. Actually what we really need is code to be easy to read or I prefer at a glance readable.

 

How do we go from readable to at a glance readable? Here's some things we do.

 

Diagrams work best with annotation.

Here's a fairly typical bit of SSDC code, from a design perspective it could probably be a little more abstract*, but it's a pretty good example of the amount of functional commenting we do. This effort allows us to understand the purpose of the BD without going anywhere else.

*SQL shouldn't be visible on the block diagram as this is detail, but the code needed to be light, so we sacrificed a layer.

BlockDiagram.png

Left to right...

  1. Cluster Element Naming.
  2. Select statement with formatting.
  3. Some good old fashioned intent comments.
  4. Enumerated commands add detail to the icon of the subVI - we know we're using a fetch query
  5. Constant Labelling, for columns and rows on arrays this is really helpful.
  6. There's a fair bit of code before the case structure, so added a label just to reiterate.
  7. True and False Colour coding using subdiagram labels.
  8. Another subdiagram label just to clarify whether we update and existing or insert a new.

This can also apply to front panels, you shouldn't need to guess what is an input and output.

FrontPanel.png

 

Language is important

I know it's hard to believe but I hated English at school, but actually the mechanisms of language are becoming much more useful to my design work.

 

Noun - a thing <-- what a good object, component or actor is. [Multimeter]

Verb - an action <-- Methods and messages. Things you do to an object. [Measure]

Present Participle - Continuous form of a verb <-- The state of the process (state in a state machine).[Idling]

Command Verb -  A verb used to tell the computer to do something <-- Transition.[Exit]

 

Cohesion is Important

The biggest problem I run into is lack of cohesion and the issues are commonly as follows.

Not enough functionality - Take calibration for example, to my mind this is 1 VI, you pre-load it channel names and equations. Then input raw numbers and it outputs calibrated numbers.

Calibrate.png

To my mind anything more is less readable (as well as being difficult to maintain).

 

VIs that Lie - something is not cohesive because it shares 90% of the data with another function, if you look at a VI and it does more than it promises that's an issue. An example is a VI that takes a query and formats to a table, you may then be tempted to use the query data to do other stuff and your FormatQueryToTable.vi becomes FormatQueryToTableAndLoadCalData.vi. 

 

I'll be touching on more of this in my NIWeek 2019 presentations.

 

Program Slow, Debug Fast

Lots of Love

 

 

Comments
Active Participant

Steve,

An excellent post, as usual.

 

Although VI Analyzer cannot measure the quality of the comments and annotations, you can run VI Analyzer tests to ensure all the constants are labeled, all your structures have subdiagram labels and that all your VIs have at least one comment label. Starting with LabVIEW 2018, you can ignore tests that don't apply to a VI with labels.

 

That is all great to measure the quality of the code or to remind us how to be better programmers or to invite junior developers to implement good programming practices. However, understanding why we are asking programmers to go through this level of detail in their code is important. Otherwise, we end up with what Allen Smith calls "VI Analyzer pacifiers", which are labels and code just for the sake of passing the VI Analyzer test. That is not the way to do it, this post is going to be what I point people to when they start complaining about some VI Analyzer tests that check for proper documentation on a VI.

 

I was told once that I add too many comments and that the labels on constants add noise. My reply was that code that runs doesn't lie but it cannot include intent. Once the code is out there, I cannot add my thought process to it. I have been thinking on writing a Quick Drop tool that would make all the labels and comments transparent and then bring them back to their color, just so someone that wants to hide momentarily all the comments, could do that, I am just afraid someone would save the VI like that! It would be great if we could turn on/off layers of the block diagram, where all the comments are on one layer. 

 

There are still programmers who push back to the creation of too many subVIs, just inline them and forget about whatever performance hit you might get for creating a subVI. Your naming test is a good one if you feel the need to add the word AND to the name of your VI, your VI is doing too much.

 

I cannot wait for your NIWeek presentation, there will be lots of good information in it.

 

Thanks for sharing your wisdom with us.

Fab

Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor
Active Participant

Fab, 

            Comments on constants are awesome!  I have them automatically turned on in the LabVIEW options. Although you still have to go change them, because the default labels are pretty generic, but at least it reminds you.

Sam

Sam Taggart
CLA, CPI, LabVIEW Champion
DQMH Trusted Advisor
automatedenver.com
Active Participant

Blatant advertisement for my "Subdiagram labels" VI Analyzer test, because I'm quite happy with it:

https://forums.ni.com/t5/VI-Analyzer-Enthusiasts/Test-Subdiagram-Labels/ta-p/3739097

 

"This test fails if subdiagram labels in Case Structures, Event Structures, Disable Structures or for and while loops are not visible. It optionally fails also if subdiagram labels are visible but empty."

 

Also, if you read the comments on the test, it's just hilarious how much room for improvement Darren found in my simple VI!


Joerg Hampel | CLA, LabVIEW Champion, DQMH Trusted Advisor | hampel-soft.com | alarchitects.org
Active Participant

That's it! I'm banning product placement in my comments.

 

This message was brought to you by

 

Giblets for Dogs

Gibletty goodness, but just for your dog

Active Participant

I just realised, I forgot to think up ways of monetising it before placing the ad!


Joerg Hampel | CLA, LabVIEW Champion, DQMH Trusted Advisor | hampel-soft.com | alarchitects.org
Active Participant

I guess it is too late to mention the Delacor custom VI Analyzer Tests package....

 

Smiley Wink

Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor
Active Participant
Active Participant

@swatts wrote:

 

BlockDiagram.pngEnumerated commands add detail to the icon of the subVI - we know we're using a fetch query

 


A wider set of more focused API functions can also help with readability.  You could improve things here with a "Fetch Row" function that returns a 1-D array, rather than 2-D.  This would make it more clear that you are fetching only one row, and would simplify and clarify the downstream indexing considerably.

 

Also, though I'm poor at commenting, I always try and format SQL for readability, such as left-justifying and using indentation.   I would format your first SQL statements as:

 

SELECT data, dataStatus
   FROM received_data
   WHERE data_tag = "%s" //note: data_tag is unique

 

I threw in a comment to point out that SQL statements can be commented.  I am generally poor at commenting, but I heavily comment the Schema SQL statements, such as "CREATE...", as with SQLite these comments become part of the database file and can be read from any SQLite viewer utility.  Thus these comments are doubly useful, as both code and data documentation.

Active Participant

I don't comment my SQL. Mainly because I'm lazy and I use a tool to create it. That's a great tip tho' and may well have helped me in the work I'm doing now!

I've deliberately wound back the abstraction on this code and it breaks one of our design rules about having detail visible in the code (SQL is the detail). This is a design decision based on customer requirements

 

Interestingly I have actually been winding back some of the wrapping functionality in VI's for simple things more recently. So if there was complex formatting I definitely would have a testable/functional VI for that. I'm tending to leave things like stripping out rows on the block diagram. I haven't really analysed this change in coding style, I think it's to do with letting the code tell it's story a bit more.

 

Great points as always James.

Active Participant

Ah, to me it is the SQL that is the most important thing to read, along with that input cluster.  The rest is details.  But I don't use a tool to generate SQL.  I actually would prefer to get the SQL to do more of the work, such as doing it all in one query:

 

//update only if changed (for speed)
UPDATE received_data SET data = "$1%s", dataStatus = 1 WHERE data_tag = "$2%s" // unique tag AND (data <>"$1%s" OR dataStatus <> 1) // Change needed



Active Participant

Ooh, SQL and LabVIEW. Hold my beer...

 


@drdjpowell wrote:

I actually would prefer to get the SQL to do more of the work, such as doing it all in one query


If I could give you more than one kudo, I would.

 

LabVIEW is excellent at many things, and many people here are excellent at it. But keeping data on the server for as long as possible, using optimised systems for sorting and filtering, should always be a priority for people.

 

Also, I'm personally happy to see SQL within an application rather than the use of a stored procedure - it's simple to confirm that your application is using validated interactions with another system, rather than relying on SPs that could be updated on a separate system without your knowing.

---
CLA
Active Participant

 


@thoult wrote:
Also, I'm personally happy to see SQL within an application rather than the use of a stored procedure - it's simple to confirm that your application is using validated interactions with another system, rather than relying on SPs that could be updated on a separate system without your knowing.

If I could give you more than one kudos for that, I would do too! I had once a "database expert" convince me of using stored procedures and it was a nightmare to maintain!

Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor
Active Participant

I have to admit walking back on the getting SQL to do more. I have a system I'm updating with a lot of fairly complex queries, compared to what I'm doing now (this was about 10 years ago) I would say I'm simplifying my queries and doing some in LabVIEW. But there's so many caveats and things to think about with that statement I would just put it down as a design decision.

 

Member

Am a late entrant to this wonderful blog, and LabVIEW banter in general. Some guidelines I (try to) follow to supplement excellent points already stated per the opening post. (SQL stuff is altogether another topic. Brrr!)

 

VI naming

  1. Builder VIs (getters) are named after the (adjective+?)noun they return. If they represent a physical quantity, I try to specify the unit as well. E.g. surfaceTemperatureInK.vi.
  2. Manipulator VIs (setters, etc.) are named as - (Adverb?)Verb(Adjective?)(Object). E.g. updateSpeedInRpm.vi of a Pump object. Ideally, such VIs don't 'return' any outputs.
  3. Selector VIs (checks) are named according to a decision-making question. E.g. hasRxdDataChanged.vi referring to the block diagram in the opening post.
  4. Input-Process-Output type VIs: (Still unsure what to do. Should this be decomposed to another LVObject?) For now, I just name them as <Output noun with optional adjective><optional From or By><optional input with optional adjective>.

 

Block diagram content

  1. I used to like sub-diagram labels, but now find that 'properly' named selector VIs make it easier to comprehend cases. (I've not used these labels in other structures yet... possibly an oversight.)
  2. Being color-blind, I avoid customization of wires, icons, borders, etc. Most of my icons simply use text, ergo sometimes difficult to read.
  3. Given that icons have limited footprint, and domain-specific acronyms are confusing for cross-domain developers like me, I now like to show the label of the method/message/subVI.
    1. Now, with LV2017+, it's easy to note the use of a malleable VI with the extension. (Am loving malleable VIs. Would like to participate in a discussion on them, especially in the context of LVOOP.)
  4. Minimize block diagram comments. If they are needed, use a limited set of #Bookmarkable comments.
    1. #Rationale: Why a particular approach was followed (In case of multiple approaches tried and tested; or if a particular standard or policy mandates the implemented approach.)
    2. #Reference: To point to applicable standard or policy item. I would recommend this only if the block diagram is an odd one out. If an entire application is supposed to comply, then such references end up polluting the block diagrams.
    3. #Info: To explain a particular section of block diagram. Especially, if logic cannot be simplified any further for whatever reason (light code base, multiple conditions, RegExes, etc.). (Regarding regular expressions, I refer the reader to any online regex tool, especially one that provides a detailed explanation and ability to test.)
    4. These should go away before release: #TBD, #ToDo, #<Someone's name or initials>.

 

VI descriptions

I avoid. (Yes, goes against CLD requirements). If the VI name is not clear enough in the context of the component (LCOD) or object (OOP) it is associated with, then the VI can be improved further. Furthermore, the context help is distracting, when comments can be put directly in the front panel (NO!) or block diagram. These are most suitable for copyrights, and generic library-level messages that need to be included with each VI or module.

 

SubVI Front Panel Control & Indicator Nabels

  1. If an output is duplicated from an input, then call it 'dup <controlName>'.
  2. If an output is filtered from the input, keep both at the same level in the connector pane. One may loosen the criteria to include certain other 'processing' steps, as long as the output data type matches. Rationale: Easier to follow.
  3. If the output data type does not match that of the input, try to put it at a different conpane level
  4. In case of the input is recommended or optional, specify its default value.
  5. If the input is a physical quantity, specify the units expected. (By the way, is the 'units' property of a numeric not popularly used?)

 

References

  1. Yegor Bugayenko, Elegant Objects.
  2. Kent Beck, Smalltalk Best Practice Patterns.
  3. David West, Object Thinking.

 

Active Participant

I mostly use bookmarks to reference the client's issue-tracking system: "#Issue 9 fix", "Changed for #MANTIS 3213".  The issue-tracker describes why something is done. 

 

Another "reference" thing I use is VI references between "matched pairs" of subVIs.  That's where a change in one requires a matching change in the other, such as where one returns an array of names that match the other's array of values (and for some reason it doesn't make sense to combine the two in one SubVI).

Active Participant

Welcome to the club Dhakkan and thanks for your kind words.

I think your comment exemplifies what I continuously repeat, the comments are often better than the main article. There's a lot of great info to unpack and agree with in there.

 

Colour blindness is a very interesting challenge for us, one deserving of more thought I think.

 

Interesting to see a Smalltalk reference, so much of our design work is based on Smalltalk, the best language no-one uses!

 

Active Participant

Although I agree that a VI's name should be enough to describe its purpose (and Steve has written about lying VIs both here and I think elsewhere - a trap that can be easy to fall into and if not careful difficult to climb out of), I don't think that means you shouldn't use descriptions as well.

 

I really like the Context Help window, and frequently pop it up to get more information about things I've written in the past, as well as the built-in nodes or VIs that ship with LabVIEW. Sometimes I place information about acceptable ranges for inputs, or more detailed information describing the behaviour of the VI with various inputs. Whilst it's of course in this case very important that the information is true, and remains so, it can for me save a lot of time opening a bunch of subVIs.

Example Gatekeeper

One professor I had always told us that if we removed everything but the comments from our code, it should still be clear what the code does (he would actually comment before writing any code). I can't say (yet) that I've ever opened up my old code and been upset at how many comments there were. If anything, long comments are probably a good indication that the section of code should be a separate function.

 

Regarding context help, I would always want something in the VI description even if it seems incredibly obvious. Good naming helps but things that are obvious right after you programmed the VI might not be that obvious for whoever is looking at your code 2 years later. 

 

If you have VIA tests to check for subdiagram labels, I would also suggest checking for structure labels as well. For single frame structures (and often boolean case structures) I tend towards using the structure label which seems pretty comparable to a subdiagram label.

Matt J
National Instruments | CLA
Active Participant

I think the main take-out from any discussion about documenting code is "you do you".

Personally I side with the documentation/comments should always be viewed with suspicion and that code never lies.

 

I often put comments in describing what I want from the section of code and then delete them after the code is working and descriptive enough to tell me what's what. I think of these as static comments. I think of the labelling on structures to be more active comments. By labelling a Case structure I'm actually thinking about the true state and the logic that drives it. I find this improves the way I program. Similarly labelling of build array and index array structures help with the readability of the block diagram as a whole IMO.

 

As an example of the bad aspects of this I spent 3 hours last week trying to get a checksum algorithm to work only to discover one of the examples in the documentation was wrong. The lesson here is that we tend to trust the documentation more than the code and this is often a mistake. The documentation is more likely to be wrong as it can't be tested.

 

I've met great programmers who love comments (and these comments help them), I've also met great programmers that hate them (the comments get in their way). This indicates to me that the actual subject of comments is either grey or not nuanced enough.

 

Really appreciate this view from the inside Matt!

 

With regard to context help it's one of the first things I look for in someone else's VI and yet one of the things I neglect. I need a chat with myself I think.

Active Participant

Steve said:
"As an example of the bad aspects of this I spent 3 hours last week trying to get a checksum algorithm to work only to discover one of the examples in the documentation was wrong. The lesson here is that we tend to trust the documentation more than the code and this is often a mistake. The documentation is more likely to be wrong as it can't be tested."

 

To me, that example in the documentation of the subVI should have been a Unit Test. Like you said, running code doesn't lie and unit tests are code that we can run. I would still leave documentation of examples of checksum, together with a bookmark that is also in the corresponding unit test. If in the future, there is a bug related to this part of the code, then:

  1. The first thing to check is if the Unit Test passes and if it is testing the case that has to do with the bug I am dealing with.
  2. Modify the code to make the unit test pass if the unit test is no longer passing.
  3. Create a new unit test that covers the bug case and I modify the code to make that new unit test pass without breaking the previous unit test.
  4. Check if the original unit test was giving a false sense of security and needs improvement.

I see unit tests as running documentation.

Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor
Active Participant

Sorry the documentation was the manual, not the documentation of the VI.

I was writing the VI from scratch.

Active Participant

In those cases, I usually copy the manual page and paste it into the subvi for easy reference.  Although that doesn't really solve the problem of it being wrong. 

 

As Fabiola points out the examples in the text are usually a good starting point for unit tests.

Sam Taggart
CLA, CPI, LabVIEW Champion
DQMH Trusted Advisor
automatedenver.com
Active Participant

We had a similar situation just last week. Fortunately, we were in contact with the device vendor, we show them that the unit tests worked if we used what we assumed was the checksum and it failed if we used their example checksum.

They corrected their documentation, and then we pasted a picture of the manual on the block diagram as Sam says. At least at that point, when we committed, the vendor's documentation, the unit test, and the code itself were all in agreement.

 

This is not always the case. We were working closely with a team as they were developing their serial device, they changed that protocol so many times that they started to use our unit tests as their documentation! Thankfully, one of the things they needed to provide to the end user at some point was an up to date documentation. Eventually, we ended up having actual serial protocol documentation for the device, guess where the examples came from? Yes, the unit tests.

 

Code that runs does not lie!

 

Certified LabVIEW Architect * Certified LabVIEW Embedded Developer * Certified Professional Instructor * LabVIEW Champion * Code Janitor