Jump to content

Decoupling the UI


Recommended Posts

I guess my original point is not getting across.

Yes it certainly is, as I stated this:

Given you have stated that your requirements are absolute decoupling, I still wanted to point out...

Because I agree with this:

"Decoupled" isn't a binary attribute--it's a gradient.

yepp. that structure you describe is called a "distributed software".

And because we do a lot of this stuff too, a distributed system that has multiple instances of client UIs that communicate with (usually NI Targets e.g. cRIO). Comms is either TCP/IP or OPC etc..

So I know what your requirements mean.

I just think, there is validity in discuss various options or gradients given the OP's question (and that the topic is interesting).

Because even when you write the distributed UI, if you choose to implement it in LabVIEW, then you still have the choices to decouple that code, so talk of references is relevant!

Link to comment

Complex requirements cam be broken down into many simple solutions that together solve the complex one.

I don't disagree with you. However, many small simple solutions put together doesn't necessarily equate a simple overall solution. But that discussion is way off topic so I'll do something really unusual for me... I'll stop. ;)

  • Like 1
Link to comment

are we fighting? oops ...

sorry guys, my english is not that good that I would recognize the fine nuances. I only understand the technical terms and "hidden intentions" if they are obvious ;) ... but if you want to blame me for that, just do it, I'm used to it ;)

ok, back to topic: I don't think that using references of the controls of a user interface adds "more" decoupling than using e.g. an event strukcture, because in the end you have to write code, that handles all that user interactions, and if youi don't use an event structure, you'll have to write all that code on your own. OK, you gain more decoupling in a technical sense, but in the end you have to reconnect the UI and the parts of your code, that do the "work" so if it's not offensive I'd like to ask the question: what should be "absolute" decouping good for?

cheers,

cb

Link to comment

Yup, it's all Shaun's fault. :P

No, seriously, this is a great discussion and I'm just waiting for the dust to settle a little.

As for my own applications, while I like John's approach, anything that runs any sort of web services is a no-no. The Information Assurance Security Gods will rise up and smite me. I'm actually in the midst of turning a perfectly fine functioning webpage into a standard UI interface to get rid of a bunch of "IA deficiencies" on our Solaris side. :frusty:

Link to comment

Cat - Web Service support SSH, if you need it.

And, there is no reason you need to use them for a decoupled UI. You could just as easily use a queue if you UI and core are both running on the same machine in the same app instance.

The benefit of a decoupled UI is: can replace or change without affecting the core code. Can use message channel to automate core (headless). Can use message channel to test core and UI separately. Cna log message channel for field debugging.

Downsides are: more code to write. Not as easy to implement, design wise. Might offer slower performance in high speed apps.

Link to comment

Cat - Web Service support SSH, if you need it.

And, there is no reason you need to use them for a decoupled UI. You could just as easily use a queue if you UI and core are both running on the same machine in the same app instance.

The benefit of a decoupled UI is: can replace or change without affecting the core code. Can use message channel to automate core (headless). Can use message channel to test core and UI separately. Cna log message channel for field debugging.

Downsides are: more code to write. Not as easy to implement, design wise. Might offer slower performance in high speed apps.

"There is the rub" (Hamlet, Act 1 scene 1 ?)

Ben

Link to comment

"There is the rub" (Hamlet, Act 1 scene 1 ?)

Yes, but only if you app is trying to display data at high speed. If your app is some sort of automation control app, you likely are not doing anything that a 1ms delay could affect. And, in most cases it is less than that. Additionally, there are ways around this by creating a separate dedicated channel for the high speed data and having a separate UI loop handle it.

Link to comment

Yes, but only if you app is trying to display data at high speed. If your app is some sort of automation control app, you likely are not doing anything that a 1ms delay could affect. And, in most cases it is less than that. Additionally, there are ways around this by creating a separate dedicated channel for the high speed data and having a separate UI loop handle it.

We're on the same page. The point I would like to highlight is decoupling, although desirable for flexibility and re-use is not nessarily desirable in all applications and should be carefully balanced with other requirements.

