09-06-2023 01:02 PM
Hello all,
I am somewhat new to DQMH and for my first project I've decided to make my testbed software compatible with future projects so I am making it as modular as I can. Modules contained within include Camera, Stage (which is a cloneable abstraction layer for a Zaber stage. Cloneable as to allow multiple axes in the future), Test, and a Model module. Eventually once I make the UI I'll have a whole MVC architecture going on and I'll make that good and nice. Camera, Stage, and Test each have their own settings which are required, and I have made a Camera Settings and a Stage Settings (cloneable) module as well (haven't gotten to test yet). These are required for reading the ini files containing the VISA sessions, baud rates, microstep sizes, IMAQdx settings, etc.
Without the data from the ini files, there's really nothing for the hardware modules to use, so I would like to have the gathering of settings information in the init message case. From what I can see, I have two options as to how to lay out the program. My initial thought is to have the modules for settings launched by each individual hardware module.
or I can have settings be given to the hardware modules by main. This avoids having a bunch of layers, and sticks with the philosophy of having everything sent through the controlling module.
I'm really not sure what the smart way to do this is. Especially with the cloneable stage module where each clone will need to be given a single clone of the settings module.
Additionally, I'm not sure how much work the init message should be doing in terms of loading these ini files. Good design philosophy tells me that it makes the module more atomic to have a separate config case, but realistically, there should be no reason for a stage module to change which hardware stage it's connected to, so I don't really want to include a configuration in the API when it can all be done at module startup.
Solved! Go to Solution.
09-07-2023 03:18 PM
Hello nokaroa,
on behalf of the DQMH Consortium, thank you for looking into DQMH and giving it a try!
First, you might get more answers in the DQMH-specific forums, so perhaps consider posting there in the future.
As for your questions, I can talk about how we do things at HSE:
You can see all these things in action in our open-source HSE Application Template. Feel free to take a look at it, perhaps there are some ideas for you to take away.
Hope that helps!
Cheers,
Joerg
DSH Pragmatic Software Development Workshops (Fab, Steve, Brian and me)
Release Automation Tools for LabVIEW (CI/CD integration with LabVIEW)
HSE Discord Server (Discuss our free and commercial tools and services)
DQMH® (Developer Experience that makes you smile )
09-08-2023 08:29 AM
First, you might get more answers in the DQMH-specific forums, so perhaps consider posting there in the future.
Noted, I had no idea there was a specific forum for it. I also posted the same question on Lavag.org because I wasn't sure where would be better.
- No code whatsoever is added to the "Initialize" case of any module unless for a very good reason (we've just recently discussed this here)
This is interesting. Your response there is that you'd have one module launch other modules, and pass the event registrations to those modules as needed? To me that seems like it would create dependencies where the submodules wouldn't be able to run standalone? I could be wrong, but isn't a core idea of DQMH to allow modules to be able to run independently of the module that's calling them in the final program? For example, if A calls B and C, and C calls D, B should be able to run without A and C should be able to run without A or B running, but D needs C to be running. If A gets the event registration references from B and passes them to C, that seems to break encapsulation for me?
I think I'm just confused by how much encapsulation is really needed.
- All of our modules have a "Configure" request which we can call either dynamically or manually, at exactly the point in time we want to (i.e. when all required resources have been started or similar)
- The "Configure" request does not have parameters and serves only as a trigger - all modules know where to find their configuration data
Okay, that's one way I've been attempting to solve the problem. My configure requests have been taking in configuration data however. If I've got 3 IMAQdx compatible cameras on my computer, and I want to launch the camera module, I need a way of determining the VISA and all of the relevant settings, so that has been solved by having a settings module which reads the config files and passes the information. But this is kind of the core of my question:
Should the configure request cause the initialization of the settings module? I can't have just a default setting for a camera module because it would fail if the correct camera is not connected and in development, that's always possible. In one module, I get the settings module from inside of the configuration event, and in another, I call configure and pass in the settings cluster which has been instantiated from outside the module. I can't anticipate the pitfalls of doing it my way as opposed to your way.
- For cloneables, we can hand over an identifier at module start (i.e. to the "Start Module" VI) so the module can eg. find a specific section in a config file to pull its instance configuration
Do you mean modify the start module VI? I have been very hesitant to modify any VIs that DQMH scripting creates other than main.vi, but if that's how you do it then I guess it can't be that bad of a practice.
The approach I came up with (since writing the original question) is to have an axis manager module that launches the clonable axes and the clonable settings modules, and stores the Module ID for both in a map. But the main module that launches the axis manager is still responsible for getting the sections from the config file and passing them to the manager's "launch axis" request.
Thank you for your time. I'll look through your template for inspiration. I feel like I'm asking a bunch of questions rolled into one so I appreciate your help as I try to manage this. It's a bit overwhelming.
09-08-2023 08:29 AM - edited 09-08-2023 09:01 AM
Hi,
To add a voice, we recently redesigned our application skeleton.
And we applied the exact same technique that Joerg described in its previous message.
Previously, we had a centralized configuration module (as you describe in your post). But ir creates coupling between modules.
We had to create PPL from modules to create a plugin arch, and we had dependencies everywhere on the configuration module... not very confortable !
So we changed that to adopt a configuration per module. Each module is handling its own configuration (JSON R/W, file change detection, ...).
Now each module is stand alone again.
We have a specific module taking care of exposing the settings to the user. It allows better UX and filtering of what settings can be changed or not by the user.
09-08-2023 09:05 AM