drjdpowell Posted November 24, 2014 Report Posted November 24, 2014 Something I did not appreciate till today: If I have an LVLIB library in which I use one of its VIs, then any LVCLASS class referred to by ANY of the LVLIB’s members will be loaded into memory (along with all their dependancies). In addition, the fact that all library members show up under “dependanciesâ€, even if only a few are actual used, makes it difficult to get useful information about real dependancies. So, should I ditch the use of LVLIBs altogether as a hopelessly-flawed tool? — James Added later: Must be getting old, as I forgot that I already knew this. But the question remains of what to do about it. Quote
ak_nz Posted November 24, 2014 Report Posted November 24, 2014 At work we favor packed project libraries for production deployment (VIPM packages for development deployment) so lvlibs are unavoidable for us. But we do run into the "load the earth" scenario too. The best compromise we have found is to break down the component into smaller pieces. Quote
hooovahh Posted November 24, 2014 Report Posted November 24, 2014 Yeah this "feature" kinda sucks at time. And I'm a little disappointed that no other posts have been tagged with "things about labview that suck" but whatever. If it makes you feel any better, in the build environment generally these unused dependencies are removed. In the build specifications under Advanced there is a checkbox for removing unused items. Then at least they won't exist in your EXE, taking precious loading time. As for the development environment, yeah modulating code helps. But doing so usually means more VIs in general, which means more dependencies on disk. I don't find it that bothersome, but if you have 100s of libraries and classes I would be pulling my hair out trying to find a better solution. Quote
ShaunR Posted November 25, 2014 Report Posted November 25, 2014 (edited) Unless VIPM is involved, I Use LLBs instead. Edited November 25, 2014 by ShaunR 1 Quote
hooovahh Posted November 25, 2014 Report Posted November 25, 2014 Unless VIPM is involved, I Use LLBs instead. Not trying to change the subject, but I avoid LLBs at all costs. Every time I find one the first thing I do is extract the VIs from it. I feel that way because it seems like a zip or an archive, where to use it with the normal tools, I need to extract it anyway. I also know there were odd bugs a while ago where the LLB would get corrupted and ruin all the VIs in it. I know that is petty especially since it probably has been fixed long ago, but it still lingers as a thing to avoid in my mind. 1 Quote
drjdpowell Posted November 25, 2014 Author Report Posted November 25, 2014 If it makes you feel any better, in the build environment generally these unused dependencies are removed. True, but how do I identify real dependancies from all the fake ones? Unless VIPM is involved, I Use LLBs instead. LLBs don’t seem to be equivalent (though I never really used them). No namespacing, no Private scope. Quote
JKSH Posted November 25, 2014 Report Posted November 25, 2014 LLBs don’t seem to be equivalent (though I never really used them). No namespacing, no Private scope. No source control for individual VIs either. Quote
ShaunR Posted November 25, 2014 Report Posted November 25, 2014 (edited) Not trying to change the subject, but I avoid LLBs at all costs. Every time I find one the first thing I do is extract the VIs from it. I feel that way because it seems like a zip or an archive, where to use it with the normal tools, I need to extract it anyway. I also know there were odd bugs a while ago where the LLB would get corrupted and ruin all the VIs in it. I know that is petty especially since it probably has been fixed long ago, but it still lingers as a thing to avoid in my mind. They fell out of favour because they hide VIs from source control rather than any bugs or funny behviours. However, VIPM can pack directories into LLBs so it's not that much of an issue anymore for most people (can keep directories for development if its an issue). Your animosity towards them is unfounded Edited November 25, 2014 by ShaunR Quote
ShaunR Posted November 25, 2014 Report Posted November 25, 2014 (edited) True, but how do I identify real dependancies from all the fake ones? LLBs don’t seem to be equivalent (though I never really used them). No namespacing, no Private scope. Well. If you abandon LVLibs, you will only have a directory of VIs which are very easy to cross link and not as easy to distribute or organise as well as no namespacing or private scope. If you want scope, put them in a class. For dynamic loading plugin distros, LLBs are great because they are monolithic containers that don't load everything into memory unless linked or loaded explicity . For identical to LVLib without the [arbitrary] bits you don't want-probably asking too much. Edited November 25, 2014 by ShaunR Quote
smithd Posted November 25, 2014 Report Posted November 25, 2014 Something I did not appreciate till today: If I have an LVLIB library in which I use one of its VIs, then any LVCLASS class referred to by ANY of the LVLIB’s members will be loaded into memory (along with all their dependancies). In addition, the fact that all library members show up under “dependanciesâ€, even if only a few are actual used, makes it difficult to get useful information about real dependancies. So, should I ditch the use of LVLIBs altogether as a hopelessly-flawed tool? — James Added later: Must be getting old, as I forgot that I already knew this. But the question remains of what to do about it. I'd say your lvlibs are probably too big. I tend to consider them to be a single API, not a library of many APIs. This matches well for the features of the lvlib. For example, I can add a icon overlay as part of the lvlib file. If I have too many things I can't make a single good icon. Everything in the lvlib should be something you want to be loaded atomically, in my opinion. I'm not sure what I would do in situations where the stuff in the lvlib is not an API I want to use. All that having been said, I've never really used the dependencies for anything except to get to parent classes and the like, so I'm not sure what sort of filtering you want to do on that information. But I would also say that keeping dependencies in lvlibs makes your dependencies organized -- you don't have 1000 stray files from VI lib, you have 5 classes and 5 lvlibs. In fact, I have the reverse problem you have. Since labview counts things in lvlibs as dependencies but doesn't necessarily load them into memory, things like find and replace or "show error window" don't actually work on them unless you manually open the front panel of every VI. Quote
drjdpowell Posted November 25, 2014 Author Report Posted November 25, 2014 Everything in the lvlib should be something you want to be loaded atomically, in my opinion. Is that wise? What if your API optionally interacts with some other API, and you have optional methods to support easy interoperation. It’s possible that a particular programmer my want to use one or the other APIs by themselves. Where do the optional VIs that depend on both go? An example might be: I have a message-passing API, and a TCP API, and I want to pass messages by TCP sometimes, without tying these two APIs forever together? And without having the extra burden of stewarding LabVIEW to do the obvious: don’t load it it it isn’t used. Quote
smithd Posted November 25, 2014 Report Posted November 25, 2014 Is that wise? What if your API optionally interacts with some other API, and you have optional methods to support easy interoperation. It’s possible that a particular programmer my want to use one or the other APIs by themselves. Where do the optional VIs that depend on both go? An example might be: I have a message-passing API, and a TCP API, and I want to pass messages by TCP sometimes, without tying these two APIs forever together? And without having the extra burden of stewarding LabVIEW to do the obvious: don’t load it it it isn’t used. Fair example. I tend to end up making simple interface classes for this situation but I know they aren't for everyone. Ideally I would have 3 lvlibs. A would be the messaging component, B would be the tcp component, C would just contain the set of functions which tie them together. I'm doing something similar with a file loader right now. I want a generic hierarchy of essentially key value pairs so that the lowest level component can be used everywhere. In the actual application I'm trying to write I have a file loader which loads my particular hierarchy which includes a system configuration object that contains N process objects which contain M plugin objects. So now that I've gotten the two libraries where I wan them, I'm writing a 3rd library which converts between the very generic hierarchy and the specific hierarchy, as well as allowing for some useful manipulations of the data set (lets say I only want to load process #4 and its plugins, but not the rest of the system). Edit: Its worth mentioning that while this is something I am definitely doing, I'd probably simplify it if I were writing from scratch -- I'm trying to refactor months of work so it can be used on a few different projects, which is why having these weird dependency links is currently desirable. Downsides to this are that it can't always work (but usually works enough for me to not worry about using lvlibs) and it does lead to occasional instances of bloat and situations where I have to convert between the types used by the different libraries, but it seems to work well enough for my purposes. 1 Quote
ak_nz Posted November 25, 2014 Report Posted November 25, 2014 Fair example. I tend to end up making simple interface classes for this situation but I know they aren't for everyone. Ideally I would have 3 lvlibs. A would be the messaging component, B would be the tcp component, C would just contain the set of functions which tie them together. I'm doing something similar with a file loader right now. I want a generic hierarchy of essentially key value pairs so that the lowest level component can be used everywhere. In the actual application I'm trying to write I have a file loader which loads my particular hierarchy which includes a system configuration object that contains N process objects which contain M plugin objects. So now that I've gotten the two libraries where I wan them, I'm writing a 3rd library which converts between the very generic hierarchy and the specific hierarchy, as well as allowing for some useful manipulations of the data set (lets say I only want to load process #4 and its plugins, but not the rest of the system). Edit: Its worth mentioning that while this is something I am definitely doing, I'd probably simplify it if I were writing from scratch -- I'm trying to refactor months of work so it can be used on a few different projects, which is why having these weird dependency links is currently desirable. Downsides to this are that it can't always work (but usually works enough for me to not worry about using lvlibs) and it does lead to occasional instances of bloat and situations where I have to convert between the types used by the different libraries, but it seems to work well enough for my purposes. A comment on smithd's description of "package management" with lvlibs - this type of management is common in our other Java and .NET applications for packaging dependencies. Discussions around how to manage packages in order to reduce dependencies / coupling between dependencies has been a common topic of discussion in the development world (outside of LabVIEW) for many years now. LabVIEW has it's own take on the same concepts. We typically try and use the "stairway" pattern for dealing with dependencies but that relies heavily on LabVIEW "interfaces/abstract" classes. It works most of the time; on occasion we have the same sort of bloat but that typically occurs when we have multiple copies of basically the same dependency loaded from different packages. 1 Quote
JackDunaway Posted November 27, 2014 Report Posted November 27, 2014 So, should I ditch the use of LVLIBs altogether as a hopelessly-flawed tool? I did. (That is, after years and N00's hours investigating LVLIBs in the context of namespacing/distribution/building/linking/encapsulation/scoping/reuse/load time/dependency management and so forth. James, I am not surprised if you independently draw the same conclusion, and I'm interested to hear if you conclude otherwise.) 2 Quote
ak_nz Posted November 27, 2014 Report Posted November 27, 2014 I did. (That is, after years and N00's hours investigating LVLIBs in the context of namespacing/distribution/building/linking/encapsulation/scoping/reuse/load time/dependency management and so forth. James, I am not surprised if you independently draw the same conclusion, and I'm interested to hear if you conclude otherwise.) Do you favor LLBs as the alternative? I'd be interested in hearing more of how you manage the same use cases. Quote
Neil Pate Posted November 27, 2014 Report Posted November 27, 2014 Massive no from me on LLBs. I do not need to distribute my code like that, so really have no purpose for them. As others have pointed out, no namespacing, no access scope makes these a stale technology (for my situation at least) in LabVIEW. I still do use libraries though (and classes of course, which are also libraries), even with all the pain associated with the loading the entire contents etc. It troubles me too much me to have to manually namespace every VI, so I am not sure I will move away from libraries or some form of them any time soon. Quote
Popular Post JackDunaway Posted November 28, 2014 Popular Post Report Posted November 28, 2014 (edited) Do you favor LLBs as the alternative? LLBs and LVLibs solve different problems (and create different problems), and are not interchangeable or really related beyond sharing the word "library" in their acronyms. Here are some characteristics and comparisons of the two: LLB provides physical packaging containment of members, and does not address namespacing (nor scoping). LVLIB provides namespace containment of members (and also scoping), and does not address physical packaging. Both LLB and LVLIB impose static linkages that can be incidental and undesirable. These negatively affect load times (IDE and run-time), build times, and compile times. Anecdotally, it's greater than O(n) time complexity, especially when circular linkages exist between multiple such hierarchies, and most especially if the library hierarchy is nested (e.g., LVCLASS within an LVLIB, or nested LVLIBs) An LVLIB can be built into an LVLIBP. An LVLIBP is different from an LLB in that an LLB packs writeable, cross-platform* VIs capable of mutating to future LabVIEW versions, while an LVLIBP is a read-only, platform- and version-specific byte code distributable (which may contain the block diagram for debugging, except still remaining platform- and version-specific). An LLB may be used to pack libraries/plugins for deployment as application plugins, or as reusable libraries in development. An LVLIBP effectively is only used for the former. Neither LVLIBP nor LLB can pack non-LabVIEW-source filetypes as resources. Be mindful to account for both renaming/name-mangling resources, and also changes in relative path. LVLIBs (and LVLIBPs) render nicely in the LVProj tree, while LLB members appear indistinguishable from POVIs (plain ol' VIs). LLBs cannot pack two VIs of the same filename. This prevents packaging multiple LVCLASS hierarchies that use dynamic dispatch methods. This represents a few LabVIEW design limitations: 1) LLB's lack of an internal directory hierarchy for organization and packing of two filenames, and 2) LVCLASS using OS filename as the only unique identifier for method identification in a class (filename represents a good default value, but we need one more degree of indirection as a field within the LVClass XML; it's another discussion why this is so highly desirable to decouple source from OS convention). For actively-developed libraries, LLBs are bad because they exist a monolithic binary file. LVLIBs are bad because there exists no diffing or merging capabilities (this also applies to LVPROJ, LVCLASS, XCTL, XNODE filetypes. This is especially insidious, because popular DVCS clients autodetect the file format as XML and think "Aw yeah dude, I got this!" MERGE FAIL. Corrupted source. Be sure to turn off this autodetection for these filetypes.) LVLIBs can apply icon overlays to members. LVLIBs may be carefully designed to include strategic static linkages, including non-LabVIEW source files. This is one strategy to avoid managing the "Always Include" section of AppBuilder for distributables, especially as a convenience for end-user-developers of re-use libraries. But this fails by default because of the setting "Remove unused members of project libraries". Unchecking that often causes failure to build for non-trivial-sized applications linking to gargantuan LVLIBs shipping in vi.lib and as add-ons. So, the strategy may or may not work (it's coupled to whether or not you're keenly aware of and properly managing all application static dependencies) The reason I want to like LLBs is their ability to provide packaging constructs that provide higher performance on actual hardware. It's faster to load 1 file of size 100 units than 100 files of size 1 unit. It's also a more convenient distribution format -- a single file. (Also, I can't think of another language that effectively enforces a 1:1 relationship between method and physical file. LabVIEW requires substantially more clerical work to develop and refactor, for this reason) The reason I want to like LVLIBs is to enable namespacing and scoping beyond the LVCLASS level. Though, this namespacing always comes with the cost of static linking, which is perhaps the #1 problem for codebases of non-trivial size (do you see busy cursors while editing and wiring? long build times? load times? type prop errors? corruptions from application refactoring? heartache and heartburn generally?) Also, LVLIBP is neat in practice, but so narrowly scoped to specific deployment scenarios where it's acceptable to target version- and platform-specfic targets (version-specificity is definitely the bigger problem. every 12mo, we are afforded the opportunity to choose between obsolecense/migration/revalidation or just-plain-outdatedness). And without arbitrary namespace composition (namespace B and namespace C may both declare using namespace A; with namespace A unaware and none-the-wiser), it's not necessarily a compelling feature to begin with. (Corollary: an LVCLASS's ability to namespace and scope its members is desirable and good; but it becomes less necessary and more-likely-incorrect to continue namespacing and scoping at higher abstraction levels without namespace composition) Do LVLIBs Scale? Using LVLIBs in source on an actively-developed project raises barriers to both team scale and application scale. The cost of not using them is loss of scoping, which is avoided through communication and convention, and easily-detected if any actual problem were to exist. Another cost is loss of namespace, easily avoided through filenaming conventions (which is incidentally an industry standard on the web; prefixing library APIs with library-specific prefixes to avoid collision). Said another way, ROI diminishes and reverses to negative at scale, and opportunity cost has simple workarounds. I choose the opportunity cost. But... LVLIBPs! Another apparent opportunity cost of avoiding LVLIB in source is the inability to have LVLIBP as a distributable. Though, if you treat build/distribution as a second toolchain from the dev toolchain, the dev source can remain unencumbered by LVLIB, which is only added as part of the build process. I have mixed feelings on ROI here, but if LVLIBP makes sense for you, consider this strategy to make your dev experience noticeably more pleasant. Here's a real-world case study. This is from a Wirebird Labs client who gave permission to release this screenshot of a bird's eye view of their application analyzed using Links. What we're looking at in the screenshot below is an application with over 8000 application VIs (not including third-party dependencies). Libraries are identified by labels. Nodes represent a source file (mostly VIs, but also including LVLIB and LVCLASS and CTL), and connections between nodes represent static links as detected by the LabVIEW linker. This is a static screenshot of the application, but while running the physics engine lays out nodes as a force diagram. The strength of the force is based on number of static links existing between nodes, and a negative force is applied to nodes with no static links. This causes nodes to form clusters in space where strong coupling exists. What is the value of analyzing the application like this? Here is a list of issues we needed to solve: It took a long time to build. This made iterating costly, both in time and morale. Oftentimes, the build failed (anecdotally, a fresh warm boot of LabVIEW helped) The IDE was painfully slow during development; the cursor continually was "waiting" during wiring operations. The way we solved both problem was simply by taking a pair of "scissors" and snipping links between nodes. The types of links that we snipped were these incidental links introduced by packaging and namespacing facilities in LabVIEW: removing LVLIBs altogether removing VIs from LLBs calling concrete instances of polymorphic VIs rather than the parent removing public type definitions and utility VIs from LVCLASSes Within a couple days, we went from "kick off a build and go grab lunch" to "kick it off and get a coffee". The application and application framework had not changed to see these improvements; just the logical and physical packaging of dependencies. (In addition to solving the main performance pain points, additional areas for architectural consideration are easily visualized; that's beyond the scope of this conversation) Without LVLIBs, how do I avoid name collisions? I prefer this filenaming convention: Project-Class-Method.vi or Application-Class-Resource-Action.vi ... or generally, LeastSpecificNamespace-...-SpecificThing-...-VerbActingOnASpecificThing.vi For instance, Deploy-UpdateService-CheckForUpdates.vi or FTW-JSON-Deserialize.xnode. The name of the owning class just drops the -Method postfix. Is it ideal? It's neither terrible nor great. Some benefits are that filenames sort nicely, and it's easy to spot anomalous linkages. Semantic naming makes it easier for development tools outside the IDE (SCC client and provider, build toolchains). One downside is that your hand is forced on naming Dynamic Dispatch methods in classes (again, I desire to see this coupling separated by a degree of indirection in future LabVIEW versions). Conclusion? This area of LabVIEW does not have a general solution or general best practice. Be aware of tradeoffs of different strategies, and ensure they map successfully to your application space, stakeholder's needs, and team's sanity. Standing offer: Send me a message if you feel some of the scaling pain points: busy cursor while wiring build times lasting longer than 10min mass compile times lasting longer than 10min LVProj takes longer than 1min to load and within 2hrs of screensharing I reckon we could substantially improve your LV dev experience. I'm interested to further build tribal knowledge and provide feedback to NI on taking LabVIEW applications and teams to scale. Edited November 28, 2014 by JackDunaway 16 Quote
Popular Post ShaunR Posted November 28, 2014 Popular Post Report Posted November 28, 2014 (edited) @JackDunawayGreat analysis with which I agree with 99.9% (except for your first sentence). You are skirting around a couple of fundamental issues, not directly to do with LVLibs but with LVPOOP and are the reasons why LVLIbs fall short of expectations. I think you have seen and hinted at, but not articulated, though. 1. it is impossible to create LVPOOP components with zero static linking (this is trivial with an open VI and a LLB full of functions which can be loaded and unloaded dynamically).2. A function per VI is a purely semantic imposition for dynamic dispatch.3. With the exception of namespacing with paths, classical labview programmers only have similar issues by bad architectural design rather than language imposition and can always avoid the issues by best practices and frameworks. Food for thought:If huge amounts of analysis and tribal knowledge is required to not write bloated, unscalable and buggy code with a certain tool. Is it not a better strategy to just not use that tool? Edited November 28, 2014 by ShaunR 5 Quote
Neil Pate Posted November 28, 2014 Report Posted November 28, 2014 Food for thought: If huge amounts of analysis and tribal knowledge is required to not write bloated, unscalable and buggy code with a certain tool. Is it not a better strategy to just not use that tool? Those outcomes are possibilities, not guarantees. Not every application has 8000 VIs, and in a lot of situations the careful use of libraries can be really beneficial. I am not ready to give up on them yet. Quote
JKSH Posted November 28, 2014 Report Posted November 28, 2014 You are skirting around a couple of fundamental issues, not directly to do with LVLibs but with LVPOOP and are the reasons why LVLIbs fall short of expectations. Isn't that upside-down? LVClasses are specializations of LVLibs, so they inherit the strengths and weaknesses of LVLibs, not the other way round. If LVLibs are improved, then LVClasses will automatically gain those improvements too. 2. A function per VI is a purely semantic imposition for dynamic dispatch. If I've understood Jack's point correctly, the issue is that the one-function-per-VI system significantly increases the number of files in a project. This increases the effort required to write and refactor code (all LabVIEW code, not just LVClass code). This also amplifies the lags caused by widespread static linking. Quote
Popular Post Phillip Brooks Posted November 28, 2014 Popular Post Report Posted November 28, 2014 Food for thought: If huge amounts of analysis and tribal knowledge is required to not write bloated, unscalable and buggy code with a certain tool. Is it not a better strategy to just not use that tool? TestStand? 3 Quote
JackDunaway Posted November 28, 2014 Report Posted November 28, 2014 You are skirting around a couple of fundamental issues, not directly to do with LVLibs but with LVPOOP and are the reasons why LVLIbs fall short of expectations. I think you have seen and hinted at, but not articulated, though. 1. it is impossible to create LVPOOP components with zero static linking (this is trivial with an open VI and a LLB full of functions which can be loaded and unloaded dynamically). It's tenable at worst, desirable at best, for an LVCLASS and its members to be statically-linked. Any desire otherwise could be an indicator of class design or object model that could use refactoring, or a desire for more appropriate language facilities (more on that later). For an illustrated example, here's one annotated section of the diagram above: The top arrow shows methods from a third-party hardware driver that are required by the application, the middle arrow is very likely an LVCLASS or LVLIB, and the bottom arrow shows unreachable, unused dependencies -- portions of the hardware API that bloat the application. Although not ideal, this scenario of roughly ~30 unused source files may not be measurably bad. The birds-eye view of this application indicates ROI of refactoring this class probably isn't justified. Though, used in another application, that exact same library could cause problems (such as even further unwanted linkages, perhaps even some that break the application with unsatisfied dependencies such as uninstalled packages or platform-specificity). Different application space yields different polarizing filters through which we choose tradeoffs. As library designers, it's worthwhile to consider our responsibility to enable our developer-end-users, and explicitly avoiding designs which cause them heartache. -- I wasn't going to bring up Inheritance as another type of static linkage best cut with our figurative link scissors, but it's now relevant in the context of LVOOP. Inheritance, in and of itself in any language, represents a code smell worth investigating. But... Inheritance! Dynamic Dispatch! This example demonstrates precisely the value of traits/mixins in an OOP language. With traits/mixins, we can achieve all desirable outcomes discussed above in terms of higher cohesion and looser coupling (and re-use!), by eschewing 1) suboptimal/incorrect inheritance hierarchies, and 2) classes that do too much, even if there appears "good reason" for the monolithic library (Hardware APIs for LabVIEW are notorious for wrapping serial protocols as one-command-per-VI in monolithic libraries. There are thoughts/considerations of dynamic versus static programming as another solution, but that's another thread). Lacking Mixins in LVOOP, Inheritance sometimes is workably sufficient to describe and implement the real-world, but oftentimes it can't. Again, to be fair, it's healthier to focus on measurable negative value than pedantry, and oftentimes it's workable to incur these tradeoffs introduced by inheritance. @ShaunR, for this reason, I don't think LVCLASSes fall short in the way you might be describing. (Except for one debatable behavior in the IDE, where all classes in a hierarchy are broken if one is, and where the explanation as to why in that link is tenuous, where the more desirable behavior is to throw run-time exception in the scenario presented in that link) The way that LVCLASSes fall short is by lacking Mixins, which provide targeted and precise linkages to atomic units of relevant code. (for clarity, regardless whether industry is landing on the term Trait or Mixin, I support the construct that also provides extension of mutable state, not just method implementations, and certainly not just interfaces with no implementations. I think "Mixin" is most appropriate, its distinction from "Trait" being "Trait" might not connote further extension of state) it is impossible to create LVPOOP components with zero static linking tl;dr The design goal when designing an LVOOP object model is not necessarily to avoid all static links, but rather to intentionally design dependency vectors, especially recognizing and avoiding anomalies and incidental linkages that have detectable negative value. And, LVOOP needs Mixins. 1 Quote
ShaunR Posted November 28, 2014 Report Posted November 28, 2014 (edited) @ShaunR, for this reason, I don't think LVCLASSes fall short in the way you might be describing. (Except for one debatable behavior in the IDE, where all classes in a hierarchy are broken if one is, and where the explanation as to why in that link is tenuous, where the more desirable behavior is to throw run-time exception in the scenario presented in that link) The way that LVCLASSes fall short is by lacking Mixins, which provide targeted and precise linkages to atomic units of relevant code. Sorry Jack. Everything will be fine if only we had X,Y Z is just adding more goo to a sticky mess. I think this discussion needs to be taken to another thread so as not to derail the OP (any further?) as there are some very simple premises here that are being conflated. Edited November 28, 2014 by ShaunR Quote
JackDunaway Posted November 28, 2014 Report Posted November 28, 2014 Food for thought: If huge amounts of analysis and tribal knowledge is required to not write bloated, unscalable and buggy code with a certain tool. Is it not a better strategy to just not use that tool? To carefully dereference "certain tool", if that refers to LVLIB, yes -- it's worth considering whether this tool belongs in our toolbox. If "certain tool" dereferences to LabVIEW -- LabVIEW as a language is excellent and certainly not worth abandoning. Conversely, it's worth considering if you're not already using it. LabVIEW has rooms for significant improvement, but its syntax is currently unparalleled in programming, period. 1 Quote
hooovahh Posted December 1, 2014 Report Posted December 1, 2014 Awesome chain of discussion guys. Sorry OP if this is derailing the conversation but I think it still is relevant to the original question. Making and using polymorphic VIs is a major pain point for several reasons. And from a reuse stand point there isn't many other options. Replacing polymorphics with XNodes (if every officially supported) I think would help because you replace the 40+ instances with a custom scripted VI. No idea if it scales well. Jack you mentioned replacing polymorphic VIs with their instance. In my mind this is something that could be done quite easily with scripting for a while project. This could be a VI that is ran periodically, possibly as part of the Pre-Build VI that could help clean up the project. Did you ever make this scripting VI? Could you see sharing it if you ever did? Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.