Jump to content

Redistributing Classes


Recommended Posts

Howdy!

As a developer distributing classes, what type of namespacing do you do/use?

I have been renaming the class during the source distribution (NI app builder).

But I have been thinking about using libraries (.lvlib's) a bit lately

Somewhere after 8.2, and definitely in 2009 you can add the source to a lvlib during a build

This seems a handy way of renaming the entire class hierarchy all in one go.

Any which way better?

Cheers

JG

Link to comment

Short answer:

Descriptive library filename appended with major version number.

EventManagerLibrary__v1.lvlib

MessageLibrary__v2.lvlib

Long answer:

[Pet Peeve alert!]

The way LV ties namespaces to libraries has irritated me for some time and is (imo) clearly inferior to other modern languages. For example, the .Net framework separates the physical code organization (assemblies) from the logical code organization (namespaces).

Another way to organize your Visual Basic .NET code is through the use of namespaces. Namespaces are not a replacement for assemblies, but a second organizational method that complements assemblies. Namespaces are a way of grouping type names and reducing the chance of name collisions. A namespace can contain both other namespaces and types. The full name of a type includes the combination of namespaces that contain that type.

Link

Labview can't do that. It's namespaces are simply a byproduct of the library file name and you can't create logical groups of related functions across multiple libraries. I gave up trying to create some sort of unified hierarchical namespace. Without the ability to separate the physical and logical organization any scheme I come up with is too fragile. (An ealier attempt to create a namespace tree by nesting libraries resulted in what my 12-yo daughter would call an "epic fail.")

However, I have finally taken AQ's advice and starting using lvlibs to organize my code into modules, and despite the inconvenience of writing more wrapper methods I think it is worth it. It definitely helps me maintain a layered application structure and limit interdependencies. I include the library right in source code rather than adding the code to a library during the build. Doing it in source helps me maintain the separation (both in code and in my head) between the library functionality and the library api. If I was distributing a single class, I wouldn't bother putting it in a library unless I expected to add more classes to it in the near future.

Link to comment

I include the library right in source code rather than adding the code to a library during the build. Doing it in source helps me maintain the separation (both in code and in my head) between the library functionality and the library api.

Me too, but I rename the library in the distribution process as to avoid a clash with the source - e.g. after it has been distributed to <vi.lib>.

This way I can control the member scopes

I only generate a new library if I want to wrap up support VIs so the release does not have those dependencies (e.g. from OpenG, my reuse library etc..).

This is a great way to do it for toolkits.

However, I have finally taken AQ's advice and starting using lvlibs to organize my code into modules, and despite the inconvenience of writing more wrapper methods I think it is worth it. It definitely helps me maintain a layered application structure and limit interdependencies.

Is this your application code or reusable code?

I have been using .lvlibs a lot lately in my application code, and it has been working out very nicely.

I now what to see where these fit with respect to reuse.

I was of the same opinion as you - that .lvlib items get loaded into memory as a group - but AQ has pointed out that this only relates to classes, which I did not know and thats why I shied away from them in the past for reuse.

However, I use VIPM and its namespacing for my general reuse library (string, boolean etc..), but at the moment I handle toolkits and classes myself (as there is no need to rename the member VIs).

I have been renaming the .lvclass file during the build, but in order to make my namespacing more unique and am looking at the best way to distribute those - rename .lvclass or use a .lvlib wrapper instead.

If I was distributing a single class, I wouldn't bother putting it in a library unless I expected to add more classes to it in the near future.

But then, if you did expand the source release in the far future by adding another class (for functionality or to release an inherited class), the original class would name be namespaced differently and your calling code would break?

Therefore, I am considering doing it for even single class released.

Plus I don't have to rename the class then - so it is no more or less work for me.

Add multiple classes in a library is great, as I only have to rename the library during the build, not each .lvclass file - so in that case its less work.

Short answer:

Descriptive library filename appended with major version number.

EventManagerLibrary__v1.lvlib

MessageLibrary__v2.lvlib

So how does your application code get updated automatically when you release a new version of your reuseable class?

If the reuse library name changes between releases, then your application code would break?

Cheers

JG

Link to comment

Short answer:

Descriptive library filename appended with major version number.

EventManagerLibrary__v1.lvlib

MessageLibrary__v2.lvlib

Using the version number in the library name will make it possible to have multiple version of the same library in you code(base), is that what your after?

I don't think that is a common thing and it migth cause broken code.

I don't see the use of a class inside an lvlib, a class is a special kind of library, so it's not really usefull.

Ton

Link to comment

I don't see the use of a class inside an lvlib, a class is a special kind of library, so it's not really usefull.

You can namespace the class by wrapping it in a library.

This is more beneficial if you have multiple class (in one distribution) that you want to rename for distribution.

Link to comment

Is this your application code or reusable code?

Both.

I was of the same opinion as you - that .lvlib items get loaded into memory as a group - but AQ has pointed out that this only relates to classes, which I did not know and thats why I shied away from them in the past for reuse.

I don't remember that discussion. Does that mean all the classes in a library (and all class members) get loaded, or just the class members of the one class that is used (assuming multiple classes in a library?)

However, I use VIPM and its namespacing for my general reuse library (string, boolean etc..),

I no longer have a general reuse library for simplish operations, primarily because the benefit I got from them didn't justify the overhead of maintaining them in a reuse library, but also because I'm trying to control the dependencies my applications and reuse code has on external modules. I do have a bunch of utility VIs I can use, but I'll either copy the vi and add it to the application code or occasionally I'll copy the code directly to my target vi. My reuse code modules target relatively large chunks of functionality, such as message handling, various kinds of data structures, etc.

But then, if you did expand the source release in the far future by adding another class (for functionality or to release an inherited class), the original class would name be namespaced differently and your calling code would break?

If I had released a single class as a reusable code module, and later wanted to extend the functionality with additional classes, I would create a new code module with the original class and the additional classes packaged in a lvlib. The original class and the class in the lvlib can exist in memory at the same time, so the calling code doesn't break. If I want to upgrade source code to the new library, then yes, code breaks and I have to fix it manually. However, so far the only single-class reusable code modules I have are instrument drivers and I haven't encountered a situation where I would add additional classes to them. I have created mock instrument drivers by overriding the functioning methods with empty methods in a derived child class, but I consider this application test code rather reuse code.

So how does your application code get updated automatically when you release a new version of your reuseable class?

If the reuse library name changes between releases, then your application code would break?

The questions are a little ambiguous. I'm not sure if you're referring to a built application or application source code. Currently all my reuse modules are intended to be reused during dev-time, not run-time, so I'll address it from that perspective.

I change major version numbers (and hence the module filename) only when backwards compatibility is broken, so any compatible updates are automatically included in the application source code the next time I open that project. Since new versions are incompatible by definition, I don't want applications to automatically use the new version. The application still loads the previous version of the library so it is not broken.

Using the version number in the library name will make it possible to have multiple version of the same library in you code(base), is that what your after?

I don't think that is a common thing and it migth cause broken code.

Not so much in the same application, though there's no reason I know of that it would inherently break code. It's more so I don't have to fiddle around with making sure I have the right version installed for a given project. I can simply have them all on my dev computer at the same time.

Link to comment

This is more beneficial if you have multiple class (in one distribution) that you want to rename for distribution.

The more important feature (for me) is the ability to set the scope for specific classes within the library. I can have all sorts of utility and worker classes in the library that I've scoped as private and aren't part of the library's public api. This ability alone is a huge help in keeping my code organized and maintainable.

Link to comment

I don't remember that discussion.

Sorry, I thought you mentioned it on an NI forum. It must have been someone else.

Does that mean all the classes in a library (and all class members) get loaded, or just the class members of the one class that is used (assuming multiple classes in a library?)

I am under the opinion that all VIs in a class get loaded into memory, but not all VIs in a library do.

Can someone confirm this please (AQ :))???

