Jump to content

styrum

Members
  • Content Count

    29
  • Joined

  • Last visited

Posts posted by styrum


  1. 7 hours ago, jacobson said:

    I would say here you are just describing what an Actor does and nothing specific to OOP. An Actor can be an object but doesn't have to be from my experience. I personally think that this use of inheritance can be the most difficult to actually understand/maintain as well. If you've ever used an NI's Actor Framework where the inheritance reaches depths of 5+, trying to understand what the Actor does can be quite difficult (though someone might claim this is because they violated SRP).

    Perhaps I'm missing some historical context though and should read some older papers.

    Exactly! To implement an actor in LabVIEW one doesn't need LVOOP! Quite a few "asynchronously communicating modules" producer-consumer design patterns, developed by different people independently from each other including my LabHSM and EDQSM show that very clearly. After all, LVOOP didn't even exist when mine were developed. One can get away with just a cluster in a shift register to access any the data from any action case, but, OK, lets instead make an instance of a "regular" (LVOOP) class and make each action case just call a corresponding method of that class. It will look a little cleaner. The main point of creating an actor is to make an object more than just a bunch of data and methods, to give it a "process", "life", to encapsulate its state and enable it to exchange messages with other objects while having that own "life", i.e. the original Alan Kay's idea about what an(y) object is(should be). If your objects are like that (actors), and you build your application with (out of) them instead of the "regular" (data plus methods) objects, then you don't need all those complex "Gang of Four" design patterns which you indeed better use if you stick with "regular" objects.

    IMHO the main harm from "THE" Actor Framework is that it scares LabVIEW developers away from the actor model.


  2. I think it is important what exactly we call "OO code". If objects are not simply "dead" combinations of data and methods, but rather have their own "life"/"process", exchange messages with the user, "environment", and other objects the way actors do, react to events, I am all for such "OO code". The "regular/"passive"/"C++/Java/C# style" objects indeed have a very limited use and I agree that the attempts to build large applications using only them by constructing and utilizing complicated inheritance hierarchies and design patterns can lead to a disaster.


  3. 😂He knew what was coming:

    " I expect some sort of reaction from the defenders of OOP. They will say that this article is full of inaccuracies. Some might even start calling names. They might even call me a “junior” developer with no real-world OOP experience. Some might say that my assumptions are erroneous, and examples are useless. Whatever. "

    I think we all still can benefit from a more substantive discussion of his particular points rather than from accusations of "not understanding", let alone "calling names" and insults. 

    A "straw man" demagogic trick is no good either. The author opposes not OOP in general or as coined in by Alan Kay, but rather the C++/Java "kind" of OOP, especially inheritance hierarchies and "promiscuous sharing" of state. Neither he advocates "unstructured coding". And the C++/Java/C# style of OOP is not and never has been the only (let alone "best") alternative to "unstructured coding". Actor model is circa 1973. Smalltalk is even older.

    Statefulness, messaging and concurrent code organization have everything to do with OOP if/when they need to be present in the same program in which you use OOP. Just because you really have to figure out how to implement them in your OOP code then. And, very softly speaking, they are not easily implementable with "regular"/"passive" objects consisting of only data and methods that need to be called from "outside" of the objects themselves.

     


  4. Some food for thought:

    https://medium.com/better-programming/object-oriented-programming-the-trillion-dollar-disaster-92a4b666c7c7

    Note that LVOOP is indeed the "C++, Java and C# variety of OOP" too, and is taught the same way, complete with "cats and dogs", all the same "Gang of Four" design patterns, S.O.L.I.D (https://scotch.io/bar-talk/s-o-l-i-d-the-first-five-principles-of-object-oriented-design), etc.

    " The bitter truth is that OOP fails at the only task it was intended to address. It looks good on paper — we have clean hierarchies of animals, dogs, humans, etc. However, it falls flat once the complexity of the application starts increasing. Instead of reducing complexity, it encourages promiscuous sharing of mutable state and introduces additional complexity with its numerous design patterns. OOP makes common development practices, like refactoring and testing, needlessly hard."

    I don't agree with everything he says, in particular with a definition of state. A variable is a state variable in a reactive (the vast majority of systems/applications and their components built with LabVIEW are indeed reactive and, hence, best modeled as such https://www.reactivemanifesto.org/) module/system/object in my opinion only if the reaction to some event/message (transition, actions that are run in response to the event, and/or target state) can be different depending on the value of that variable. And each object has its own state. The states of all the objects in the program combined constitute the state of the entire program itself, of course. But the very purpose of breaking a program into objects with their own ("isolated") states is to not have to deal with that combined state. The state of each object can and should be "mutable" in a sense, because real life objects indeed change their state with time and that indeed can have an effect not only on themselves but on their interaction with others. It should not be shared explicitly with other objects though, of course. I totally agree with him on that.

    Personally, I came to developing my LabVIEW applications as collections of asynchronous modules/active objects/actors which are backed by (hierarchical if needed) state machines  and communicate with each other only via queued messages long before LVOOP was created, let alone "THE Actor Framework", DQMH, JKI's "State Machine Objects", etc. showed up. Search for "LabHSM" and "EDQSM", they are both circa 2004-2006. Those two templates/toolkits/design/patterns/frameworks of mine, just like some other similar "asynchronously communicating modules" frameworks, have no explicit sharing of state and are closer to the Alan Kay's/Smalltalk idea of objects, where messaging between objects is "The big idea" and where the state of the receiver object (and, hence, the actual code/action/method that will be run as the reaction to a particular message from the sender) is of no business of the sender (now recall Do method in AF's message class and what it takes to decouple actors exchanging such messages)! "Active" objects and actors are not just data and methods, which need to be called externally, by some other methods of some other objects and ultimately by the "God" main loop (well, technically, for active objects as opposed to actors, it is still their methods that are called but those "method calls" are actually just message sending to its process). The main idea is that in contrast to the "regular" OOP, each of "active" objects (actors, modules) has its own "life", in which it reacts to various events, both internal (resulting from its own actions) and external (messages it receives from environment/other objects). It can and often does react to the same event differently, depending on its current state. The reaction consists of running some other actions (which may include sending messages to other objects) and changing its state (transitions). Ideally, it is a true parallelism, not just concurrency, i.e. while communicating with others (within the same physical machine or over the network), it runs in its own thread, process, container, virtual machine or even its own CPU core or an entire real physical machine, because each such object is a "microservice". It is like a complete computer in a sense, just like Alan Kay imagined it.

     I counted at least three more similar idea "actor frameworks" presented at the latest NI Week and GDevCon. Some of them even use LVOOP :-)

    Maybe it is time for many other LabVIEW developers to look at the LVOOP and "regular", "passive", single loop/thread (C++, Java, C# style) OOP more critically  too.

    Some more on the topic:

    https://medium.com/@richardeng/the-object-oriented-schism-9dedbbc3496b

     


  5. 9 hours ago, crossrulz said:

    There also appears to be A LOT of interaction between things.  If I disable the Value Property Node, the User Event gets into the same realm as the Notifier and Queue.  Removing the channels makes it even more the similar.  Maybe the Queue Status in every single VI is doing something?

    Yes, checking the watchdog queue takes a lot of time (if not most of) in each sender iteration. Please check out a "sequential version" in the latest posts or try putting a Disable structure around those Preview Queue Element nodes in the sender VIs (you will have to stop everything with the stop button on the toolbar of the Main then).


  6. Ok, OK, my bad, I left Debugging enabled. This is not a commercial app. This is is just some "food for thought", and something to play with, which you would otherwise not have the time to put together yourself. But now you can find some time (much less) to play with it. The goal was to get people to play with it, find flaws, "unfairness", etc. So I am glad that happened so quickly. Here is a version that has debugging disabled plus a "sequential" flavor of the whole thing.

    Some disclaimers right away:

    1. Yes, I deliberately do not count the iterations completed by sender loops but not completed by the corresponding receivers by the time the senders are done, because I do want to count only fully completed "transactions" in evaluating "performance"

    2. No, I don't say that lossy and non-lossy methods are comparable "1 to 1" in general context. But for the declared purpose of this particular experiment, updating an indicator in a UI VI, where the user is interested only in the latest value, it is fair to put them "together".

    Fastest update of indicator from subVI (3).zip


  7. 1 hour ago, jacobson said:

    Would you be able to summarize your findings in a table?

    I'm also interested in what frameworks/methods you were thinking of.

    Well, the very point of putting together this code is for people to see the numbers for themselves and that I didn't "cheat" on any of the tested methods to make some look better than others. Their significantly different performance numbers are real.

    In summary, the main findings are:

    1. (Widely known) Passing a control reference to a subVI or a VI running in parallel to the VI where the control(indicator) is located with the purpose of using that reference to update that control/indicator is the worst you can do.

    2. (Not so well known) Using "user events" in event structures for the same purpose mentioned and moreover, for implementing asynchronous communications in messaging architectures between "modules", "actors", parallel loops, etc. instead of regular queues and notifiers and now channels is (softly speaking) not a very good idea either from the performance point of view.

    3. Even the fastest "channels" are not better than the "good old" notifiers and queues. At least channels give more features and allow to do things impossible before. Which hardly can be said about user events.

    DQMH is one of the frameworks which rely heavily on such use of event structures one can recall right away. There are others, I bet. 


  8. Yes, I know, you wanted to do this some day too. So I did it for you. Just run (and then stop) the Main VI from the attached set (Saved in LabVIEW 2016 32-bit). I suspect (and hopeSmiley Tongue) the numbers will be quite a surprise and even a shock, especially for the fans of one particular method and some very aggressively promoted frameworks which use that method.

    Fastest update of indicator from subVI.zip

    • Thanks 1

  9. OK. So OCD is "obcessive compulsive disorder" I figured. Sorry, sickos patients, my native language is not English, but I still know what past participle is and even, for example, when to use past perfect tense in English (How many Americans do?).😋 "Cast Operator: () (programming) A type cast provides a method for explicit conversion of the type of an object in a specific situation. v. cast, casted" (https://english.stackexchange.com/questions/94565/can-casted-be-the-past-tense-of-cast)

     

     


  10. Thank you, Darin! That's exactly what I needed!

    By the way, what does OCD stand for in this context?

    BTW2: After calling Change to Constant the constant appears instead of the terminal exactly at the same place the terminal used to be, just as if I right-clicked on the terminal and selected Change To Constant. Well, at least in LabVIEW 2016.


  11. I want to use a Call By Reference or a Start Asynchronous Call node in my TEMPLATE code. Which means I MUST have a type specifier constant (or control) wired to the Open VI Reference. In my CONCRETE code created based on the template code using VI scripting I need to replace the type specifier, or rather the VI which that type specifier extracts the connector pane from, so that the Call By Reference (or Start Asynchronous Call) node can use a new connector pane within themselves instead of the one it has in the template code. Normally (manually) we just drag and drop a VI with a desired connector pane onto type specifier constant or control. But how can we do that (tell it which VI to use) programmatically?


  12. On 11/29/2018 at 1:07 PM, MikaelH said:

    You won't believe what I had to do to get it working ;-), coding VIs that runs in the project provider application instance is not always easy.
    A VI that works fine when you run it normally, could still crash/freeze LV when it's running under the project provider application.
    I hope it will be easier in NXG.

    So, can you make a tutorial (provide links to info/examples) on specifically that topic: How to make your own project provider, how to add your own items/code to the popup menu on the items in the project editor tree, including your own New..., the same way way Open GDS and AF do? Is this the best place to start? https://forums.ni.com/t5/LabVIEW-Project-Providers/gp-p/bymqyodmkc?profile.language=en

    What specific troubles did you run into that are not covered there?


  13. In his "Don’t Wait for LabVIEW R&D…Implement Your Own LabVIEW Features!" presentation Darren Nattinger advised to not mess with project providers. So, he didn't give any links to anything on this subject. How did you figure out how to do it? Please provide links/code on how to make your own project provider. Is this the best place to start on this topic?

    https://forums.ni.com/t5/LabVIEW-Project-Providers/gp-p/bymqyodmkc?profile.language=en

    Any  advice/help/examples you can offer from your own experience making your own project provider?

    image.png

×
×
  • Create New...

Important Information

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