Jump to content

Re-Designing Multi-Instrument, Multi-UI Executable


Recommended Posts

I have searched extensively and cannot find the example anywhere in the 2012 Beta. Could you point me to it please?

It's right on the Getting Started Window (new project from template, or so). See the beta forum for an update to the sample project, though. Arg, this doesn't count as talking about the beta, does it?

Link to comment

It's right on the Getting Started Window (new project from template, or so). See the beta forum for an update to the sample project, though. Arg, this doesn't count as talking about the beta, does it?

Yeah, it kind of does, but I won't tell the Powers That Be if you don't...

jbjorlie: Read the beta forum for comments from me about this.

Link to comment
I actually don't like calling it MVC because I don't think it's an accurate description. It's closer to a Model-View-Mediator architecture, but that's not exactly right either. Depends on your messaging topology. Applications using the observer pattern lean towards a lot of direct point-to-point communication. In these the message source usually sends a copy of the message to each receiver. I prefer a hierarchical messaging topology. In that system the thermocouple sends out a single Temp message to it's owning mediator, which then forwards it to the next mediator, and so on down the line. Copies are only made if a mediator has to forward the message to multiple destinations. Or you could always do a hybrid of the two...

This is somewhat tangential, but the Gang of Four folks (pp. 5-6) consider M-V-C a composite design pattern, where the individual design patterns are Observer, Composite, and Strategy.

Link to comment

In our components the Model publishes its state.

My preference is more along the lines of Paul's "other flavor" MVC implementation. There is no direct communication between the model and view at all; it all goes through the controller. (Instead of a triangle my three components are in a line with the controller in the middle.) The controller is where I put the glue code that translates output messages from one into input messages for the other. I actually don't like calling it MVC because I don't think it's an accurate description. It's closer to a Model-View-Mediator architecture, but that's not exactly right either.

I prefer a hierarchical messaging topology. In that system the thermocouple sends out a single Temp message to it's owning mediator, which then forwards it to the next mediator, and so on down the line. Copies are only made if a mediator has to forward the message to multiple destinations.

Excusing my horrible flowchart design, are we talking about something like this?

post-15786-0-76975100-1328907695_thumb.j

Edited by jbjorlie
Link to comment

Excusing my horrible flowchart design, are we talking about something like this?

Well, Dave and I are advocating different things.

In practice, our project uses a hybrid approach. This is from our presentation last August:

post-6989-0-47233900-1328914000_thumb.pn

Description:

A user clicks a button on the view. The view code handles the button event and publishes a value (a demand). (Note that another view or controller in the application can publish this same demand, if we so design it. This is great for designing a hierarchical system.)

The "Data Listener" for the component subscribes to all relevant demands (really any input data) for that component, and upon receipt of a new demand creates a corresponding Command object (see Command Pattern), which it publishes. Hence the Data Listener is a sort of mediator, I suppose.

The Controller subscribes to Command, and responds accordingly. When there is something to do it invokes methods on the Model.

The Model changes state as appropriate, and publishes updated aspects of its state to appropriately named topics.

The View subscribes to these state topics. When a value change event occurs, it updates the appropriate indicator. (Binding the indicator to the shared variable is another way to accomplish the same thing in the very simplest cases.)

Note that multiple Views can subscribe to the same information.

We have implemented a number of systems now and I think this is really quite elegant.

[some details: We actually use programmatic access to SVs. Also we right justify and fix the digits for numeric indicators and use proper units. For this and other reasons we use events rather than shared variable binding in most instances.]

Link to comment

In practice, our project uses a hybrid approach.

I assume your "Model" is self sufficient and processes internal events through its own "mediator(s)" thingys? If not, what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

With that in mind, this updated flowchart may be inaccurate but I would appreciate more feedback on this:

post-15786-0-62909100-1328919194_thumb.j

Link to comment

Excusing my horrible flowchart design, are we talking about something like this?

