Search the Community
Showing results for tags 'action engine'.
-
I've recently built a medium-sized application that controls a bunch of devices in a university laboratory. From the start, I've been focussed on writing a modular, extensible program, as people tend to add or remove equipment and write new measurement routines accordingly. In my architecture, each device is represented by an Action Engine (i.e. Keithley Controller.vi). The UI is comprised of subpanels that contain a simple UI for a single device (i.e. Keithley Panel.vi). Due to the nature of AE's, any vi can send commands to any device; data changes are communicated to the panel through User Events. This all works really well. Creating new measurements is extremely simple, which is vital as most of my colleagues and students are LabVIEW novices. Adding a device is relatively simple too, as Action Engines are easily understood. And now, the downsides. Mainly, there is a lot of code duplication in this architecture. Many AE's look very similar, with actions like Set VISA Address popping up in every single device. Moreover, imagine having two identical Keithleys (a very real prospect)... one would have to duplicate each vi to create Keithley A and Keithley B, which seems silly indeed. Also, I don't particularly like the extensive use of Variants to limit the number of inputs on the AE. All this tells me it's time for LVOOP, but so far I haven't found a satisfactory design pattern for my use case. The problem is that classes in LabVIEW are by-data instead of by-reference. Somehow, I need to get class instances of my devices across to different parts of my application (including measurement plug-ins), without having them operate on different copies of the instance. Solutions to this problem seem to come in two flavours: communicate to each instance via a command queue (Actor Framework) or operate on references (DVR, Single Element Queue). I find both approaches unsatisfactory: the former buries the elegance of a class (properties and methods) under a pile of asynchronous mumbo-jumbo I don't need, while the latter can introduce deadlocks and forces my users (students and co-workers who will create measurement routines) to place all calls inside de-referencing blocks (be it an In-Place Element structure or a Checkin-Checkout procedure). Finally, I should mention that I'm aware of the existence of GOOP, which seems to enable by-reference OOP in LabVIEW, but I would like to stick to native solutions if at all possible. Is there a way of harnessing the power of OOP (inheritance, instancing) in LabVIEW, without moving to asynchronous designs or potential deadlocks? Where do I go from here? PS: my apologies if this turned into something of a rant, but shifting to the OOP paradigm in LabVIEW seems overly complicated compared to other languages.
- 8 replies
-
- action engine
- application design
-
(and 1 more)
Tagged with: