Why Poor LabVIEW Project Organization Makes Your Code Stink

The good news is that if you currently experience these problems, there is hope

We often find ourselves knee-deep in a project only to find that we now have a sea of intermingled code, making it hard to differentiate what goes where and how to find files. Typically this comes from the failure to create an organization plan from the start. At best, it leads to difficult-to-navigate file structures and hard-to-manage source code control (SCC). At its worst, it is one of the sources of high coupling in applications.

code-coupling-from-wikimedia-commons

Image source: Wikimedia Commons Coupling Sketch

High or tight code coupling results in poor modularization, difficult scalability, long build times, and circular references. We’ve all felt the pain of changing one typedef or VI in a project and seeing that dozens or hundreds of VIs have been modified and need to be saved. This is the result of high coupling, and is what we are trying to avoid.

There are plenty of books and articles that cover coupling, so I will not get into it here. In short, you should strive for low coupling between application components and high cohesion within a component.

The good news is that if you currently experience these problems, there is hope. Let’s start by looking at some of the practices that lead to poor organization. See if any of these smells are familiar to you.

Bad Smells

Let’s have a look at this example project taken from nowhere in particular.

source-code-structure-document-library-example

This project has several unique components, but they are sliced up into pieces and strewn across several folders that are organized by similar functions with other VIs that have nothing to do with one another other than they each have a similar name (and thus an assumed behavior). Why would these not be grouped with their appropriate component?

To drive this point home, let’s look at a clearer case. Would you put all read VIs in one folder regardless of what they read (RS-232, data file, TCP, configuration, UDP, DAQmx)? Or write? If you answered no, then the above example should now smell equally bad. Let’s have a closer look at some of those bad smells and why they stink so much.

Controls/Typedefs

source-code-structure-document-library-controls-typedefs

These controls all belong to different parts of the application and not even one target, but three (FPGA, RT, Win)! If a project has this folder, then you are not putting typedefs in their correct location.

Typedefs are a datatype definition and should be grouped with the methods (VIs) that operate on that specific datatype (high cohesion). Even though a type definition and its methods aren’t called a class in LabVIEW, they should be treated as such and should each be placed in their own folder.

The VIs below all operate on the KeyedArray.ctl.

source-code-structure-document-library-controls-typedefs-2

The only controls that might go in a controls folder are common custom controls (like buttons) that you want to use throughout your application to maintain consistent looks, but not typdefs. In that case, a better name would be Common UI Controls.

In short, there are many good and bad ways to organize your files. Files should not be organized by file type.

Support/subVIs

Everything in your project besides the top-level VIs can be classified as “support” or a subVI. That doesn’t mean that support should be a dumping ground for everything in the project that is not a top-level VI. Each component of the app should be thought of as a distinct, cohesive group independent of other components. Using support/subVIs causes confusion for you and for others about where VIs should go and how you should group them. It also adds one more unnecessary layer to your folder structure that makes it just that much slower to navigate.

Globals

This one may or may not be a bad practice depending on how it is used. If this is a bucket for all globals, then it’s wrong (see note above about organizing files by type). If you use this as a place for application-wide globals (truly global scope), then that is much better. In the latter case, the folder should probably be named something better, like “Application Globals”. Globals that share data from a component to other components are part of that component’s interface and should be grouped with the owning component (cohesion).

Loops/Error Handlers

These VIs may have loosely similar behaviors (they are loops/processes/actors/etc.), but they belong to different components and should be grouped with those.

source-code-structure-document-library-loops-errors

Again, VIs in this case are being grouped by general behavior (they are in fact loops), but they should be separated. Remember the read/write example?

A Better Alternative

This particular project already has a high degree of coupling, and may be a result of thinking about organization in the wrong way (or not at all). A better way to think about organizing this project would be something like this:

source-code-structure-document-library-a-better-alternative

Moving the files does not change the fact that this source code is still highly coupled, but this organization by components will provide a much better project structure. If each component is thought of as independent with a defined interface for other components to use, it will lead to a high cohesion/low coupling design.

So you have seen some of the bad practices for project organization and why they can have a negative effect on code. Join us for the next installment, where we will discuss what some better practices are for organization as well as some naming guidelines. All these considerations are part of a holistic approach to software development that results in better, easier-to-maintain code. If you’re looking for help with your LabVIEW-based system, check out our LabVIEW expertise and reach out if you want to chat.

If you’re interested in organization and naming for LabVIEW projects, check out this article.

Deep into learning mode?  Check out How to deal with LabVIEW Spaghetti Code.