Close. What you show is more of a mixed model. A strict hierarchical messaging topology looks more like this. (I don't know what those symbols mean in a flowcharts, but here it just represents one "thing" and multiple "things.")

post-7603-0-36901200-1328915889_thumb.pn

A couple things to note:

1. The "things" on the diagram do not represent individual vis or even classes; they are loops. IMO loops are the fundamental unit of execution.

2. The hierarchy represents "is responsible for," not "is dependent on." A vi containing a sub loop may or may not be on the block diagram of the mediator vi. I think it's easier to start with the responsibility tree matching the dependency tree, but it is not a requirement.

3. The purpose of a mediator loop is strictly message routing. They don't do any file IO, VISA commands, etc. This helps prevent message queues from getting clogged.

4. The messages the mediator loop accepts from and sends to "higher" loops define the public api for all the functionality below it. Mediator loops also handle message routing between its immediate sub loops. (i.e. Messages always go up or down; they don't go sideways.)

5. The diagram shows the controller being responsible for the UI and Model components. In truth any of them can be responsible for the other two--it just depends on your goals. It's probably most common to use the UI as the root.

There's a lot of other little bits of information rattling around in my head... I'd better stop there lest I get too long winded.

...what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

This is just my opinion, but the model should be self sufficient except where user interaction is required. I'd definitely put temperature monitoring and automatic shutdowns in the model.

Link to comment

I assume your "Model" is self sufficient and processes internal events through its own "mediator(s)" thingys? If not, what happens when a change in the process value necessitates some additional actions on behalf of the model? Overheating! Turn heater off, ... Does that go through the VIEW and back down? Maybe I am assigning too much responsibility to the Control and it should not be doing things like running PID loops?

OK, the Controller executes Commands, which simply invoke methods on a Context (see Command Pattern). The Context methods (also trivial) delegate their instructions to State methods (see State Pattern) that implement a state machine.

The State methods invoke Model methods directly (OK, via an interface).

The State methods determine which Model methods to call based on:

1) A new external trigger (user interaction, message from another system)

2) An internal trigger (overheatingIsTrue). The Model has a method that calculates that overheatingIsTrue (and will create an error or warning as appropriate) but it does not determine what to do in that circumstance. The state method does. This is actually quite important.

To reiterate, the State methods know what to do but not how to do it. The Model methods just now how to do what they are told.

By the way, we treat an interrupt or other start loop trigger as just another instance of an external trigger (external to the controller thread, but running on the the same hardware in the same application). This simplifies things dramatically.

Within our State methods we have exactly two methods where we wire an error cluster input to a case structure!

[by the way, I view the state machine as part of the controller, not the model. I think the definition of the two is sufficiently ambigous in the literature I have read that you could alternatively define the "model" to encompass what I am calling Context, State, and Model here.]

Link to comment

Great information fellas, I hope I can return the favor somehow someday. Thank you, I had the model looking more like the set of instrument drivers and not the loops that control them. Now it is much more clear how I should be approaching this AND how to name what.

There are many more questions coming but I need to take what I've learned and put it into action first. Also, I'm leaving the Actor Framework to a smaller project in LV2012 and walking the LapDog through this one :yes: It sure is tempting to try and use them all though! Why is it so painful and expensive to be an early adopter? :throwpc:

Link to comment

It's not so much early adoption as it is hours spent up front instead of 10-fold on fixes and more fixes. A well designed application is more or less hitting the ground running, and you can focus on adding functionality or the next application instead of perpetually fixing the old ones.

So the pain you feel is just because you do all the work up front, and the sum of it is much less than if you look back at the work put into a poorly designed application :).

Cheers,

Steen

PS: I hope the "holiday dinner" feeling has faded - for the record I believe the debate about using Shared Variables or not is very much in synch with the topic (if that was the topic you felt sidetracked your thread a bit here). My experience with SVs, which I described here, was a direct response to your "I now see no reason to avoid shared variables for sharing data between vis when only one vi is ever going to write to them" statement. And that experience didn't come cheap. Just for the record. Didn't want to swamp your voice :P.

Edited by Steen Schmidt
Link to comment

A well designed application is more or less hitting the ground running, and you can focus on adding functionality or the next application instead of perpetually fixing the old ones.

Very good quote! If I ever throw that into a presentation I'll give you credit.

As for the holiday dinner, it wasn't so much of getting sidetracked than of many related but distinct conversations going on at once. Not bad, just hard to follow for my experience level. Thanks for all your input, I am glad you came back with some pitfalls of SV's and I am now thinking of messaging all my process values, LED's and whatnot. The result will depend on my skill, I suppose, and if it is too slow or creates too much complexity in message handling I may give your vi registers a try for those needs. The registers are completely self-sufficient, yes? If I remember right, they just drop onto the block diagram without the need for any database or administration type vi's? Do you think they will be highly portable to future LV versions?

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.