Jump to content

Destination: Task


Recommended Posts

Actually, there I have a bigger problem. I don't require the user to drop a constant because the "constructors" don't have a class input. Instead, the user needs to select a specific VI. This has advantages in that each VI can have different inputs, but it does cause problems in the logging challenge in that there is no VI in the base class. That would mean that we would need to create a logging VI for the base class and then have every constructor call that VI.

But again, this is not because of the LVOOP thing, but rather because I use separate VIs (which I would anyway, since I want different inputs on that VI).

It does have something to do with LVOOP since the ease of use is basically derived from overriding a base class. Rather than the user having one VI (or class) that he/she is choosing VIs from, They now have to pick some from the base class and some from the other classes. This doesn't sit well for me as it (in my mind) it breaks encapsulation. What would you suggest to mitigate that?

Lets look at it a slightly different way in that: what would happen if I too wanted to make different inputs as you want to do?. I would have to split out the "Listener" and "Open" cases into single VIs (one for each interface) and wrap them in a polymorphic VI. The advantage here for me is that the users choice of interface is decided by what type of control and where it is wired. I'm no worse off than classes but I have more VIs to maintain and test

However, that causes me an additional problem in that I can no longer distil all the functionality into one "Transport.VI" that the user simply chooses a function from a menu. I need to split out read, write, close open and listener into separate VIs since you cannot nest polymorphs (read, write etc are separate anyway, but the user doesn't see that). I am, basically, requiring the user to do do the same as you, They have to manipulate a number of VI's instead of just one. OK, I could group them in a Virtual folder but as I add the CRC and packinging VI's I'm getting further from a one-stop shop for comms. So in this case, I have sacrificed the encapsulation derived from my top level polymorph for the ability to type the inputs. Although my Virtual folder is now looking remarkably like your base class.

How would you start to add the CRC and packing VIs? They don't fit with the base class template so would you add a new class for each?

Link to comment
It does have something to do with LVOOP since the ease of use is basically derived from overriding a base class. Rather than the user having one VI (or class) that he/she is choosing VIs from, They now have to pick some from the base class and some from the other classes. This doesn't sit well for me as it (in my mind) it breaks encapsulation. What would you suggest to mitigate that?

That depends on how much functionality you add in the base classes. If you have all (or almost all) of your actual VIs available in the bottom level class (say UDP), there's nothing preventing you using only VIs from there. If the VIs are overriding, then changing the wire type to TCP will automatically use the other VIs. Other than that, I don't think anything more can be said - if TCP is a Transport, then you will need to know what Transport has to offer as well. Maybe if you build palettes LV will offer you the entire inheritance chain if you right click a wire, but I have no experience with that. If you really want, you could probably build a single palette with all the needed functionality including the constructors (see the next point), but I doubt I would.

Lets look at it a slightly different way in that: what would happen if I too wanted to make different inputs as you want to do?. I would have to split out the "Listener" and "Open" cases into single VIs (one for each interface) and wrap them in a polymorphic VI. The advantage here for me is that the users choice of interface is decided by what type of control and where it is wired. I'm no worse off than classes but I have more VIs to maintain and test

You can take the "constructors" from all the different classes and add them into a polymorphic VI. It would work the same way. I don't think I would do that for one main reason - I'm assuming that at one point the user of the library knows which transport they want to use. At that point, I'm OK with letting them find a specific VI.

...I'm getting further from a one-stop shop for comms...

I doubt that desire can easily be realized in any way other than the one you used (unless you're willing to accept a palette as a one-stop shop). Personally, I don't feel the need for such a design, but I can see its appeal.

How would you start to add the CRC and packing VIs? They don't fit with the base class template so would you add a new class for each?

You haven't given any example of using them and you don't have them in the actual API, so I didn't incorporate them into the API. If you just want to have the VIs as-is, there's no problem with just putting them somewhere. If you want, you could actually create two more hierarchies of classes (compression and verification) and thus use different types. Doing that, of course, is more of an undertaking which is pointless if you know that you only want blowfish and CRC. The really problematic thing would be if you wanted to change the API to add the encryption and verification - because you would presumably want to do this for all the transport, it would have to be in the transport class, which is more complicated, because it would require calling the relevant VI from the parent class in each child class or encoding the data in the parent's write VI and then getting it out of there (which can be done by keeping the data in the class data, but is still cumbersome).

Link to comment

That depends on how much functionality you add in the base classes. If you have all (or almost all) of your actual VIs available in the bottom level class (say UDP), there's nothing preventing you using only VIs from there. If the VIs are overriding, then changing the wire type to TCP will automatically use the other VIs. Other than that, I don't think anything more can be said - if TCP is a Transport, then you will need to know what Transport has to offer as well. Maybe if you build palettes LV will offer you the entire inheritance chain if you right click a wire, but I have no experience with that. If you really want, you could probably build a single palette with all the needed functionality including the constructors (see the next point), but I doubt I would.

I think going down that route there actually wouldn't be much benefit over using the in-built prototypes from the users point of view. He has a load of VI's in his palette which some of which are interface dependent, some aren't. I think I would want a bit more than just amalgamating the read,write and close VIs for the different interfaces considering the amount of code I have to write.

I doubt that desire can easily be realized in any way other than the one you used (unless you're willing to accept a palette as a one-stop shop). Personally, I don't feel the need for such a design, but I can see its appeal.

Perhaps it's a personal preference. But I see it as more modular. I've done similar things with queues and notifiers so that I don't have wires all over the diagram and can safely call it from anywhere without much thought. I strive very hard for this type of "node" and it serves me well.

You haven't given any example of using them and you don't have them in the actual API, so I didn't incorporate them into the API. If you just want to have the VIs as-is, there's no problem with just putting them somewhere. If you want, you could actually create two more hierarchies of classes (compression and verification) and thus use different types. Doing that, of course, is more of an undertaking which is pointless if you know that you only want blowfish and CRC. The really problematic thing would be if you wanted to change the API to add the encryption and verification - because you would presumably want to do this for all the transport, it would have to be in the transport class, which is more complicated, because it would require calling the relevant VI from the parent class in each child class or encoding the data in the parent's write VI and then getting it out of there (which can be done by keeping the data in the class data, but is still cumbersome).

Indeed. there isn't an example, but I only really released the library because it's used by other applications in the CR.

The encryption is in the API. But I never found a "native" labview compression algorithm and didn't want dependencies on dlls (I'm still looking as I'd like that feature and the stubs are in there). I'm not expecting you to write any more code since I think there is enough to discuss the differences. But I've moded the examples to show you how it works with my implementation. I didn't include CRC as I don't think there would be much mileage as it's unlikely that new CRC algorithms are required and it's not really relevant to all the protocols. But it is a useful utility. The CRC is used in a similar way as the Pack/Unpack instances as a separate entity.

As you can see. It's up to the user to use them rather than embedding support at the protocol level. I did toy with the idea of making this transparent too. But that would have severely complicated the ability to turn it on and off on-the-fly. This way, the user decides if he wants to support encryption and only needs to switch by supplying a password or not.

However, classes tend to make you think of embedding to conform to the class hierarchy, so making it a stand-alone module isn't the first thought, (although ultimately preferable I think). That's why I asked the question. I cannot immediately see an intuitive way to combine it into your architecture without a lot of work.

Link to comment
I've done similar things with queues and notifiers so that I don't have wires all over the diagram and can safely call it from anywhere without much thought. I strive very hard for this type of "node" and it serves me well.

But you DO have wires. I happen to like the singleton which gets the reference internally as well, but in this case your one-stop shop is simply a poly VI, which is what I was referring to not needing. Incidentally, as long as the pane patterns match, you can create your poly VI with classes as well.

The encryption is in the API

...

As you can see. It's up to the user to use them rather than embedding support at the protocol level.

Which, as far as I'm concerned, means they're not an integral part of the basic API (i.e. the user has to explicitly use them and they're not part of the R/W VIs). They might be an auxiliary part, but that's easily done with classes as well - all you need to do is add the VIs somewhere and have the user call them just like you do.

I should also point out that this isn't necessarily a problem. It keeps the API simple and manageable and is what I was referring to earlier when talking about Daklu preferring simple APIs.

Link to comment

But you DO have wires. I happen to like the singleton which gets the reference internally as well, but in this case your one-stop shop is simply a poly VI, which is what I was referring to not needing. Incidentally, as long as the pane patterns match, you can create your poly VI with classes as well.

I did say "similar" wink.gif. The point I was making is that I prefer to simplify and modularise. The ideal result (for me) is a single VI with a multitude of uses but a simple (2 or 3 parameter) interface rather than a number of VI's, specifically tasked towards specific functions. A ploy is a half-way house to that goal.

I've already commented on the singleton (anti?) pattern; many moons ago in an earlier post. They are just irrelevant for classic labview and required to get round a problem of your own making (not specifically you, POOPers in general)

Which, as far as I'm concerned, means they're not an integral part of the basic API (i.e. the user has to explicitly use them and they're not part of the R/W VIs). They might be an auxiliary part, but that's easily done with classes as well - all you need to do is add the VIs somewhere and have the user call them just like you do.

I should also point out that this isn't necessarily a problem. It keeps the API simple and manageable and is what I was referring to earlier when talking about Daklu preferring simple APIs.

There is no auxiliary, or basic. there is just API. My definition of that is that it's a collection of functions to facilitate the execution of a task(s) based around a common theme. Perhaps yours is more strict. But I prefer not to restrict myself with semantics

Indeed you can just implement as I do, but for classes that would seem, well, a hack, since you should really be creating an "Encryption" object and passing that as an argument to be used by your read/write VI's.

Well. I think we've come to the end of this little exercise and I thank you for your participation in the absence of the OP. People can draw from it what they will, but I think it was a fair example given that it was very suited to both approaches without prejudice.

so. Only one other thing to say:

.

Shopping.Create;Shopping. Alcohol := 10  /* litres */Shopping.Food:=20  /* kg */Merry.Create (Shopping);Merry. Happiness = Shopping.Food * Shopping. Alcoholxmas.Create (Merry);

biggrin.gif

Link to comment
Indeed you can just implement as I do, but for classes that would seem, well, a hack, since you should really be creating an "Encryption" object and passing that as an argument to be used by your read/write VI's.

I'm not sure what you mean by "should". I could, but I could also just do it the same way you did. It all depends on the requirements and the design decisions made based on those requirements.

Well. I think we've come to the end of this little exercise

I agree.

Link to comment

I used to think that too until AQ and someone else (Adam Kemp maybe) straightened me out. Project libraries will check to make sure all the necessary files can be found, but it doesn't actually load them. (Though it does load sub-libraries.) I have no idea if vis are "loaded enough" for cluster edits to propogate through the library. The details of when something is actually loaded seem rather obscure... I saw a post once from a blue referring to something along the lines of, "dependent vis 4 or more levels down aren't loaded..." (I'm sure I've completely misrepresented what the post really said. I didn't pay much attention at the time and haven't run across it again.)

I've been thinking about this. I wasn't aware that project libraries didn't necessarily load all their dependencies (although I encountered precisely that after I posted but before you replied). You are quite right about the behavior. On the other hand, what I am proposing for this use case is that one put all custom code in project libraries and include all required project libraries in the project. Since each project library loads all its parts, then all items will be in memory, if I understand correctly. So I think my proposal works for this situation.

Of course, I am in favor of using objects in any case!

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.