GDevCon #2 is wrapped. I’m really proud of the event we put on this year and its got me really excited about where we can take it next year. We’ve got plenty to think about and I hope that we can top it again.
I’ve taken some really interesting thoughts away and I thought it would be interesting to share them (and help me by having to describe them!)
Our target from the start has been that this has to be valuable to all members of a team. The CLA summits are often a place to pontificate about architecture and design but that is of no interest to someone getting going with LabVIEW or working on an established framework but with engineering challenges and deadlines to meet.
This year I feel we got this much better. I believe that showed in the variety of levels, engaging presentations and useful takeaways.
On the whole, it felt like there was a more pragmatic approach than other conferences (influenced by DSH workshop’s pragmatic software development workshop?).
This is a combination of confident presenters who were happy to present what they do and accept it may not be perfect but it works for them. This was then largely reflected in comments and questions that respected this. (while still looking to inform when there are other options as well)
This really excites me as I think it makes it a more friendly and open environment and hopefully might encourage more to speak so we get different perspectives on topics.
So think about this in future presentations. It works for you! and try and think about the pros, the cons and your context which all factor into it being a good engineering decision.
“Chill Out” Room
I still love having the streaming room. I get frustrated sitting in one place for too long so it was great to have somewhere to stretch out but not miss the content (as I often have at other conferences). It does cost money! But it seems to be valued by those who use it.
Ready for Next Year!
I hope we can start soon with planning next year so make sure your signed up to the mailing list at gdevcon.com to hear about it.
We will be asking for feedback soon as well so do let us know what works and what doesn’t. My final takeaway is that I can be very wrong about what people will like! I’m happy to admit that I had concerns about a few things this year and how they would be received that were completely wrong. So help me to be right more by telling us what you need!
I’ve been thinking a lot lately about tooling. I’ve been getting my CI system running smoothly (ish, more on that later) as well as exploring another new language and working on open source projects on GitHub.
I’ve realised that there are specific penalties that we have to face as LabVIEW developers that are largely down to the graphical nature of LabVIEW.
In my head, I think of this as the graphical tax and thought it would be interesting to put these out there, see if there are solutions I’m missing or at least let’s have a discussion.
Software Engineering Tools
This one is an easy place to start.
Most software engineering tools assume a text-based system. Git works incredibly well on text. Github can merge requests in the browser on text-based files. CI tools use a text-based interface (the command line) to automate tasks like building, testing and linting your code.
As LabVIEW developers, we miss out on a lot here:
I’ve tried to plug the gap to CI tools with G CLI ( https://github.com/JamesMc86/G-CLI) but it is far from seamless as LabVIEW still has many cases where it pops dialogues.
Git etc. do work but don’t understand the files so manual merge and diffs all round
Any tooling for the language has to start from scratch. We can’t leverage what already exists.
This one is frustrating as software engineering marches on – we have to be careful not to get left behind. NXG promises to help a little with a human-readable VI format but I’m not yet convinced it will solve many problems (though some I’m sure).
This is one that I think is really fundamental and just something we have to accept.
Compared to LabVIEW, text-based style seems simple! spaces vs tabs, newlines or not, camel-case or snake-case. There are certainly huge debates but it is essentially a 1D problem. It’s also easier to manage with linters and code analysis tools.
With LabVIEW, we take that problem and add new dimensions. Style is literally 2D. There is so much room for variation. So many mitigating circumstances for given diagrams that having a common set of skills is hard.
With text, you can add your own visual style on top with your editor while keeping the code “pure”. With LabVIEW, if you want different colours for your background it saves into the code.
A great example was a pull request I got on GitHub. After downloading the code to my machine many of the comments were too small. When I requested they were made larger to fit the text, they sent back a screenshot showing it fits on their screen.
This is an area that interests me in understanding more. I’m not sure if it is hopeless or we just need to be stricter. It certainly feels like a barrier to more collaboration and so something that should be considered.
Web Tools for Review
I think this is going to get harder and harder over time.
Increasingly the web is the centre of our working world. Text translates to that world well.
Review is also getting bigger. The place this really hurts for me is in pull requests on GitHub. When I receive a pull request for the C# part of G CLI it can be a 5-minute process. I can review the diffs in GitHub and understand what is going on.
With LabVIEW, you are forced to pull the project down to the desktop to open the IDE and view it. So when, like as I write this, I’m not on my main dev machine I may not be able to provide any comment on what is happening.
This could be improved by having sites with plugins for LabVIEW that can generate code images and diffs. I know some work has been done on this in Jenkins so it can be improved. But it will never be as straightforward as commenting on text code (line by line comments are handly).
So why pay the graphical tax? Or:
If your just going to moan about it James then use text based languages
Well, there are still some hugely compelling reasons:
I believe it is easier to understand program structure graphically which greatly speeds up development and debugging. At least I’m a very graphical thinker.
There are no other tools that allow you to target desktop, real-time and FPGA systems with very little difference in syntax and concepts.
Even on a single target – there are not many other languages that combine a fairly high level of abstraction and the level of performance that LabVIEW provides.
So I still think I’m a net gain for using LabVIEW. I have no plans to jump ship any time soon. But maybe, by sharing my concerns, I might trigger some thoughts on how we can tackle these issues.
Open source software projects are making huge contributions around the world. They allow communities to pool their resources and achieve progress that couldn’t be reached by individual teams in silos.
While there are open source projects in LabVIEW, it feels like a resource that we aren’t great at using as a community. Every project I’ve seen seems to handle things quite differently, and it can be hard to track down where to work. Since I started the first draft for this post it seems there have been discussions in the US on the same topic:
In this post (and another on setting up a project). I want to collate what appear to be best practices in other communities to see if we can’t improve the open source capabilities in our community. There are hundreds of guides out there – so I will be liberally linking to others and trying to highlight the potential differences in LabVIEW.
Open Source Project Structure
So what is an open source project?
In short, it is a project that someone has decided to make available for free to everyone to use and improve. I’m not advocating making all of your work free, but often, there are bits of sawdust – the bits of code or tools that you have lying around to make you more effective, that you can share and help drive the community forward.
Firstly let’s look at the people involved in a project:
Maintainers – Normally the original developer, they are responsible for the master copy of the project. It may also include trusted contributors who have taken on more responsibility. As well as working on the project, this is the group that will be involved in setting a direction for the project as well as assessing and accepting contributions.
Contributors – These are people that have provided code changes or documentation to the project.
Users – More obvious, people who are using the project themselves and may contribute bug reports and other issues.
There are some tools for finding open source projects to use or work on, but don’t be surprised if LabVIEW is missing from the list.
If you are looking for a project for a specific function, then Google may be the starting point. However, when I tried this with Modbus, the results weren’t great. Adding “open source” to the search got us closer, we now see download pages, but no source code.
So, to do better, we need to search some common places for open source projects to be hosted. We can stick to Google for this. By far the most common for new projects is github.com so we add site:github.com (bitbucket.org and gitlab.com can be worth trying too). Now we see two open source libraries
Of course, those sites have their search functions which can be useful too.
If you go to Github.com and enter “language:LabVIEW” into the search box, it will show you all of the LabVIEW projects on there. You can then add additional search terms to narrow it down.
A big concern with open source is how do you know if this project is reliable? There are a few indicators that you can consider:
Most services have some form of user rating – while the small size of the LabVIEW community doesn’t help these – you may be able to apply some judgement to them. For example, projects can be “starred” on GitHub.
Look at how active the project is. GitHub will show you the latest commit, and you can also see releases, commits and contributors at the top. If there is a good commit history or multiple contributors, this is a good sign the project is active which usually means a higher quality output (since maintainers are fixing bugs or improving the code base).
Finally, it is open source! Download the code and examples and take a look to see what you think, try it out quickly before committing to it.
Use and Report Issues
The simplest thing you can do to support a project is using it! From the GitHub page you should be able to find directions to install the project and possibly directions on reporting issues.
I try and will be convincing others to do the same, to use the built-in issue tracker on GitHub or bitbucket. This means that:
The issues and discussions are public so others can contribute.
When you have an issue, you can search this first and see if there is an existing solution. (yay for reduced support burden!)
The issues list becomes a list of items that new contributors can work on.
When you find a problem or something you want to change, the first thing to do is create an issue. This allows you to open a dialogue with the project maintainers about the problem. They may already have a fix, or they may suggest you contribute the change yourself.
Fix Issues and Contribute
Firstly, contributions don’t have to be code. I was delighted on the LabVIEW CLI project to have help producing a getting started guide. Maintainers sometimes leave documentation and examples to the end but they are hugely valuable. Of course, you can also contribute to the code base as well.
A good project should have a contributing guide in the repository. This will let you know how the maintainers want to receive contributions. This is also a great place for details on things like LabVIEW version, source code structure or build instructions.
If ther is no contributing guidelines, there are some excellent guides for this already, so I’m not going to repeat them here:
A good general description: https://www.hanselman.com/blog/GetInvolvedInOpenSourceTodayHowToContributeAPatchToAGitHubHostedOpenSourceProjectLikeCode52.aspx
A LabVIEW specific guide to Github (covers starting from scratch): https://github.com/NISystemsEngineering/GitHub-Hands-on/blob/master/docs/Git%20Basic%20Concepts.md
I hope this article gets you interested in contributing to open source in LabVIEW. If you wanted some more comprehensive guides then I suggest the following:
We have long known that VI Analyzer is a good idea – much like unit testing – people on the other side of adoption swear by it.
We’ve found a few hurdles for mainstream adoption into our process, and I suspect yours too.
1. Understanding Why
The first step in adopting VI Analyzer (and keeping that adoption going) is understanding why you are doing it!
What I mean by this is you need to make the tool fit your process – not the other way round. If you use VI Analyzer because NI says so then you’re going to see less benefit and it will feel a lot more effort.
For me – I believe that consistent style and code inspection reduces bugs and improves readability of the system. I have a style guideline, but I don’t always follow it. As I typically work on my own, then code reviews aren’t an option.
Your “why” will probably be very similar but the subtle differences will make some of the following items slightly different from mine.
2. Complicated Setup
As I said above, VI Analyzer is all about consistency for us. We want every project to follow the same style guidelines. Unfortunately, VI Analyzer does not make it very natural to create a standard test configuration and share it between projects since there is a single configuration file for test setup and which VIs to test.
These are the steps that I went through to build a standard configuration:
Start with your style guidelines. I made mine into a table and identified what already had a VI Analyzer test, what had a custom test in the community, what could have a custom test and what was not testable.
I downloaded the custom tests that are available online and created a couple of key tests myself. I didn’t do them all, and I will expand my coverage over time.
I used a project to create a VI Analyzer configuration file. I worked through the tests and configured them to my style guideline. Then I removed all of the VIs to be tested. I saved this configuration file as my standard.
I created a VI package which would install the custom tests and the configuration file to a shared location in my documents. Full credit to Fabiola De La Cueva and Delacor for this idea. They have been helping their customers with this for some time. (You can see their video of this on Youtube)
By completing these steps up front, I can introduce a consistent VI Analyzer configuration to a new project quickly and easily.
3. Defining A Trigger
As with any good habit, you need a trigger to tell you when to do it else you often won’t follow through. There are a few common triggers that I have seen people using:
Post-Commit in a CI Server – I’m not a big fan of this one because you now need another trigger to review the results and implement the changes.
Pre-Code Review – This is a great one if you are on a team. You should test with VI Analyzer before a code review. You don’t want to waste time picking up things a machine can identify faster. As I am a solo developer, this one is limited for me.
Feature Branch Merge – If you are using a branching workflow in Git or Mercurial, then you can use a feature branch merge as a trigger. This is a good trigger as it should limit the scope of what needs testing. However, if the change list gets long, then there could be a lot to review.
I wanted my trigger to be a commit. I feel like the code should go through VI Analyzer to be “finished” and only “finished” code should be committed.
This is a problem though. Analyzing a whole project can take many minutes, and I might commit 10+ times a day.
One way to solve this would be to test only changed code, but VI Analyzer lacks any native support for this workflow.
I have developed a tool to tie it to git changes. It isn’t great, so we haven’t shared it yet (it still lacks many essential features), but it has started us using VI Analyzer regularly.
This tool will take a configuration file and then run it against only the code that Git shows as changed. Testing only the changes cuts the test time and now means that it is possible to check at each commit and fix the changes before that commit.
By overcoming these hurdles, VI Analyzer has become a standard part of our workflow. I hope you can use this to incorporate it as well.
I don’t write code in the best way the first time. No-one does. Instead, if we want to get to a state of clean code (readable, maintainable etc.), we often have to put specific effort into it.
Martin Fowler’s Refactoring book summarises it nicely when talking about refactoring. You need two hats. One for adding functionality and the other for refactoring. Your process may have a nice point to change hats (I use TDD which does) – or you may have to be more deliberate. But at some point, you need to think about refactoring.
I’m not going to go into loads of detail on refactoring now. Instead, I want to focus on one type of refactoring that I use a lot – creating more subVIs.
Why Refactor Code to have more subVIs?
There are several reasons why code with more, smaller subVIs will tend to be easier to work with than a flat VI:
The diagram is smaller – The simplest of them all – your diagram now fits on the screen!
Improved readability through abstraction – This can be a contentious point. We are putting the detailed implementation another click of the mouse away which some people dislike. My experience is that this is outweighed by how much easier the code is to read. By creating a well-named, cohesive subVI, the calling VI is faster to read since you don’t have to worry about the details. You can worry about the problem it is solving and dig into the details if/when you have to. There are also testing and debugging advantages since the new subVI can be debugged in isolation.
Clear and Obvious Coupling – Coupling is one of the primary concepts in software design that you need to grow to understand. A flat diagram can easily hide coupling in the noise, but once you create subVIs, it is obvious if a subVI has too many inputs or inputs that you wouldn’t expect it to have. These are both signs of coupling problems.
Where to start?
I signed up for a presentation at NI Week to talk about clean code and needed to talk about this topic. The day before planning to write the subVI section, I was working on a customer project. As I have a young baby at home, I try to leave at 5 pm every night now, but it was getting on for 5.40pm, and my Wife was messaging me to see where I was so I got the code running but never put on my refactoring hat.
When I came to write my presentation, I realised that stepping through the refactoring of this code was the perfect example! The code I abandoned that evening is the code in the steps below.
Look for Commented Sections
The first and simplest clue, is to look for sections of code with comments describing what they do. If it is enough of an important chunk to comment, it is probably cohesive enough to make a good subVI.
See the sections for formatting at the bottom? There are three types of data to be formatted for the table. One is already in a subVI but the other two are just labelled as doing the conversion. This is the classic sign of a subVI that hasn’t been created yet.
The first step here is to turn these all into subVIs.
I’ve created the subVIs, aligned them and given them a consistent naming convention.
Different Levels of Abstraction
I’m still looking for a better term for this, but there is still a smell in the code above for me.
Most of the code is now subVIs doing non-trivial functions. Loading from a log, generating tables. But there is a section on the left that is doing array manipulation. This is a problem because it is too much detail for what this code describes. This code is supposed to “say” load the data from the log, convert the sections to a table and combine them all. But instead this story includes handling memory allocation as well!
So my next step is to abstract this into a more descriptive subVI.
I hope you agree; this code is now much more straightforward to read. It is doing everything it was before (as efficiently as it was) but as developers, we can become faster at understanding the code.
Did you notice the coupling?
This highlighted a nice reason for this refactoring. Why is a build table function using an array of timestamps?
We sucked these in as part of the “create subVI” process, but they don’t belong. We can refactor the timestamp array out but using the rows in the time table instead to remove the input.
This is a somewhat trivial example, but by abstracting out the subVIs, we can now understand our code in a way that is clearer than before and better visualise the coupling between functional components.
Are we done?
Naturally there is no “perfect” state. This was the stage I stopped at since I had removed the immediate “smells” and the code worked well. Now the code structure is clearer though it actually highlights some other things we could consider:
The build table code could be generalised for reuse by removing some of the labelling. If I need this same function elsewhere, I may come and grab this code.
The program flow shown is that we generate each sub table before building a large table. It may have a higher performance to directly insert each of the subtables directly into the pre-allocated table. Right now the solution above is simpler, and I don’t have any performance concerns, so I haven’t done this.
I’m going to keep on about this – These potential changes are much more obvious in the new structure than the old – that is why those first steps are important. There is also a point where you have to say good enough, or there isn’t enough information to know what is the next best step (options 1 and 2 above may clash so we don’t do them until we know which we want).
A Note On Testing
Isn’t there a risk of breaking your code with refactoring? In theory refactoring should not make any functional changes to your code but we have all done things with unintended consequences!
Allowing low-risk refactoring is one of the ways that unit testing leads to better code. Because I have tests around this section of code, I could change it as much as I wanted with confidence that it still works. This is why we treat unit testing as a foundational principle at Wiresmith Technology.
A loop within an application component. It has a single reason to run.
Why Loops Run
By “run” what I mean is what triggers an iteration of that loop. I’ve identified these sources:
Time – Intended to run every x ms.
Event – Either a UI or User Event, the loop contains an event structure.
Data – Basically a queued message handler but “data” means anything that means a loop waits for data. A data interface could be queues, notifiers, streams, DAQmx etc. Some external process is forcing us to wait for new data to be available.
The rule means, if one loop is trying to use two of these methods (or multiples of one of these types) then problems may occur. Examples might be:
Using the timeout on an event structure (did you know it won’t fire if user events fire, even if you aren’t handling them? Thanks Chris R for this demo!) Thanks Fab for the correction: This was a bug that has been fixed.
Using the timeout of a queue to perform a repetitive action.
As you can see – time is usually the conflict because the others are kind of obvious to avoid having in the same loop.
Why This Rule Exists
Put simply, in most cases where two of these exist there is a conflict which is hard to resolve consistently 100% of the time, mostly because the event and data drivers depend on external components which aren’t predictable.
Take the timeout case of the queued message handler. If you want to check a state about every 1 second, then the best case is a new external message once every 2 seconds. Then 1 second after that message arrives you perform the check. Maybe you will get a second check before the next message, maybe not. Most likely you will end up performing the check every 2 seconds. Perhaps that is acceptable?
However then an external component generates messages every 0.1 seconds. Now that check doesn’t happen ever, through no fault of yours! (In the context of the code in this loop).
But I Need To…
Perhaps there is a case where you want to break this rule. I have two solutions:
Use a second loop as a “proxy”. For example in the case above have a second loop which runs every 1 seconds and enqueues a message for the check.
Another example is when you have an API which generates messages on an event but you need it in a queue. If you have used the actor framework, this how you extend actor core for GUIs.
Break The Rule… And Be Very Careful
If you don’t see a way to design around this rule, then you need to know you are breaking it and be very careful. Most likely by adding some management code to a loop.
The example I could think of was if you needed data from two loops. In this case, you would write code to read from each queue. If one read timed out, perhaps you store the successful data and then try again, reading only the failed queue.
I don’t think there are many cases, but rules are about knowing when you break them and why!
The word of the year here at Wiresmith Technology is process. In areas where I have standardised processes life has got easier, less stressful and more reliable. Now I’m looking at the software processes to see where we can get the same benefits.
Something that I have wanted to address for a while is architecture. Working on my own has given me the benefit of being able to be quite ad-hoc and try different designs on different projects.
Well, I often think coming back to your own work after 6 months isn’t so different from working with someone else and I’ve certainly felt the drag of having to review how I built the architecture on each project. So I want to at least have some standard templates.
What I found when I came to it was I first had to define what is in a program!
Language Is Important
There are so many conflicting terms and every framework has its own terminology.
I really wanted to start with knowing what I want in a generic sense. By doing this without looking at specific frameworks it gives me the freedom to find a framework that fits the way I work best (as well as the freedom to change or not use frameworks depending on the project).
I’ve seen this approach work in my business. I’ve been trying to find tools to help me be more productive, but it isn’t until I decide on what the process is that these tools are supporting, I waste hours trying to choose as I have no way to determine what is best!
So before even trying to work with templates or frameworks, I reviewed my previous projects to try and pull out and name the different elements of my architectures so I can map other tools to this.
What I Picked
So here is what I listed as my architectural definitions. Before you read them, understand I am sharing these for your curiosity – you may have your own set of definitions in your team already. This isn’t about right or wrong, this is about consistency between team members and projects.
Not to be confused with…
An asynchronous VI with it’s own lifetime and own control of when to run. This is the top level of the architecture design.
A piece of engineering data e.g. acquired data.
Messages: We split this concept as messages are more framework-oriented.
A framework command for a process to do something.
Data: although they are data in the strictest sense, they are not directly related to the data involved in the engineering domain.
A process that receives heterogenous messages and data.
Data-driven process: this has homogeneous data to handle.
A set of related code. In our system, it is a class. It is generally unit testable.
Module (DQMH), Actor (AF) – These are processes or message handlers.
A loop within an application component. It has a single reason to run.
I’m pretty happy with this – the one element of confusion is where the actor style module (whether that is an actor framework actor or another QMH based framework like DQMH). In reality, this sits somewhere between a module and a process but I need to experiment more with how to think about those.
The one I think is particularly important is modules. Too often the important logic gets muddled and mixed with framework code
For me the next step now is to create templates or frameworks to handle these items in a consistent way – more on that in a future post.
My challenge to you is to think about this for yourself. Maybe you already have a framework so you don’t need definitions like this, but where do you find you or your time are inconsistent over time and would a common language help?
Its that time of year – the arbitrary point to review what is going on in our lives! To that end, I thought I would review my LabVIEW life here.
What has worked well this year?
Probably my most exciting LabVIEW element this year has been working on the LabVIEW CLI toolkit (well it launched in 2016 but let’s not quibble).
It has gained a lot of traction as CI has become more popular in the past 12 months and it is great to have something you have put out there used by other people and even receiving contributions back to the code.
There are still improvements to be made in handling cases when LabVIEW might already be open, I hope to get to these soon, or we will have to see if NI’s release solves this and so may supercede what we can do.
Getting More Organised
Over the past 12 months, I have better defined how I structure my code and documentation which, while tedious, helps me to focus on the important bits. I’m not done yet – but it is getting better all the time and creates the opportunity for one of my themes for 2018 which will be automation.
What do I need to do better?
System Testing and Analysis
You should hopefully all be aware I love unit testing. It is built into the way I work and has improved my code greatly. I need to take this a step further and make sure I increase my testing at a system/integration level to catch things unit testing can’t. I don’t yet know what that looks like – it is especially hard in LabVIEW since there is so much hardware involved but what I have learnt is I need to try to automate whatever I can to make sure it happens consistently.
2018 is the year that I am going to adopt a basic framework at a structural level. This will just save time and increase consistency which will make code easier to maintain and open up more options for collaboration. The only problem is that I’m not a fan of frameworks!
My idea is I need to work out why not. Starting from principles of what I need, I can then evaluate existing frameworks or just build a couple of templates to work from. The best example is that I find most frameworks don’t have the concept of a time-based process, e.g. DAQ, but this is in every system we work on! I’m sure I will share more as I go.
Time for Personal Development
I have found it really hard to date to make sure I spend enough time experimenting, learning and developing tools in LabVIEW (as well as other areas of expertise). This year, I am going to figure this out! Hopefully, that means more posts here as well as this time is the best source of ideas for this site.
What Am I Excited About?
2018 is going to represent something of a new era for Wiresmith Technology. I have decided that I need to focus more on application areas rather than LabVIEW to expand my reach and make marketing much easier.
The area of focus is Automated Measurement Systems. This means an emphasis on applications where we are taking dynamic measurements and analysing or logging this on the fly. While I expect there to be some areas of control in these systems (for example, stimulating the system we are measuring), this represents a move from our previous split of measurements on the one hand, and control on the other.
Why is this exciting from a LabVIEW perspective? This narrower focus also helps me to allocate development time better and prioritise certain technical assets that fit the applications well. It should improve reuse and let me dive deeper into some interesting areas.
VIMs and Channels
My projects all exist in LabVIEW 2015 still, but this year I will move to 2017. While some of these recent releases have been mocked for having very few material changes (I’m looking at you, 2014 icon change!) the few productivity improvements have really made a difference day to day.
2017 also sees some new language features though. I’m excited to try channels – I’m not sure exactly how I will use them yet but I like the idea that the top level of my code can look like an architecture diagram.
VIMs on the other hand look game changing for me. So many re-use ideas are scuppered by the idea that I must create loads of versions for different data types, but this is the solution. Simple things like a “has changed” VI or stall data flow mean that we can produce much more valuable reuse code without the penalty of having to go to variants.
With a new baby at home, I’m supposed to travel less, but the calendar is already looking at bit exciting! You will find me at:
CLA Summit Europe 2018: We are in Madrid this year. I volunteered as co-chair, so I’m going to have to be a bit responsible this year. I’m also going to be banging on about unit testing again.
NI Week 2018: I was planning on not going this year due to family and financial commitments, but I got an excellent price on flights yesterday! Skype should keep the family happy.
GDevCon 2018: With the lack of a UK event for advanced LabVIEW developers, some of us decided to make our own! Go to the site to sign up for updates on tickets and content.
I hope I will get to meet you at some of these through the year, say hello!
The APIs that you have to test are not always simple. As well as passing data they may involve events (with the front panel or with user events).
The other day I needed to test that an event fired as part of a test case. I could see a generic solution, so I created a template for it. I had two requirements:
If the event doesn’t fire – test fails.
If the event fires with the wrong data – test fails.
In my given when then sequence then we end up with a test that follows the structure:
Given: Who knows, in this case, a UI library has been tied to a control.
When: We take some action that should cause an event on that control.
Then: Check the event.
To check the event we create an event structure outside of a loop as we don’t want to handle multiple events. We need two cases:
A timeout case with a suitable timeout – In this case, we call the Test Case.lvclass:fail.vi to fail the test. This should never run if the when code fired the event.
A case that handles the event – If you don’t care about the data then you can do nothing here, otherwise, include tests on the data included in the event.
Dynamic Event Registration: If this is a user event then you will need to register for the event. I’ve included this in my template, but you must move the event registration to the given case. If you haven’t registered the event before the action in the when case, it won’t ever fire.
Parallel/Dynamic Event Generation: If your event is in some dynamic code you may need to have this running. My advice: DONT. Try and pull out the internal API and test synchronously. Asynchronous testing in LabVIEW introduces timing concerns which make your tests much more complicated.
When writing applications that will be used by anyone else you will need a configuration file. In my experience, this is almost universal and the more I make configurable, the more powerful the software becomes and the less small changes I have to make for my customers.
Where do we save config files in LabVIEW? The landscape is more complicated than you would think! In this post, I’m going to summarise what we do on our LabVIEW projects. We are focusing on Windows since RT is simpler (put it in /c/) and I don’t use Mac or Linux with LabVIEW.
Types of Config Data
I’m going to refer to two types of config data:
Global Data: No matter who logs into the system they should share the same configuration. In my experience, this covers the vast majority of industrial applications.
User Data: Configurations that should change depending on the user. This might be screen layouts for example.
Files or Registry?
Microsoft is actually quite keen that you put this data in the registry – that is what it is for. There is a Software folder in each top level folder where you should create your own Company/App folder structure and you can store settings as different variable types.
For user data, you can store it under HKEY_CURRENT_USER and for global data, you can store it under HKEY_LOCAL_MACHINE. In many ways it is a pretty nice solution to the problem, however, I’ve avoided it for 3 reasons:
Files are much easier for users to get, edit or send you. Whilst I don’t want them directly editing the files much it is great that when there is a problem they can send me a file or even a screenshot of the file (when it is readable) so I can understand their setup.
Files make save as… much easier if the user wants to be able to switch between configurations.
Files are universal. Although I don’t have much cross-platform code I like that I can create multi purpose configuration libraries that work on Windows or RT. Without this, I would have to have different code for the different platforms.
I am curious though about who is using this. Please leave a comment below and let me know why you like this and if I have anything wrong.
If Files, Where?
OK, so we have decided on files, where should we put them? Helpfully Microsoft has an article on this however 7 years on there are still issues!
User data is the easiest and where Microsoft’s advice still works. In each user folder, there is a hidden AppData folder. This is designed to hold user-based configuration files and so the user has full read/write access to this. It is just hidden to protect you from “users with initiative” as Fab puts it in this presentation! Within here you should create a folder structure with Company Name\App Name to follow the standard convention.
To get this path use the Get System Directory.vi with the User Application Data input.
Global data is where this gets messy. There is an equivalent folder to the user AppData folder for this purpose, but…
In XP all worked well. It was located under All Users\Application Data and all users had write access and software worked.
Then Windows 7 came and two changes occurred:
The location was changed to C:\ProgramData (A hidden folder)
Folders had restricted access. The creator/owner has write access but no-one else.
One use case for this is to install fixed configurations at installation time and this works well since everyone has read access. However, if you need to write these after installation you normally do not have access.
The solution to use this? You need to set the permissions as part of a post install step to allow all users to have write access to the relevant folders.
One day, I may sit down and get this set up automatically as a post install step. For now, I have too many concerns about managing failures of this causing extra support. My solution? Use the public documents folder.
I follow the same structure but in Public Documents instead of Public Application Data. So far I’m happy with this decision and I haven’t had any headaches due to this.
I would love to hear your thoughts. What do you do? Am I wrong?
The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.