I no longer have a general reuse library for simplish operations, primarily because the benefit I got from them didn't justify the overhead of maintaining them in a reuse library, but also because I'm trying to control the dependencies my applications and reuse code has on external modules. I do have a bunch of utility VIs I can use, but I'll either copy the vi and add it to the application code or occasionally I'll copy the code directly to my target vi. My reuse code modules target relatively large chunks of functionality, such as message handling, various kinds of data structures, etc.

If I had released a single class as a reusable code module, and later wanted to extend the functionality with additional classes, I would create a new code module with the original class and the additional classes packaged in a lvlib. The original class and the class in the lvlib can exist in memory at the same time, so the calling code doesn't break. If I want to upgrade source code to the new library, then yes, code breaks and I have to fix it manually. However, so far the only single-class reusable code modules I have are instrument drivers and I haven't encountered a situation where I would add additional classes to them. I have created mock instrument drivers by overriding the functioning methods with empty methods in a derived child class, but I consider this application test code rather reuse code.

Great post, thx, its cool to hear someone else's approach to reuse.

Do you distribute your reuse code in packages (e.g. .ogp or vip) to your developers?

The questions are a little ambiguous. I'm not sure if you're referring to a built application or application source code. Currently all my reuse modules are intended to be reused during dev-time, not run-time, so I'll address it from that perspective.

I change major version numbers (and hence the module filename) only when backwards compatibility is broken, so any compatible updates are automatically included in the application source code the next time I open that project. Since new versions are incompatible by definition, I don't want applications to automatically use the new version. The application still loads the previous version of the library so it is not broken.

Not so much in the same application, though there's no reason I know of that it would inherently break code. It's more so I don't have to fiddle around with making sure I have the right version installed for a given project. I can simply have them all on my dev computer at the same time.

Sorry about the ambiguity, I was interested to know if you updated the reuse module, and you wanted you application code to link to this new version, how would it be handled automatically (which you have answered).

The more important feature (for me) is the ability to set the scope for specific classes within the library. I can have all sorts of utility and worker classes in the library that I've scoped as private and aren't part of the library's public api. This ability alone is a huge help in keeping my code organized and maintainable.

I am purely looking at the benefits for namespacing, so I meant more beneficial when compared to a single class... ...but obviously access scope is the major plus if that is required, for a particular release.

Link to comment

I am under the opinion that all VIs in a class get loaded into memory, but not all VIs in a library do.

Can someone confirm this please

From the dark side:

Just to clarify, LabVIEW loads all members of an LV class when a class or a member VI is loaded. LabVIEW does NOT load all members of a regular project library when the library loads.

George M

National Instruments

Link to comment

All good news

Yeah, except the part about me not remembering a discussion from three days ago. wacko.giflaugh.gif (Actually I thought you were referring to a discussion from many months ago...)

I created this example project to explore the behavior and there are still things going on I'm not understanding. I get the impression that each individual decision makes sense but I find the overall behavior rather confusing.

post-7603-126845894437_thumb.png

After closing the project, if I load any one library then it opens a project window with Lib 1 at the root and all the other libraries correctly listed as children. The VI hierarchy window shows that only the two lvclass files and the two class VIs are loaded. This (along with the comments from George and Stephen) leads me believe the entire library hierarchy is loaded regardless of the library type, but whether or not the VIs are loaded depends on the library type.

After closing the project again, if I open VI 8 the entire class is loaded including--according to the VI hierarchy window--the lvclass file. Since an lvclass file is a library, does that load the entire library hierarchy and both classes? Apparently it depends on which app instance it's loaded into. If it's loaded into the Main App Instance then no, the loading appears to stop with that class. If it's loaded into a user app instance then yes, the whole library hierarchy is loaded... unless part of the library hierarchy is already loaded in the main app instance.

post-7603-126846048931_thumb.png

Here I had loaded up VI 8 in the Main App Instance, then created an empty project file (declined to add the open vi's to the project) and opened one of the libraries. Class 2 is missing from the project, even though it is part of Lib 5. I thought that was odd so I closed that project and opened my original saved project. Both Class 1 and Class 2 were missing from the project! (Not shown.)

I understand that VIs can't communicate across app instances, and by not loading another copy of Class 2 into the project context we can save some memory and time, but not showing the class as part of the library is confusing. I can't think of any reason why both classes were missing when I loaded the original project.

I will say that even though the classes were missing from the project window Labview appears to handle it reasonably well behind the scenes. I made some modest attempts attempts at messing up the library links and after reopening the saved project everything was in place and the missing classes were back. More radical attempts to screw with Labview resulted in crashes.

I also saw inconsistencies while renaming the lvlib files. Try this:

  1. Open the project and rename Lib 1.
  2. Save when prompted. (Notice only VIs are being saved; no lvlibs.)
  3. The project window shows a dirty dot, so Save All.
  4. Rename Lib 2. Save when prompted. Notice no dirty dot is on the title bar.
  5. Using a text editor, open the (now renamed) Lib 1 and Lib 3.

Both should have references to your newly renamed Lib 2, but they still have the old name in place. If you close the project without saving (which should be fine, since there's no dirty dot) you'll have a heck of a time trying to fix the project. I don't know if this is a side effect of the loading behavior of the lvlib files, if it's an unrelated bug, or if I've been misinterpreting what the dirty dot actually means.

I appreciate the efforts NI goes to to hide the details from us and have it "just work." Still, I wish we had more information about exactly what is loaded and more control over when it is loaded.

Nested Libraries.zip

Edited by Daklu
Link to comment

Yeah, except the part about me not remembering a discussion from three days ago.

Thats alright, I just thought I was going crazy :wacko:

I created this example project to explore the behavior and there are still things going on I'm not understanding. I get the impression that each individual decision makes sense but I find the overall behavior rather confusing.

Great post. I will have to spend some more time looking at what you have come up with before I can comment.

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

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