Jump to content

Aristos Queue

Members
  • Posts

    3,183
  • Joined

  • Last visited

  • Days Won

    202

Posts posted by Aristos Queue

  1. 19 minutes ago, Michael Aivaliotis said:

    It's worse than what you show. I see a lot of typedefs there. One issue with your approach is that there is no guarantee your values will remain when you update your typedefs. I have been using LabVIEW long enough to know that you should never trust typedefs on the block digram to keep the values when they get updated. I would change your code right now because it will fail in the future.

    Is that true in the recent versions? The typedefs got revision protection in LV 2015, I think. If the mutation is going to throw away data, it does the same sort of "relink" behavior as when changing conpanes of subVI so you preserve the data. 

  2. 9 minutes ago, Petr said:

    I see advantages of "constructor" method solution (flexibility, DD/ inheritance, ...). But this produces huge init VI BD (see example for only5 nested objects and imagine the same for 100 objects). I'd like to have something more readable/maintainable. How do you manage initialization/"construction" of hundreds of nested objects?

    Short answer: Make it table driven.

    Long answer: As you scale up like that, you're entering the realm where you aren't going to code those values directly into G. You may be looking at

    • an array of values in G that you loop over to create objects
    • a binary file where you read back the objects you serialized earlier
    • or something as complex as a SQL database with relationships between multiple tables and you process the entire database to create your object layout. 

    These are just suggestions. There are many other options. The point is, you need to make your construction more data-driven instead of directly coded. This is true of all programming languages I've seen, not just G. The notation of objects is such that they come into being as data drives their existence. It's relatively easy to create an object with a given value, and if you're building up objects as they come into existence within a system, everything works fine. But to create an entire system of objects in one burst, you need a data structure that can describe an entire system. That's why things such as object databases exist. 

  3. I agree with Shaun. By the time you ship, of course, you shouldn't care whether auto error handling is on or off (your VI Analyzer tests caught those), but it is invaluable during early development. And if you did miss something (developer submitted a VI late on deadline and didn't quite follow procedure or test machine had a bad day and skipped a step of your build or whatever), having AEH enabled can save you a wealth of time.

  4. So I have this bug report that AppBuilder fails to build this one particular app whenever the "remove polyVIs and typedefs" option is enabled. The top-level VI breaks during the build.

    I try some of our usual debug approaches and don't find anything, so I hack up AppBuilder a bit so that when I get to the end of the build, I can open up the broken VIs and see what they look like. And I see this:

    Untitled.png.634a79c1419f7f2a6910eea30e27ed3e.png

    Where the heck have all the class methods gone? They're in memory at the start, missing at the end. That shouldn't happen! So I set up a trap to detect when the VIs go missing. I'm working in a debug build of LV with a lot of extra guards and logging turned on, so it takes about two hours to run this build. And I get nothing. So I rework my trap, thinking I've coded something wrong. Four times I do this over the course of yesterday, working on other issues while the build runs. Four times -- roughly 8 hours -- nothing. The VIs swear they're all in memory and the caller should know about them. 

    This morning I come in and, for some reason, I happen to double-click on one of those ? nodes. And, lo, the missing VI opens. Say what? Turns out, AppBuilder had stripped all the VI icons out (saves space in the built EXE to ditch all those unneeded images), so they all render as the ? icon.

    Untitled2.png.fee47d43f110336561efb0c86ce4689c.png

    I have no idea what's actually broken, but it ain't that all the class methods have gone away. One wasted day. *head bang*  *head bang*  *head bang*

    Yet another reminder -- as if I needed it -- that computers only do what we tell them to do. And they do it very precisely.

    • Like 1
  5. I decided my previous reply could be taken too snarkily... not what I intended. 

    Let me be explain -- Ernesto is right, and with the lens he's looking through, it's a reasonable position. There's a rather substantial difference between a casual refactor that changed a terminal to be consistent with all other terminals and a foundational logic shift required to make two terminals that are literally the same address in memory return different values -- but that's something I can know with deep knowledge of the code underlying these two issues. No way for Ernesto or any other customer to recognize that. One can be done just by removing what appeared to be a bug; the other would require significant and deliberate retooling of the code. Not to mention it would break regression tests (tests that don't exist for automatic error handling since at the time that feature came along, there wasn't a good way to automatically test for anything that triggered dialogs requiring human acknowledgement). 

    There are levels of trust between tool vendor and tool user, and once those are breeched, the promises of the vendor aren't worth anything. That's the case here. So even explaining all of the foregoing logic doesn't really suffice to say that Ernesto is wrong in his defensive coding practices. That's something NI has to earn back for that user. So perhaps if the bug with the auto error handling gets fixed and nothing changes about the errors of the accessors for another couple versions, we can get to the point where Ernesto feels comfortable removing the unnecessary bits. But until then, he's right to continue his current practice, and I shouldn't have said otherwise. I apologize. 

  6. 12 hours ago, Ernesto Aneiros said:

    As we have already seen, a statement from R&D is not a strong guarantee.

    I also plan to connect both not because I like wasting my own programming time (as negligible as connecting an extra terminal might be) but because LV's behavior here is _inconsistent_ between versions and _silently_ changed. What guarantees do we have that it will not change again?

    Never mind. You're right. Sorry. 

  7. Quote

    The errors are the same at this point in time, but I don't think there's any guarantee that that will not change in the future. I plan to always connect both.

    Yes, there is a guarantee: both a statement from R&D and also just how much code we'd break if that ever changed. But if you want to continue connecting both, it's just your own programming time and run-time performance you're wasting, so go for it. 

    Quote

    The comment that the automatic error handling is satisfied if one of the two terminals is connected seems incorrect. Please see the image below. I have tested this both in 2015 and 2017.

    I'll file the bug report. Definitely worked when the feature was first introduced (thanks to TomOrr0W for checking back to 2009). *head bang*

    This has not been a good LabVIEW day. 

  8. Paul: Your response is exactly why I thought inheritance is a bad choice here. "D:Exit()" on a state is not a well-defined method because it's behavior depends upon context. Having "D:Exit()" that ONLY does the exit work of D and not the exit work of B or A means that the transition can call "D:Exit()" and then could also call "B:Exit()" if and only if the transition knew itself to be crossing that boundary. Or, better -- it would just call B:Exit() and let B know to call D:Exit(). It's all design time knowledge -- using reflection means that design time information is being computed at run time, which is both inefficient and error prone.

    I know that neither of the alternatives I just now suggested fits cleanly into your existing architecture. Your need for reflection is clear to me given your current design. And while I would consider your architecture as a use case if I were working on reflection, I would still push back on the architecture itself. To inherit, you need Identity, State, and Behavior. All three. If you don't have all three, you shouldn't be inheriting. You don't have Identity. State D is not a flavor of state B. It is a substate of B. Any time you miss one of Identity, State, or Behavior but choose inheritance anyway, somethings work, but other things will become significantly more complicated. And a need for reflection is a bright red sign. 

  9. 19 hours ago, PaulL said:

    This is the State Pattern, not my idea. (There is a link to my full presentation in this thread https://lavag.org/topic/17937-state-machine/#comment-107773.)

    I'm familiar with the State Pattern. I've just never seen the inner states implemented through inheritance of the outer states. I've always seen that as composition. Once I pulled it apart, it made sense. Let me see if I understand:

    • If the transition is from one inner state to another inner state, you call a method X.
    • If the transition is from one inner state to another state outside the outer state, you call a method Y ("StopMotion" in the example). Either that method is responsible for calling an abstract core functions to be implemented by the inner states ("OnInterruptProcessTriggers" in the example) OR (not in the presentation directly but seems to be alluded to) the inner states would override "StopMotion" to add the behavior they need for that transition and use Call Parent to make sure they get the common transition code. 

    Assuming I have that right, it all makes sense. What I'm not seeing is why any of the function invocations have to be decided at run time. It's all fixed function calls to match your state machine model. You never have to find the "common parent" for a given transition because every transition has its own method (that is only implemented starting at a particular level of your hierarchy). 

    Where does the dynamic come into play? 

  10. 37 minutes ago, PaulL said:

    The hierarchy can be determined at compile time and stored (not so robust)

    What does the inheritance hierarchy look like? Are you saying that there is a class D that *inherits* from class B? I've never seen a state chart implementation where there would be an inheritance relationship between the outer and inner states. That's typically a "has a" not an "is a" relationship. I tried to picture what state (i.e. private data fields) B could have that should be inherited by D... I couldn't come up with any use cases. And the methods are all methods on class State ("Enter", "Exit", "Loopback", etc), not things inherited from B. Please explain how this works. I'm intrigued, as it sounds like a novel approach to state chart implementation. 

  11. Quote

    From what I see they are not.

    Oh, yeah. I forgot about that. There's a whole writeup somewhere discussing why I did things the way I did for that library. It's been a while since I worked on it. Sorry for the wild goose chase.

    Quote

    (wonder why this information is not in the class flattened string?).

    Flattening the names of the complete ancestry into every flattened string would be an incredible bloat of the flattened size of data.

    Quote

    Disadvantage of that solution is a need to change inheritance.

    I do not believe this is a disadvantage. Serialization is special... if the parent is not serializable then the child is not serializable. Requiring inheritance from a base Serializable does not seem to me to be a bad requirement. Even in other languages where serialization is an interface, mostly they have to add special syntax checking to make sure that the interface is implemented by the eldest class or else it doesn't work. Serialization isn't functionality that can be injected on a descendant level. It's all or nothing to be meaningful because failure to preserve parent state means you aren't actually saving the state of the object. Thus the requirement to inherit from specific base seems absolutely reasonable to me... indeed, it is an advantage because it syntactically assures that the ancestors are included.

  12. @Zyga

    Here: https://forums.ni.com/t5/Actor-Framework-Documents/AQ-Character-Lineator-working-draft-version-of-serialization/ta-p/3512840

    It's my complete, working flatten-to-anything-unflatten-from-anything serialization library for classes [and any other lv data type]. I forget exactly how the names are extracted, but the functions are in there if you want to use them for your own serialization project. Also, feel free to use the library as it stands. 

  13. On 8/28/2018 at 8:09 AM, bbean said:

    Two

    BBean: How bad is the limitation? Just annoying or is it actually blocking work? And was the error message sufficient to explain the workaround?

    I've looked further at creating the mapping system -- it's a huge amount of effort with fairly high risk. I'm having a hard time convincing myself that the feature is worth implementing compared to other projects I have in the pipeline.

    On 8/28/2018 at 4:58 AM, Mads said:

    Stephen - did you see this video I made of the behavior of the Malleable VI when trying to call a *protected* VI? Looks kind of funny, or?

    As I said on ni.com, I investigated Mads' bug where malleable VI fails when calling protected scope subVI. I was unable to replicate the issue. Mads could not replicate it again either. So it is definitely a corner case bug. If anyone sees it, please share VIs that replicate.

    On 8/16/2018 at 1:36 AM, gb119 said:

    Having to use the accessor vi rather than a property node tripped me up - I can see how the compilation issues mean not accessing the private data directly, but not the difference between calling an accessor vi directly or inside the property node.....

    When you change a subVI, which VIs in memory have to recompile? Only those that call the subVI. How do we know those? Well, we have a network of links between VIs (and libraries and projects) that track all the dependencies, so I just traverse the links from the subVI to all of its callers. I don't have to recompile every VI in memory on the off-chance that it calls the modified subVI. Conversely, when you run a VI, which subVIs need to be locked so they can't be edited while you're running? Again, I can traverse the linker graph to lock those that are dependencies of the top-level VI.

    When you change the private data control, which VIs in memory have to change? Prior to malleable VIs, I didn't need any sort of tracking for which VIs accessed the data -- I just told every member VI to redo its compilation... fast and narrowly scoped. No link information required. And when you run a VI, does the private data control need to be locked? Only if a member of the class is invoked.

    But with malleables introduced, if they could talk to private data directly, the linker graph wouldn't reflect the dependency of the malleable instances on the main malleable VI. If you go through a subVI or subVI-masquerading-as-property-node, there is a link, so when the private data control changes, we change the subVI, and that causes the caller to recompile (if necessary... usually only necessary if you've inlined the subVI).

  14. I've been informed now that this can be achieved as long as the
    > VIM uses an accessor when operating on private data...

    That information is in the error message. Do I need to clarify the message? 

    (It seems a bit strange that the VIM is not allowed direct access to
    > private data, but it can still call a private method to effectively do the
    > same thing (so why not allow it to access the private data without the
    > accessor in the first place...)).

    There's a pretty crucial optimization that LV classes are built upon that when the private data changes, the only VIs that need to be evaluated for recompile are the members of the class. The dependencies between VIs are tracked (i.e. when one VI calls a subVI), but creating a similar web of dependencies on the individual fields was significant work that was unnecessary ... until the advent of malleable VIs. When I considered the work of adding such a matrix compared to the workaround of providing a private accessor VI, it just didn't seem worth it. So, I put the limitation in for private data access and waited to see how many people would object. One so far. :-) 

  15. On 6/27/2018 at 5:14 PM, GregSands said:

    So this gets a little more interesting with the output type of the DDS:

    ...

    In any case, here's the Default Element VIM (saved for 2012) for any who might use it.

    Default Element.vim

     

    This turned out to be surprisingly easy to fix. The fix will be included with LV 2018 SP1.

    The problem is that there are a very few nodes in LV that reach downstream to get their types when they think it is safe to do so as a way of giving better default types for terminals. But when the downstream terminal is something polymorphic, that has to be limited or disallowed. I never knew about that feature of LV (though I've unconsciously taken advantage of it many times, it turns out). I just needed to add a downstream malleable VI to the disallowed list so that the malleable is always driven by upstream instead of driving upstream.

    • Like 2
  16. The 2018 Americas CLA Summit will be September 12-14 (Wed to Fri). As we say every year: the volunteer organizers can plan the event, reserve the space at NI, and invite the CLAs, but without content from the community, the CLA Summit cannot happen. We need your input!

    Please click here to fill out the application to present.

    Deadline for submissions: May 31, 2018

    Presentation Options

    We are making a few changes to the overall 2018 format in response to community feedback, but the three types of presentations remain the same as for 2017. We hope we can accommodate the kind of presentation you are comfortable presenting!

    1. Large Audience, 50 minutes: You will present once to the entire conference, expected to be ~250 CLAs. These are good for lecture-style presentations with big graphics.
    2. Small Audience, 50 minutes: You will present at most twice on the same day (only once if we have enough submissions). You will be addressing 2 different small audiences of ~50 CLAs. These are good for demo-oriented presentations with more of a Q&A style.
    3. Large Audience, 7 minutes: You will present once to the entire conference as part of a 7x7 rapid-fire topic presentation. Have your presentation rehearsed exactly as the 7 minutes is a hard cutoff! We will have a 7x7 on each of Wednesday and Thursday, and we prefer that the presentations be on that day’s theme.

     

    Themes

    There will be two themes for the 2018 Americas CLA Summit, one on each of the two main days.

    Wednesday: Solutions to Complicated Programming Problems

    In this theme, we want to hear about solutions to the most difficult problems you have encountered while developing applications, specifically with the actual code design.  We are looking for topics that present the context of the problem and discuss the solution that you came up with.

    Some sample titles to inspire you:

    • “How we got data from point A to point B in record time”
    • “A common algorithm you might not recognize because we’ve optimized it so much”
    • “Even our plug-ins had to have plug-ins”
    • “The most insane customer requirement ever and the code that satisfied it”

    Thursday: Learning To Build Tools and Toolchains

    In this theme, we are looking for topics covering software tools you have written or workflows you have adopted to simplify your development process. Whereas past CLA Summits have asked for tools in a specific arena for people to use, here we want to focus on how tools get built. Specifically, we’d like you to discuss how those tools work on their insides. The focus on how to build tools is as important this year as what any particular tool does. Be prepared to explore design decisions and to discuss the pros and cons of the decisions you made when creating the tool. Ideally, we want either tools that are open for the community to help extend or instructions on how people can build their own to cover their own unique situations.

    Some sample titles to inspire you:

    • “Custom VI Analyzer tools”
    • “Get your CI Toolchain Up and Running in Under an Hour”
    • “The MEAN stack and LabVIEW”
    • “A tool for managing PPLs”

    Please click here to fill out the application to present.

     

    — The 2018 Organizers
    (Jon McBee, Stephen Loftus-Mercer, Jeremy Marquis)

     

  17. It's binary encoded data, so it can get big. The FlattenedPrivateDataCTL is literally the private data control -- the .ctl file that defines the data. It includes everything that a separate .ctl file would save. The connector panes are the complete signature of the methods, including types, layout, requirements, inplaceness, and constantness.

    • Like 2
×
×
  • Create New...

Important Information

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