Jump to content

JackDunaway

Members
  • Posts

    364
  • Joined

  • Last visited

  • Days Won

    40

Posts posted by JackDunaway

  1. Can you explain what you mean by "These concrete instances fundamentally represent functional programming...?"  And do you really mean *functional* programming, or do you mean procedural and/or imperative programming?

     

    Yes, functional; definitely not imperative/procedural, which is roughly on the same spectrum (yet in a less-desirable direction) as OO. But functional is orthogonal to this spectrum, and promotes at least one tenet that typically competes with imperative and object-oriented programming: minimizing mutable state, and ideally statelessness. An OO approach to the NotifyUser.lvclass example might suggest setting property SetMessage.vi and then invoking DisplayMessage.vi, in the meantime storing Message in the class private data. Functional Programming promotes statelessness, so we would strive to implement Display Message with a ConPane with the complete set of parameters necessary to perform the action. Not coincidentally, this style marries beautifully with event-driven programming.

     

    For this reason, I want child class functionality to implement and "override" (I use the term "override" loosely) with different ConPanes than the parent. And I'm clearly stating that this request does not jive with OO purism, so I completely agree with (yet reject as a argument against "Must Implement: :P ) all sentiments in this thread that "Must Implement" does not adhere to the interface as defined by the parent.

     

     

    I can't even predict all the reasons I might want to create a subclass, much less predict why others might want to create a subclass.

     

    Fair enough; but we can predict some.  ;)

     

     

     

     I rarely use Must Implement, and even more rarely use Must Call Parent.  I try to restrict their use to situations where not using them will break the behavior of class, not just because that's how I think the subclass should be implemented.

     

    Likewise, I rarely use these either. (yet, mainly because of the limitations described in this thread!! e.g., wanting unique ConPanes for child Implementations). Your second sentence above is perhaps a better verbalization of my sentiments; a subclass who Implements a parent, yet does not Implement a certain method that would be best marked as "Must Implement" (yet not Dynamic Dispatch) is effectively breaking the functionality of the class. The reason the class designer would flag "Must Implement" goes beyond vacuous expectations of what ought a child class to do; it's an indication that "something is broken with this inheritance unless this obligation is being fulfilled". We would probably agree that if the class designer uses this contract much beyond ensuring things don't "break", that the contract is probably being overused and/or misused.

     

    This crusade is for a desire to minimize mutable state. Reduce asynchronization between an object's cached state with the subject's physical state. Reduce cognitive overhead of understanding systems (i.e., reading code). Increase opportunities for parallelizability. These are my perceived benefits of functional programming over imperative programming, and why a healthy dose thrown is thrown in with the benefits of LVOOP.

     

     

    Setting aside for the moment your desire to use language constructs to impose your expectations on class users, you've already pinpointed the issue behind all of these problems.  Regrettably Labview doesn't allow classes in the same ancestoral line to have methods with identical names unless they are dynamic dispatch.**  If NI can fix that (and I really hope they do) I think it would relieve a lot of the issues you are describing.

     

    It won't necessarily relieve the issues described in this thread; but generally agreed that it will relieve other issues, and is a much welcome improvement.

     

     

     

    I'll go out on a limb here and claim this is a mistake.  Must Override and Must Call Parent are requirements that only have meaning in the context of overriding a method.  It makes no sense to flag a static dispatch method with Must Override, and it's equally nonsensical to flag a child method with Must Call Parent when there's no parent method to call.  My guess is if you find yourself wanting to enforce Must Override or Must Call Parent rules on non-dynamic dispatch methods, something in your design isn't right.

     

    100% agreed, and you're not on a limb. Consider my calling it a 'compromise' a friendly euphemism for 'mortal sin'

     

     

     

    Jack: After working through your thread, I think the answer you are looking for is what would be called template classes in C++ and generic classes in C#.

     

    This is a new, interesting discussion altogether, but not the solution. It breaks down simply when you want different numbers of parameters on the ConPane for child implementations. (Whereas, genericity describes unknown type for any one parameter) That being said, genericity might alleviate (even, significantly) some of the root problems here.

  2. It works fine for me... only returns things that are really problems. Inside the project, open one of the specified VIs... does it ask to be disconnected from the library? Open the library... does it show yellow triangled items?

     

    No -- again, I see *no* negative side effects, no yellow warnings, no linker/compiler errors... let's take this offline, and I can report back to this thread if we learn anything of interest.

  3. Something is wrong with your library if you're getting hundreds of hits with that operation from vi.lib... or something is broken with that function.

    This feature finds items that will be broken when they load into memory because the library claims them but they do not reciprocate the claim. The library somehow thinks all of those VIs are its members. Weird.

     

    So, there's definitely something wrong here. My sanity says 'thanks' for this info.

     

    Attached is a snippet that shows just the first few hundred 'issues' -- feel free to run it yourself on your own project; the values from my run are set as default data on the indicator. And again, 'issues' notwithstanding, nothing in the project is broken.

     

    post-17237-0-85660100-1358974141_thumb.p

  4. "Items incorrectly claimed by a library" is perhaps a bad description. A better term might be "Items that are claimed by the library that do not reciprocate the claim".

    These items are ones where the library has been saved to disk and records "the item at this path location is a member of me" but the items themselves (VIs or sublibraries) were saved not claiming to be part of the library --- they may claim to be part of no library or another library.

    This sort of thing generally happens when you move files around on disk instead of inside LV or when you rename the library but don't save the VIs in the library. It can take a while to untangle.

     

     

    Reviving a bit of an old thread... 

     

    So when I click on the root project item and invoke "Find Items Incorrectly Claimed by a Library", it returns a list of hundreds of VIs, nearly all of which are in vi.lib. But a few dozen were in my codebase, and so I fixed them; fair enough. (The trivial fix is to manually drag offending members out of the library and then back in; a bit tedious for a few dozen items, but it could be automated through VI Server)

     

    Just trying to learn more about this, so...

     

    What is the benefit of resolving this 'condition'? What are negative consequences of not resolving this non-reciprocation? I have yet to run across any concrete problems caused by this condition, other than an icky feeling. (Case in point: vi.lib ships with many library members who don't acknowledge their ownership, apparently without problems)

  5. I usually stick with the Pane Size events, I believe that those will fire as expected in the subPanel.

     

    Great tip! Hearty +1! In the past, I've brokered resize events from the parent into the children using the application's interprocess messaging -- using Pane resize events will simplify this :-)

  6. Jack, yeah, the object level makes it significantly different. I don't think it would solve your problem.

     

    I'm not necessarily looking for a resolution of a problem; rather just comparing notes to what seemed like a similar scoping construct -- mine was one of those ideas that has never graduated past a 30sec stream-of-consciousness dump onto the LV IdEx Google Task list :-)

     

    It would be interesting to hear more about the specific context in which you originally envisaged this feature.

  7. Has anyone ever felt the desire to declare fields of a class that are private to a single method of a class?

     

    Here's a direct copy-and-paste from a note I wrote a couple years ago on the "potential IdEx Candidates" list:

     

     

     Ability to set property of a wire to "locally scope" the wire. That way, it could not be run into SubVIs. Or, perhaps, some other method of disallowing developers to wire a wire into a SubVI (e.g., state data from a State Machine being passed into a SubVI en masse)

     

    The gist is to truly scope data to the BD of a single VI, discouraging abuse of exposing data across a SubVI (or even structure) boundary where it does not belong. Is this idea kinda like what you're proposing? Or an alternate solution to solve the same problem? (One obvious difference: this declaration would be held at the VI level, not the object level)

  8. What does Metro have to do with this? I know it's a joke, but I don't see the connection.

     

    Not really a joke -- some branches of design (Metro, notably) actually are headed toward flat and rectangular, like the current rasterization of LabVIEW -- didn't mean to sound flippant.  :oops:

     

    Maybe you'll find ways to accomplish your goals using the Icon API directly from <vi.lib>LabVIEW Icon API; or perhaps with the LV2012 Icon Editor source; hope this is helpful.

  9. Two years later -- I'm reporting back that .lvlib is absolutely better than .lvclass without the concept of an "object" or "statefulness".

     

    An important performance consideration -- previously unmentioned in this thread -- is that when a member of an .lvclass is statically linked to a caller, the entire .lvclass and its members and their static dependencies are loaded into memory. On the other hand, an .lvlib grants random access to its members without loading the entire library and dependencies.

     

    Typically, I'm not one to promote performance micro-optimization, but this consideration is one that can easily take seconds and affect end-user experience of your application.

     

    (And a few tags for the googles: Dependency management, static linkage, lazy-loading)

  10. Wait... It uses a limited palette? WTF? Why? There's no good reason for that on today's hardware! Where can I get a copy of this modified icon editor?

     

    The stock Icon Editor actually uses and stores icons as 24-bit color -- yet the icon preview on FP/BD, and also instances on a BD -- are rendered with a palette that very nearly resembles (or, is exactly) the 216-color web-safe palette, plus 10 each for a spectrum of R, G, B and greyscale to make 256 colors.

     

    In other news, 8-bit and minimalism (e.g., "Metro") is one branch of latest design trends -- we could turn the conversation positive and just call it ahead of its time  :)

  11. Yes I've seen this demo, and have played with the XControl too.  A few things I don't like about it (but have never mentioned to the author) is the fact that you don't have control over allowing the user to close a tab or not.  If I'm using this with subpanels, there is a use case where I load a non-reentrant VI into the subpanel and may not want the user to close it.  Also I think it would be nice to be able to have control over what happens when a window is closed.  Should it pop back in or close?  

     

    Me too!! But in the spirit of not hijacking this thread, perhaps let's continue discussion on the XTab thread to help both OP and Olivier  :lol:

  12. I care not for architectural astronautics

     

    Agreed, a Spolsky fan also, and keeping software engineering on the lithosphere.

     

    The override is used because of "re-use" and to avoid code replication which is not a pre-requisit for override which is generally used to modify the object. The override enables me to put operations that are identical in all the child classes  (error translation for example) into a single location.

     

     

    Yep; this shows the power of 'Must Call Parent', which also would exist for 'Must Implement' as it does today for 'Must Override'. This type of code re-use contract is not unique to Dynamic Dispatch, but equally important with Must Implement.

     

     

    The dynamic dispatch is still, however, required as the child (in the example, the protocol) is still determined at run-time. This is no different from the parent calling the "Read" from within a case-statement (where each case is a different protocol) and then carrying on to process the result of the call. However, with the case statement scenario I could indeed have different terminals for each protocol.

     

    Then I sit here scratching my head how the object is determined run-time, yet one concrete implementation requires a different ConPane than another. Again, I'll stand by the statement that if any methods in a Dynamic Dispatch hierarchy need separate ConPanes, Dynamic Dispatch was the wrong choice, and your comment on the Block Diagram "Not Used; Only to make ConPanes identical" seems like a red flag... it's the desire for the three current language benefits of overrides (defining the parent-child relationship, ability to require implementation, and ability to require calling parent for object construction and re-use), just without the requirement of the defined ConPane.  :wacko:

  13. I have actually come across this instance before where it was frustrating that I couldn't have different terminals for an override. It forced me to have "dummy" terminals which were only functional in certain overrides which (to my mind) was unnecessarily confusing and meant more documentation.

     

    .attachicon.gifUntitled.png

     

    Aha!

     

    This is a perfect example where Dynamic Dispatch 'appears' to be the correct solution, yet it's not. Any override with unused or incoherent inputs on its interface is better replaced by simple static methods in the concrete classes. The parent should not define the superset interface of potential child implementations, where concrete class callers "just should be aware" of which inputs they should be wiring (that makes for a weak API)

     

    Your example is a canonical example for 'Must Implement' -- the Static Concrete Implemented Method is a more appropriate construct than 'Must Override' with Dynamic Dispatch.

     

    Yet you, and me, and others make the compromise (or make the mistake) of sometimes using Dynamic Dispatch purely for the Must Override and Must Call Parent contract.

     

    And I'm *totally* not ragging on your code, Shaun -- rather, happy to see another respected developer show code and admit what we've created "felt wrong". I bet we're not the only ones, and I'm determined to hash out a resolution for this, whether a new ability to 'Must Implement', a design pattern to account for this, or just better personal coding practices.

     

    Finally, a few common instances where Dynamic Dispatch is often the incorrect choice where Must Implement 'feels right':

    • the initialize() function of concrete object types that requires unique sets of parameters to construct the object;
    • a Serializer, Logger, Messenger, or DisplayNotifier class who expects its children to serialize(), yet understands and allows for their need for strongly-typed unique inputs;
    • basically, *any* time you ever find yourself considering a variant or stringly-typed input or output to accomodate for unique interface requirements

  14. Haven't read the whole thread (i.e the replies) as yet so might be going off half-cocked (as per usual). But is this definition (Must implement) just another name for abstract?

     

    Reference

     

    I believe the 'abstract' concept from other languages typically defines the full function prototype, including parameters. Which makes 'abstract' more akin to Dynamic Dispatch than Must Implement. I'm suggesting Must Implement does not define the function parameters for subclasses.

     

    (But perhaps Must Implement does require a minimum set of parameters; the object input, for instance, would be required in order to invoke 'Call Parent Method' <headscratch>gotta chew on that one</headscratch>).

     

    (And a sincere virtual+1 to you for joining this thread without using the term LVPOOP :lol: Perhaps the term 'functional programming' piqued your interest  :D Just ribbing.)

  15. You're basically saying if you're going to have an "is a" relationship with me, you need to do something(). But an interface can't be provided so you can't provide the context in which something() will be called. No code that operates via the superclass interface can do anything with something() due to the lack of this interface. The code requires direct knowledge of the derivative class, which has completely defeated the purpose of defining something() at the superclass level.

     

    Aha.

     

    I understand. Had to read that many times, but I see we're probably coming from two different angles.  :lol:

     

    The spirit of what I'm suggesting emphasizes how concrete classes interface with calling code. It's decidedly functional-programming-esque, not OO-purist by any stretch of the imagination. You're defending the case for OO-purism, where unknown concrete interfaces (ConPanes) of 'Must Implement' methods would be clearly incompatible with inversion of control, where superclasses must know the interface, by definition.

     

    The usage of 'Must Implement' best jives with calling code that instantiate concrete, static classes. These concrete instances fundamentally represent functional programming, and incidentally enjoy the OO benefits of encapsulation/access scope/inheritance of abilities/and contractual requirements of subclassing (woot!). On the other hand, an OO-purist application might inject dependencies at runtime, where fundamentally the application is abstracted and transcended into a higher state of being.

     

    Both approaches are valid! Yet if inversion of control is not an application domain requirement, I choose concrete implementations. Why? Static analysis by the compiler is your friend. +1 for compile-time errors vs. runtime errors 1446 or 1448.

     

    That's all -- admittedly, the suggestion of 'Must Implement' is not OOP-y, and I'm still curious if any other languages address (either, have implemented, or have explicitly rejected) a notion such as 'Must Implement'.

     

    And to quote you, 'please understand I'm not trying to be hostile' -- just laying it out there, and learning to be a better programmer like the rest of us!  :lol:  :yes:

  16. I also don't quite understand the sentence: "Also tried using classes, but then the same problem exists, just with a new abstraction layer added!"  Can you elaborate on this a little?

     

    That's a reference to the LVOOP implementation of the Command Pattern in LabVIEW, and its portly codebase. As a codebase grows, two other things grow greater-than-linearly: cognitive overhead required to understand a program, and the liability of a codebase owner. (And length of tea time, waiting for your build. But we like tea time.)

     

    "Programs must be written for people to read, and only incidentally for machines to execute." --Abelson & Sussman, SICP, preface to the first edition

     

    Another quote (that even Google cannot produce right now) says something about object-oriented and functional programming being roughly orthogonal, and the sweet spot of productivity for your language du jour comes by acknowledging the syntax and constructs of your language. It's just an opinion, but Command Pattern and subclassing every message is a beautiful and pure concept, but too close to the OO extrema to be practical. Syntactically and logistically burdensome.

     

    [Crouching, waiting for tomatoes to be thrown]

    • Like 1
  17. I think the combination of non-DD and the "Must implement" will simply lead to massive code smell where programmers just implement the required VIs as empty husks and do the rest of the work in the rest of the child class.

     

    Sounds like you need to fire that second-rate subclass designer  :o Just joking of course -- the goal of this language feature is to help convey information to developers about the intent of subclass design -- to help you implement the correct things. Not make things hard.

     

    If you're attempting to subclass in a manner that far outside the original class designer's intent, it's perhaps time to consider composition rather than inheritance. That's your code smell.

     

    If I re-read your posts a few times I get the feeling you want to limit the types of messages a given actor can send and receive within the AF, is this correct?

     

    Nope!  :)

     

    GAHH. No. Overloading is not cool.

     

    Yeah, agreed. (And, AQ, what are your thoughts on Must Implement?)

     

    On the other hand -- on the subject of 'same' names -- I see no reason one could not mark multiple methods from one subclass as Implementing a Must Implement parent method -- with the requirement they have unique filenames and therefore function names. Why is this desirable? To have access to the Call Parent Method; and to establish relationships and intent through native language features.

     

    (This ties back to the same wish for overrides for Dynamic Dispatch, where a GUID property of the class is the basis for contract fulfillment of a 'Must' flag, rather than filenaming convention. Even writing this, I cringe thinking "Oh yeah, and development of this other GUID linkage feature gates the development of Implemented multiplicity..." Nevertheless...)

     

    To illustrate with the Display Message example, DisplayMessage.vi could be Implemented by DisplayMessage-Bool-YesNo.vi and DisplayMessage-Bool-YeaNay.vi

     

    post-17237-0-62322100-1358217053_thumb.p

     

    You see that and think, "Aha! Canonical use case for subclassing NotifyUser-Bool.lvclass with NotifyUser-Bool-YeaNay.lvclass and NotifyUser-Bool-YesNo.lvclass and then overriding DisplayMessage.vi with Dynamic Dispatch! Gotcha, suckaaaah!" But what if we wanted a different flag on the ConPane to for YeaNay to print "Yay" for some dialects and "Yea" for others? We're back to a case where Dynamic Dispatch is just the incorrect tool.

     

    Finally, these 'Must Implement' and related 'Require Implemented to invoke the Call Parent Method' features do not grant new abilities that cannot already exist by diligent convention. But I prefer compiler feedback to diligence or conventions  :thumbup1:

     

    (EDIT: removing double post)

  18. Hmm. Jack, please understand I'm not trying to be hostile, I just really don't understand how this could be used.

     

    No worries! I would never think that. The burden's on me to provide a good enough example to show the value  :) (tl;dr -- skip to the example below the horizontal rule)

     

    So if a superclass deems MethodX must be implemented, but it can't call this method because no interface has been defined, how is the VI useful to the superclass or any other code that interacts with the superclass interface?

     

    A superclass is unable to call an Implemented method, just as a superclass is unable to call a static dispatch methods of its descendants. You know, the error "You have connected a refnum of one type to a refnum of another type and both types are members of some class hierarchy, but there is neither a simple up cast nor type cast between the two classes." So, I think your question indicates you're still seeing Implemented methods like a Dynamic Dispatch override. There's no sense of run-time polymorphism. It's just a static method in the subclass whose existence is necessitated by its parent. The parent says, "If you're going to have an IS A relationship to me, you gotta define this method. Implement it however you want, I don't need access to it and I'm never going to invoke it, I just gotta ensure you're taking care of business."

     

    Something similar would be the ability to overload methods: being able to define a new VI with the same name but different connector pane. This however is mostly syntactic sugar as in languages that allow it as no real functionality is introduced that couldn't be achieved by naming each method differently as we do in LabVIEW. In effect overloading is really an edit-time convenience.

     

    In the original post, I debated on whether to call this new option 'Must Implement' or 'Must Overload' or 'Must Supercede'. Implement seemed like the most correct term, since it's not overloading, per se (the method is in a separate namespace, and is only available to the Implementing class and its descendants -- an overloaded method seems like the overloading functions would have the same namespace and access scope, so overload seems like the wrong word).

     

    Interesting, I take it you're not drinking the AF coolaide? The arguement you're making hasn't been my experience, and one of my favorite applications of the AF IS a complicated Subpanel architecture

     

    On the contrary -- AF has disrupted the way I look at systems and interprocess messaging. Holistically, it's a hammer that shouldn't be swung at every nail, but the principles it teaches supercede the framework implementation itself. (To Jon: and we haven't talked in a while, I've contacted you to see if I can get a demo of your UI implementation with AF!)

     

    I just really don't understand how this could be used.

     

    Maybe it's a weak argument, but if one sees the value in "Must Override", that same magnitude of value exists with "Must Implement". It's just the parent's ability to ensure a functionality exists in descendants; one happens to have run-time polymorphism and a defined interface, the other doesn't.

     


     

    Here's a simple example.

     

    Consider the class, NotifyUser.lvclass which only has one method, DisplayMessage.vi, whose purpose is to display a string to a user. Later down the road, you consider it worthwhile to display other types of things to users, like Bools and Numerics, so you decide to subclass NotifyUser.lvclass since it's already got all the business logic for displaying messages. The illustration below shows this:

     

    post-17237-0-02570900-1358099482_thumb.p

     

    Notice how the two implementations have separate ConPanes from the parent. A need for separate ConPanes is always an indication that Dynamic Dispatch is the incorrect design choice, and I used to try to solve this (incorrectly) by weakly typing the inputs as variants or strings -- a bad API design choice. Also tried using classes, but then the same problem exists, just with a new abstraction layer added! (This is one of the syntax/logistical burdens of the Actor Framework implementation, and more generally the LVOOP approach to the Command Pattern in LabVIEW) That's where Must Implement saves us -- the ability to establish a relationship between child and parent methods, without requiring them to have the same interface.

     

    Another thing to note above is that the two children are broken with the message "This VI attempts to override a static VI in an ancestor class." This is due to today's design limitation that subclasses cannot have the same method names as parent methods, except in the case of overrides. Further, note that in the middle diagram, use of the "Call Parent Method" is unrecognized. These two issues would be addressed by a "Must Implement" feature, shown below (note: this is not valid syntax with LabVIEW today, but through image manipulation we're able to demonstrate the proposed syntax)

     

    post-17237-0-10425100-1358099919.png

     

    Now, with "Must Implement", we have the ability to contractually require functionality in subclasses while maintaining the ability to extend parent class functionality, having acknowledged that Dynamic Dispatch is the incorrect tool when distinct function interfaces are desirable.

     

    One final note to further stress the power of this new contractual relationship: "Must Implement" methods could additionally require "Implementations must call Parent Implementation", à la Dynamic Dispatch.

  19. In labview, if I wanted to do this, I'd probably use something very similar to the Actor framework where the interface for all methods is itself a class (i.e. the message type)  It basically creates an additional abstraction layer. 

     

    This becomes syntactically burdensome and impractical. Dynamically-dispatched methods in this Command Pattern cannot readily accept/return unique parameters that are scoped locally to the caller (e.g., one method accepts a Boolean wire from the caller, while another accepts a Numeric wire). Additionally, this statefulness of the caller does not necessarily belong in the object just to circumvent this issue (now you have a LVOOP-style-clustersaurus).

     

    Case study: try creating two user interfaces requiring request-response communication with Actor Framework (e.g., any sufficiently advanced SubPanel architecture), then examine the sequence diagram (timing diagram) of communication.

     

     

     

    How would you ever wire up to the must implement method if you haven't defined the interface?

     

    You cannot wire what is not created :-) Creating an "Implemented" method is the exact same workflow as creating a Static Dispatch method; it's just that the LVClass is broken before its creation, and happy once created. Unlike Must Override, which defines a both the name and parameters of a function prototype, a Must Implement would only require a name and leave parameters (ConPane I/O) up to the child class.

     

    The parent class is saying "if you want to be like me, you have to do at least this; you can do it however you want, but you gotta do it."

     

    Finally, the superclass could itself Implement and still mark itself as Must Implement -- just like Must Override. The subclass creating the Implemented method has access to the "Call Parent Method" LVOOP ability, which would effectively drop a static method of the parent implementation, while still reserving the freedom of defining its own new interface.

  20. When subclassing, methods can be defined as Dynamic Dispatch, allowing implementations to override the parent. These implementations must have the same ConPane interface as the parent.

     

    Further, the parent can (awesomely) declare "Must Override" per Dynamic Dispatch method, a contractual requirement of the subclass to implement the method. We're cool so far -- this is just a definition of how things work.

     

    Here's where things get tricky: it's *so nice* to have that "Must Override" flag, yet you wish that implementations had a different ConPane than the parent method. Clearly, Dynamic Dispatch would be the incorrect choice, yet it hurts to give up "Must Override".

     

    So what do you think: could there exist a concept of "Must Implement"? It's like "Must Override", yet does not require the subclasses implementation to adhere to a ConPane interface.

     

    These Implemented methods act like a static method of the the class, only callable by the class and its descendants (this is not like Dynamic Dispatch, since a broken wire would result from wiring a Parent object to an Implemented method). The parent simply requires implementation -- the existence of a method -- without defining the interface.

     

    Do other languages have this concept? Are there design patterns that address this need? Or is this desire for "Must Implement" indicative of poor OO design choices?

  21. National Instruments has published the canonical document on closing references in LabVIEW. 

     

    And here's the guerrilla guide:

    1. Take a good stab like a jolly good sport at closing all your references
    2. Every blue moon when you run into a bug caused by improperly closed references, run Desktop Execution Trace Toolkit and take 5minutes to fix the yellow rows. Prosper.

    :yes:

     

    Now the *tricky* part comes with, not closing your references -- but keeping references open -- by understanding lifetime w.r.t. dynamic processes. I'm still refining my understanding and best practices to deal with this limitation.

    • Like 1
  22. Ran across a new programming language today - vigil from https://github.com/munificent/vigil ---- and you thought *LabVIEW* sometimes leaned too-restrictive in favor of being beginner-friendly.  :lol:
     
    From the vigil readme:
     

    Syntax and semantics
    Vigil is very similar to Python with the minor proviso that you must provide a main() function which will be automatically called for you.


    The implore statement to beseech your needs
    Often, a function will require that parameters have certain desireable properties. A function in Vigil can state what it requires by using implore:


    The swear statement to state what you provide in return
    If a good caller meets its obligations, the onus is thus on you to fulfill your end of the bargain. You can state the oaths that you promise to uphold using swear:
     
    Runtime vigilance
    This is where Vigil sets itself apart from weaker languages that lack the courage of their convictions. When a Vigil program is executed, Vigil itself will monitor all oaths (implorations and swears) that have been made. If an oath is broken, the offending function (the caller in the case of implore and the callee in the case of swear) will be duly punished.

    FAQ

    Is this serious?
    Eternal moral vigilance is no laughing matter.

     

    I am now seriously considering using the phrase "The ever vigilant watchers of your code have found malfeasance in: %s" for of my custom error call chains in LabVIEW.

    • Like 2
×
×
  • Create New...

Important Information

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