Jump to content

shoneill

Members
  • Posts

    867
  • Joined

  • Last visited

  • Days Won

    26

Posts posted by shoneill

  1. Warning: I'm not a scripting veteran.  I know my way around vanilla Vi Server pretty well, but Scripting is still (kind of) new for me.

     

    I am looking into the possibility of scripting a different kind of accessor for a "framework" (I use the term loosely) I am working on.

     

    What I'm really not sure about is whether I should try to leverage the VIs present in the "\Framework\LVClassLibrary\" directory.  Most are password protected and I'm unsure as to whether the work will be easier wrangling the existing code to do what I want or just doing it from scratch....

     

    I don't need IDE integration, just code which can be run when needed.

  2. Nobody moved the relevent posts across, so I'll have to cut and paste bits here instead instead of quote the originals.

     

    Hmm. Composition Vs Inheritance. I'm half tempted to show you an example without classes at all just to show that using lists has nothing to do with inheritance. As for composition. I though you were proffering the Composite Pattern. When you talk of composition, I think of [object] composition like the image below which is a form of inheritance IMO :wacko:

     

     

    I am and I am.  I am referring to both the composite pattern AND composition, both terms being used correctly.  The idea of a Frame containing a List class internally and handling this WITHIN the borders of it's encapsulation : not exposed) is composition in the classical sense, one class containing another in order to implement some aspect of the functionality in a sub-class.  The fact that this Frame incorporating a List (which accepts Frames as items) is also a Frame object is the Composite Pattern.  The item representing multiple instances of a defined object type is transparently exchangeable with an item representing a single instance of the same object type.

     

    As to your image.  Hmm, I see no evidence of composition here at all.  There's only a single object wire, no observable sub-objects.  I think you're simply showing inheritance at work here which is most definitely NOT composition (in the generally accepted sense).  If you're defining some super-literal definition of composition then you need to make that clear but the standard definition of composition is that a class "car" can have  four "wheels".  If each "wheel" is itself an object (different inheritance hierarchy than "car") then by giving an object "car" four member classes of type "wheel" allows the actual implementation of "wheel" to vary independently of "car" and also allows run-time substitution, something which Inheritance cannot.  It would theoretically be possible to replace four standard "wheels" with jet propulsion units without having to modify "car" at all.  Only the Interface for "wheel" needs to be compatibly with the implemented functionality.

     

    In your case, "Truck" IS A "Vehicle".  This is Inheritance.  In my example "car" HAS "wheel"s, this is composition.  It's identity versus possession.  Two very different approaches to essentially different problems.

     

    Nothing to do with discussion

     

     

    Good, then let's move on.

     

    So this is a "what if" scenario that doesn't really pose an issue for lists, but is the type of thing the pattern was designed for. I'm not even sure I understand "interface bloat" in terms of a LabVIEW implementation since I either use the TList Vis or use the "Frame" VIs which at this pint probably only has one or two VIs (Get Result and Execute?). Each child is also free to handle its own "aggregation" however it sees fit. You can also have "several different flavours of collections (lists)" as well as Steps, Actions and any other classes you care to include but the main thing we want to do is move them around within the list, change their order and add and remove them so it;s hardly bloat if we are actually using those functions.

     

     

    Well I think a "What if" scenario when the problem has been defined as variable, i.e. not knowing which requirements are going to come next as was expressed in the original post, is an important thing to consider.

     

    The aspect of Interface bloat is easy to understand.  If I take one of your Frame objects I can call each and every public method of your List class on my Frame.  Even if they're not required.  Even if they're not on the Menu but they are there and any tool which auto-populates a menu to show accessible functions will be bloated.  The methods are there and supported.  I'm referring to the actual Class interface, not whatever is shown to (or hidden from) the user.

     

    Another topic: So which object type does your List contain?  Some generic datatype?  So I could feasibly call Frame.Add Item and pass it an Action and similarly call Action.Add Item and pass it a Frame?  Or do you have some way of hiding these methods of your List after inheritance?  The only thing I can think of is "Community" scope but IIRC this is bugged to hell.

     

    I consider a collection to be the same as a list, so your first sentence doesn't make a lot of sense. But no. In LabVIEW you don't have the exposed methods unless you override explicitly so I'm not going to create a VI in the child for every VI in the base jsut to give me the right coloured squares. I will just use the base class VIs. Granted in C#, Delphi et.al your code completion list will be shorter so you can reduce "interface bloat", but they get those automatically without writing skeleton functions. We don't have that in LabVIEW so interface bloat is moot as far as I'm concerned.

     

     

    The bolded term is simply wrong.  Flat out, no discussion.  I can call ANY public methods you have defined for your List on any Frame object.  It will call the Parent implementation (I think this is what you're getting at) but I can do this, it's legal and there's nothing to stop me doing it.  Depending on how you present your VIs to the end-user you may have any subset of the interface listed there, but doing so does NOT remove them from the interface.  The methods are there, they can be called and they do something.  You even say later that "I will just use the base class VIs.".  Exactly.  But why have those methods available when they're not always needed?  That's interface bloat right there.  Parent methods are just as much a part of an object's interface as it's own.  This is because the child IS A parent (inheritance).  Making a shorter list, looking only at that level of the inheritance hierarchy or just plain pretending the methods do not exist for that object does not mean that the methods are not there.

     

    So for Frames which are only a single item and will only ever BE a single item, the List methods are bloat.  Taking things further, if (beyond Frame initialisation) you never need to deal directly with the List functionality, having them there is bloat, exposed methods which at best confuse and at worst destroy any encapsulated functionality you might have implemented.  What if I choose to Add a new item to a List half way through execution so that the currently executed step is suddenly a different one?  Why have methods available which are unneccessary?

     

     

    The downsides I see is that it really doesn't give you much and it kind of fixes you into an application architecture that may not be that good for other aspects. For Sequences and Steps (slipped back into TS terminology as we don;t really know what a Frame is) they are just line items in a list. It is "actions" that actually do stuff and everything else is just ordering the actions. All you really need is a list and execute to manage sequences, steps and actions. What you actually execute is a different matter.

     

    Here we have things backwards.

     

    Inheritance (inheriting from List) fixes us into the fact that each and every Frame is a List for ever and ever, immutable.

     

    Using Composition, those Frames which need to be a List can manage their list privately, knowing what to do when told to execute.  If one wants to have a Collection, one wants to have a State machine, one wants to have a Client-Server connection, if one wants to pick random items from disk or whatever then each and every Frame is free to implement the grouping methodology it requires and handle it appropriately when told to execute.  That fixes you into nothing.  It frees you to do whatever you need whenever you need.  You can access the EXACT same functionality as with Inheritance but the List methods will NOT be callable on Frame.  When a Frame with an internal List is told to execute, it will call the appropriate methods on it's List without the caller needing to know or see any of it.  THIS is the composite pattern combined with composition.  Allowing you to treat a List of Frames as a Frame as the same type of object is the composite pattern.  Using an internal List to give extra functionality and choosing which methods (if any) are exposed is composition.  By doing so you also expose "Add" functions which accept ONLY Frames which prevents a cross-communication with other object types, something which the normal "List" methods cannot do.

     

    Shane

  3. I never said that I was using a pattern of any kind. All I am doing is using common denominator implementation for a very specific part of the problem.

     

    I also made no claim whatsoever that you were using any kind of pattern.  I was comparing with a pattern.

     

    The obvious drawback of your idea is the static linkage to the List class.  While the List class is most likely a lovely piece of work, if you want to implement a Frame as a different kind of grouping (don't ask me, I'm just theorizing, perhaps a conditional looping of individual elements until a condition is met) then either you build that into your List class or you implement it separately in your child class.  By moving the List functionality into the child class, each child is free to implement whatever method of aggregation they see fit without requiring interface bloat.  Each item implements whatever it needs.  You could have several different flavours of collections (lists) which do things different based on some corner cases.

     

    You also cannot hide the interface to the List aspect of your objects which is something you CAN do when the child implements it (in fact it almost requires it).  Depending on your taste you might prefer one solution over the other.  If I want to do something with a Frame, why does the interface for that object insist on telling me it's a list when that's not something I need or want to be confronted with.  It creates noise in the interface which is seldom a good thing.

     

    So imagine a "collection" which internally manages a List (your class).  When dealing with a collection (strictly typed child of Frame), you have the exposed methods for the list, when working with Frames (when you don't need to know whether it's a list or not) you have a much cleaner interface.  By moving your same List class up two levels of the hierarchy you gain a lot of flexibility and remove static linkage to the functionality of your list.  What are the downsides you see with this approach?  The only downside I see is the creation of some proxy VIs which, depending on your taste might be enough to sway you.

     

     

    I know what you are getting at, though. This is a good example of the tradesmans viewpoint dilemma or if you go back a few years the very similar Bottom Up Vs Top down design argument. I have stated on previous occasions that I use both in every project (diamond design) ;)

     

    I don't want to weigh this relatively focussed topic down with previous discussions which may or may not be applicable and to which I was not a party.  I also don't mean to be nasty but your usage of both has no relevance to the discussion.

     

     

    I suggest we get into that on a new thread if you want to explore it further as it could go on quite a bit. :D

     

    That's fine by me if you think it requires it.

  4. Uhuh. Like the List object I described earlier ;)

     

     

    Almost.  There's one major difference you're missing out on here Shaun.

     

    When designing the "list" according to the Composite Pattern the List itself is an instance of the objects it contains.  You cannot do that with your List class.  If I make a List of "Frame", the List is a List, not a Frame.  In the Composite pattern, the List is also a Frame, allowing it to be placed in another List and so on recursively.  It's the interchangeability of the List and the object it contains which is the essential part of the Composite pattern.

     

    In BobDobbs code shown above the user can program with a Frame Collection or Frame interchangeably.  In your case, all of the objects are inheriting from the List class so you're going about things the opposite way.  By making EVERYTHING a List you also have a single interface but the downside is that when you DO want to have a single object rather than a collection or list, you still have a list (and associated now non-functioning interface elements).  This is a variant of the problem where the "single interface" is the sum of all possible implementable interfaces within the problem space.  Why, if the user program doesn't need to know, is it presented with a List Interface for the objects being processed?

  5. So, consider that there's 8 DUTs. These DUT's are more or less alike and will be tested by the same piece of hardware. This piece of hardware applies a voltage to each DUT, but can only apply that voltage to one at a time. The amount of voltage that's applied is specific to a sequence that is specific to each DUT. So DUT1 may get [5v, 3.3v, 5v, 1v, 3.3v] and DUTmay get [3.3v, 1v, 5v, 3.3v]. Which step of each DUTs sequence that we're on is determined by the group. So, there's a Group0 which does some pre-work, but applies no voltage, and starting with Group1 we apply the first voltage. Also, each Group may apply the voltage in a little different way, maybe we pulse the voltage 5 times, maybe we apply a voltage and wait, than apply the same voltage again. This is defined by the Steps. So, all of the DUTs have a Step performed on them, than we go to the next Step. When we run out of Steps we either increment the cycle count of the Group, or move to the next Group if we've reached the last cycle of this particular Group. Steps contain Functions, and each Function is performed fully on a DUT before you move on to the next DUT. So DUT1 has the first Function performed, (which is something like, move the DUT to the voltage source, apply the voltage, wait, stop the voltage), than DUT2 and so on until we've done all DUTs and than we go back to DUT1 and do the next Function. Each Function consists of the specific Actions that define how to apply the voltage, the move, voltage on, voltage off, etc... There's also those random requirements that are thrown in (that always caught me up on my CLD and CLA test) like, the last voltage that we apply always has to be applied at the same time for all DUTs, even if some DUTs have shorter sequences than others (so in the above example the 3.3v of DUT2 would get saved to run with the 3.3v of DUT1) and some certain aspects of a function (repetitions for example) are specific to what voltage we're applying that cycle. 

     

    The composite pattern is not really what you need here since you admit yourself that the different levels of the hierarchy require different interfaces.

     

    What you need is simple object composition (a grouping of objects to increase functionality) which is NOT the same as the Composite Pattern.

     

    I think your different object hierarchies are relatively clear.  Your confusion arises perhaps from the false expectation that all levels of your object composition need to share interfaces.

     

    So a Group is a single step for ALL DUTs, right?  Group 0 is Initialise essentially, Group 1 is Step 1, Group 2 is Step 2?  This sounds like it may actually be a candidate for the Composite Pattern.  Why not implement a Group as a Composite of Step with the same interface?  This will allow you to treat groups and steps transparently.  I don't know if that functionality would actually aid your development, I'm too far away to be able to judge that but it would allow you to have "Virtual DUTs" which are actually comprised of several individual DUTs.

     

    Your functions are a completely different beast, as are your Actions.  Again you could theoretically define Functions and Actions so that the Composite Pattern could apply.  Again this would allow the generation of an Action which actually contains several other actions.

     

    Part 1:

     

    Base Class : Step

    Child Class : Group (contains 1..N Steps)

    A Step is an object which represents a stage of your testing procedure for a single DUT.  A group represents the same thing but for 1..N DUTs.  A group may contain other groups.  A group and a Step can be used interchangeably within the program.  The interface you would code to is that of the Step (Parent class).

     

    Part 2:

     

    Base Class : Action

    Child Class : Function (contains 1..N Actions)

    An Action is a single action (Set Voltage, Raise Alarm, whatever). A Function is also an action but contains 1..N other Actions.  A Function can also contain other Functions (Hierarchical definition of test procedures).

     

    So I could imagine (without in-depth knowledge of EXACTLY what you're trying to do) that you could use a combination of Object Composition  (Action&Function or Step&Group) and the Composite Pattern (Step contains 1..N Actions) to achieve what you want.

    • Like 1
  6. You can do this better with the blending bin and blending mode.  Your solution is always running after the 3D control to patch things up whereas a solution with the correct blending bin and blending mode will be automatic.  I recommend you re-visit the other methods posted as it's a far more robust solution.

  7. Well if you don't have a plug-in architecture working yet (which would be one way to solve his problem) you need to have your classes included statically somewhere in your code.

     

    Why not make an array of your implemented classes and simply call an "ID" method on them returning their IDs which may or may not be different from their names on disk.

     

    How are you managing all of your different classes at the moment within your program?

  8. The only way I can think of is to add a (public) boolean element to the Child to signal whether it should execute it's version of the overridden function as opposed to simply passing it on to the "parent".

     

    It's dirty and feels wrong but might be a way out of your predicament.  I mean, which is MORE wrong, this construct or simply duplicating code?

  9. That's why I thought it sounded familiar.  I'm pretty sure my problems are also linked to the separated compile code and the cache.

     

    I personally tried deleting the cache, but after making one or two edits the problem just came back.

     

    If I make it to NI Week this year and I'm bald, faulty deploys on our RT system will be the reason.  I really do feel like tearing my hair out at times, it's extremely frustrating.  Debugging on FPGA is a walk in the park in comparison. :throwpc:


    One topic plodding around in the back of my head:

     

    Wim, What are your locale settings?  I presume, like here in Switzerland, you have a comma as a decimal separator?  Maybe there's a bug somewhere where some string somewhere isn't paying attention to the system decimal point?  If so I'm switching locale tomorrow.....

  10. However, the issue is already fixed.  Can't tell how... I don't understand it.

    I copied it to my test system and VISA is running fine too.

     

    Strange solution ....  Was the build spec corrupt?

     

    I really can't tell but I'm glad my exe is running as expected now.

    Ooh, this sounds familiar.

     

    I have been running into issues with very similar symptoms recently.  My code is on a RT system and I have noticed extremely weird behaviour when deploying.  Sometimes it will simply NOT deploy the current code from the Object cache, even if I force a recompile of the top-level VI.  What I have obeserved is that if I edit some sub-VIs in a different context (a project with only one target so that objects are not locked for example), these changes do NOT get automatically detected in the original context (even after closing and opening again)  The fact that my sub-VIs are inlined may or may not be relevant.

     

    I have had situations where my testbench would run a function absolutely according to spec but when deployed (Save, close Testbench project, open main project, compile, deploy) it would behave as an older version, even after forcing a recompile of the entire hierarchy.  I managed to "fix" it by placing a global write in a specific sub-sub-sub.vi in the proper context.  Then it compiled properly and deployed correctly.  I have the feeling that some "other context" edits are getting obscured somehow int he system.  But don't ask me to reproduce it, I've been trying for years.  Each time I try to pare down the code to get an example running, the problem goes away.

     

    I'm running LV 2012 SP1 with separated source code.

×
×
  • Create New...

Important Information

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