Ben

Link to comment

Of general interest to future readers is a presentation Tomi did at NI Week 2010. (Link to slides.) Slides 12-14 illustrate the concept of decoupling the UI.

You want the UI to be extremely lightweight, and if you have 'skinnable UIs' you don't want duplicate code in the UI's.

Interesting idea. I had never considered skinnable UIs. I suppose as long as your references don't penetrate into the domain layer you're still maintaining a nicely decoupled UI. When you do this, how much code do you have on the UI block diagram? Is the UI still your 'top level' vi in the dependency hierarchy, or is it more of a 'bolt on' component that can be easily swapped out?

The point I would like to highlight is decoupling, although desirable for flexibility and re-use is not nessarily desirable in all applications and should be carefully balanced with other requirements.

This comment gave me cognitive dissonance and I've been thinking about it for the past couple days. I agree that flexibility and re-use are not necessarily explicit project goals and all requirements need to be balanced, yet the idea that decoupling would not be a desirable characteristic in any app of reasonable size is... dissonating.

Decoupling (in general, not just the UI) does more than just improve flexibility and reuse. Most notably, testing a decoupled component is much, much easier than testing that same functionality in a tightly integrated system. It also (IMO) makes development easier as there is a clearly defined api that can be implemented without worrying about hidden interactions with other components. While I have never has a customer explicitly require decoupling, the requirements they do specify (as well as the implied requirements, such as fixing bugs in a timely manner) always lead to at least some degree of decoupling.

I'm not disagreeing with you... just verbalizing (or textualizing?) the way I resolved the dissonance.

Link to comment

...

This comment gave me cognitive dissonance and I've been thinking about it for the past couple days. I agree that flexibility and re-use are not necessarily explicit project goals and all requirements need to be balanced, yet the idea that decoupling would not be a desirable characteristic in any app of reasonable size is... dissonating.

Decoupling (in general, not just the UI) does more than just improve flexibility and reuse. Most notably, testing a decoupled component is much, much easier than testing that same functionality in a tightly integrated system. It also (IMO) makes development easier as there is a clearly defined api that can be implemented without worrying about hidden interactions with other components. While I have never has a customer explicitly require decoupling, the requirements they do specify (as well as the implied requirements, such as fixing bugs in a timely manner) always lead to at least some degree of decoupling.

I'm not disagreeing with you... just verbalizing (or textualizing?) the way I resolved the dissonance.

Many of my apps came to me as "NI said it can't be done" (or antoher third party)due to the extreme performace demands (Real-time NDT is an example). These apps typically can not tolerate using the UI thread (which is required if using property vlaue nodes)to do the updates. Additionally duplicating data is a big no-no since there is barely enough memory for the first copy let alone the copied version.

So althought Decoupling and OOP ideas in general are useful when developing, if my apps is the "perfect LVOOP" app but runs like a dog, its harldy perfect.

Ben

Link to comment

Many of my apps came to me as "NI said it can't be done" (or antoher third party)due to the extreme performace demands (Real-time NDT is an example). These apps typically can not tolerate using the UI thread (which is required if using property vlaue nodes)to do the updates. Additionally duplicating data is a big no-no since there is barely enough memory for the first copy let alone the copied version.

So althought Decoupling and OOP ideas in general are useful when developing, if my apps is the "perfect LVOOP" app but runs like a dog, its harldy perfect.

Ben

Question:

This idea comes to me because I once read that LV was an early inventor of the idea of "time" in programming (I don't remember when or where).

Is the idea of "Time" reflected in OOP ?

I can't recall running across the speed ever entering into the game.

Ben

Link to comment

Just to throw in my salt on OOP and high-performance apps, get rid of the OOP-vs-non-OOP concept. (LV)OOP is building organically onto the concepts (e.g. AEs, type'defed clusters) we used to do before. It's just adding architectural layers. The other way round, don't forget what you have learnd befor LVOOP, there are the same nodes still in the code!

We need to take the same care when going into high-performance code as before. Having additional layers seems like a pain, if you ignore that they are vectors in a different dimension.

To be a bit more practical than my introduction, let's take the example of a very big data set -> no copies allowed. So what did you do conventionally? You changed the code from wireing the data (passing SubVI boundaries, branching the wire) to encapsulating the data in an AE.

Now let's don't make the mistake of thinki think that an LV-Object is just an AE with a wire. Of course, now we get the encapsulation-possibilities of AEs, but not the inplaceness of AEs.

Going back to step 1 again, why the f*** are we 'required' to place all data of the class in the 'private data cluster'. Nothing forces us. There is a thread by AQ discussing a WORM-global as being acceptable if it would be private to a library. To be more specific, when you don't have any access to the class private data, you won't be able to tell weather it's stored in the class private data, a global or an AE.

Now let's even go a step further, the public interface (Accessors + Methods operating on that data) are the sole place you need to change to switch from a too-slow in-the-cluster datastorage to a faster in-the-AE datastorage.

On the architecture level (thinking in uml), this would be just the use of a 'nested classifier' (e.g. a class which scope is limited to the containing class; and as an AE missing functions like inheritance -> you really do not need that if it's private anyhow!).

Just to summarize, I can't really see a big conflict between OOP and before-OOP (OOP is just adding a set of new features, albeit I considere them so important that I like to call them dimensions). It's all data-flow. :yes:

Felix

Lost thought (I don't know where to insert it above): If a C++ programmer was doing a high performance app, what would he/she do? Make as class data a static array for that data and shoot with pointers at it. How OOP is that?

Link to comment

Nice discussion. I would like to add that an easy way to determine a decoupled UI and engine would be if you could test the engine without any UI in the first place. If you have an automated test bench for your engine that does not use VI server to generate UI events then you probably have a loosely coupled UI.

Link to comment

When you do this, how much code do you have on the UI block diagram?

About this much:

post-10325-0-44015600-1297950323_thumb.png

Get all the references, then its just handling events (sends message to engine) and receiving event (normally data to update screen etc...)

Trying to keep it simple: with skinablism - minimise duplicate code

More complicated stuff is done via references - configuring graphs etc...

Is the UI still your 'top level' vi in the dependency hierarchy, or is it more of a 'bolt on' component that can be easily swapped out?

Nope,

post-10325-0-51060700-1297950324_thumb.png

In the case above the engine can run the UI thread (or another higher-level VI could run all threads, but old habits).

If you want to change the UI then drop and new one in and delete the old one.

Of course you could do it more spectacularly (e.g. dynamically instantiated etc...) (code to switch between the UI's at Run Time etc...) but this project did not need it, nor could I be bothered (I just want to decouple the UI further).

As per your 'slave loops' it easier to program on the separate thread just be double-clicking to open it.

Link to comment

Just because you passed all the reference from your FP to a sub vi does not mean you are decoupled. The sub-vis still need to know what is on the FP and how to control it.

To be decoupled, you would need your FP to have code behind it that received data from the core engine and then decides how to display it based on your UI's layout.

To return to a point I made awhile back, if you UI and core engine cannot be on separate computers on a network, then you are not decoupled.

Link to comment

To return to a point I made awhile back, if you UI and core engine cannot be on separate computers on a network, then you are not decoupled.

Well. I think that's a bit extreme. That's like saying it's not programming unless it's POOP wink.gif.

Whilst a network interface can be used to achieve decoupling. I don't think it's a requirement - just an implementation method,

Link to comment

Whilst a network interface can be used to achieve decoupling. I don't think it's a requirement - just an implementation method,

That is not my point. frusty.gif A network interface is just an example. The interface could just as easily be a queue. The point is it CAN be sent over a network if you so choose. In other words, the UI and the core engine know nothing about each other's implementation. They just pass data over a <insert generic interface here>. If you are passing references from your UI to your low level code, then you low level code must know a lot about your UI and therefore you are not decoupled.

I'm not saying that is a bad design. I do it all the time. I am only saying that it should not be considered a decoupled UI design.

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
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.