Jump to content

Project, Libraries and Classes, oh my!


Recommended Posts

I am testing the waters for converting my large application into LabVOOP. We have a lot of clusters (typedefs of course) so the end goal is to hew to AQs advice that "all clusters should be classes". I would also like to supply more unit testing as I go along.

However I feel a bit confused by one basic thing: How do I map my existing code into lvclass, lvlib, and lvproj? I get it that lvclass is the cluster and the functions which muck with its private data, and that lvlib is a namespace and has a one-to-one pairing with VIs. I am also thinking that each functional grouping should be an lvproj which includes some test VIs, or should they be in the lvlib too?

If I can take similar clusters and convert them into inherited objects from a base class, then how much of that goes into lvlib?

I realize there are no strict answers, but I'm having trouble getting started. Any advice would be appreciated.

Link to comment

AQ's general thoughts on project, library and VI relationships:

  1. A VI is a function dedicated to a specific task. It has no particular allegiance to any particular application. It doesn't care who calls it... it does what it does when it is invoked.
  2. A Library is a collection of related VIs. Some libraries are dedicated to a particular task: .lvclass libraries are dedicated to defining a new data type. .xctl libraries are dedicated to defining a new control. Libraries are coherent distribution units -- all the VIs therein should distribute together. The VIs that test a library's functionality should not be in the library since you don't generally want to distribute your test harness. Again, libraries have no allegiance to any particular application in LV.
  3. A project *is* a particular LV application. There is a one-to-one correspondence between "something I as a user generate to be an end product" and a single .lvproj file. There is some leniency to this one-to-one relationship if a single chunk of VIs are used to build multiple build targets -- perhaps both an exe and a dll, or multiple flavors of source distribution, for example -- but these are just flavors of the same general deliverable.
  4. The project should include the test harness for the deliverable.
  5. A VI and a library are reusable components. They may be used by multiple projects. If you intend to have a component that you share between multiple projects, then there should be a project for that shared component itself. That project should contain the test harness for that component. The other projects that just use the shared component don't include the test harness for the shared component.
  6. In the most extreme of stringent coding practices, the project for the shared component has a Source Distribution build. It is used to generate a separate copy of the source code which will be used by all the other projects. The other projects do not ever reference the original source code of the shared component. This protects against unintended edits, and allows you to always regenerate from the shared component's project a clean version of the shared component.
  7. The post above said "that lvlib is a namespace and has a one-to-one pairing with VIs". The Library actually has a one to many relationship with VIs. Each lib contains multiple VIs. You should package together VIs that are related, to the extent that feels reasonable to you. Some libs are very small. The Analysis library that ships from NI has 600+ VIs in it. In the words of Yoda, "Size matters not." It is a question of how related the functionality is and whether the VIs are intended to be distributed/used together. You can use sublibraries to give further breakdown if that is useful.
  8. Make VIs private or protected whenever possible. It helps your debugging later if you know that no one else could possibly be calling a given VI. And it makes it easier to change conpanes if you know that no one else is using a given conpane.
  9. My personal goal is that all VIs should be owned by either an XControl library or an LVClass library. Plain libraries should only own other libraries for packaging and distribution purposes. This is in accord with the maxim "All bits of data may be thought of as part of some object; all functions may be thought of as actions taken by some object." Do I actually keep to this goal? No. LabVOOP still has inefficiencies in some places, and sometimes I get lazy. But I'm working toward that goal and do believe it is viable.
  10. All the VIs for a single project go in a single directory unless they are components intended to be shared among many projects. Within that single directory, I recommend creating subdirectories for each library. I do not recommend that you have any further disk hierarchy. If you create folders within your libraries, so be it, but don't make directories on disk that reflect those folders. Why? Because folders are the organization of your library for presentation as a palette and for providing scope for VIs. It is really annoying to want to change the scope of a VI and have to save it to a new location to keep your disk organization consistent. And it serves no purpose. If the library is a coherent distribution unit, then when you're on disk you're supposed to be moving the entire library as a chunk. Some people complain that that makes it hard to use the "Select a VI..." item in the palette. But I suggest that is what drag-n-drop from the project is for. Use the project window as a pinned palette during development. When you deploy, deploy the library with a .mnu file that is part of the regular palette hierarchy.
  11. All of this can feel like overkill for a single developer by him/herself. But I find that these guidelines help avoid cross-linking problems, debug problems and distribution problems even with my own projects that aren't shared with any other G developers.
  12. All of the above are my PERSONAL thoughts and should not be taken as NI speaking. I am NOT a full or even part time G developer. I do C++ and G is my hobby, so take my advice with a grain of salt. But, on the other hand, I do spend a lot of time talking about and thinking about what the right way to do things in G is, and I know how the internals are designed. At any rate, its your call how valuable you think all this advice is.

PS: If your clusters are already typedefs, put the typedef into the project window, popup on it and choose "Convert Contents of Control to Class." This will help you on your way to converting your project over.

  • Like 1
Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 01:29 PM)

AQ's general thoughts on project, library and VI relationships...

Nicely done summary. It's helpful for me to hear it -- and see it! -- again, and again, and again. Having worked as a single developer -- and essentially on a single project -- for a number of years, I know the various shortcuts that I've developed to implement these ideas. It's really great to see the support from them being implemented directly within LV.

Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 01:29 PM)

AQ's general thoughts on project, library and VI relationships:

I could probably post this after most of your responses AQ, but this is an excellent post. Perhaps it should be morphed into a wiki article of some sort?

Jaegen

Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 01:29 PM)

AQ's general thoughts on project, library and VI relationships:

The post above said "that lvlib is a namespace and has a one-to-one pairing with VIs". The Library actually has a one to many relationship with VIs. Each lib contains multiple VIs. You should package together VIs that are related, to the extent that feels reasonable to you. Some libs are very small. The Analysis library that ships from NI has 600+ VIs in it. In the words of Yoda, "Size matters not." It is a question of how related the functionality is and whether the VIs are intended to be distributed/used together. You can use sublibraries to give further breakdown if that is useful.

The point I was attempting to make is that a given VI can only be a member of one library. If two different pieces of code need to call the same function, I guess that requires it to be made into a separate object with its own lvlib (or preferably an lvclass), which can then be shared.

QUOTE

My personal goal is that all VIs should be owned by either an XControl library or an LVClass library. Plain libraries should only own other libraries for packaging and distribution purposes. This is in accord with the maxim "All bits of data may be thought of as part of some object; all functions may be thought of as actions taken by some object." Do I actually keep to this goal? No. LabVOOP still has inefficiencies in some places, and sometimes I get lazy. But I'm working toward that goal and do believe it is viable.

Not knowing any better, I would suggest that most lvclasses should be contained in either an lvlib or lvproj to hold the class and its test harness and any examples.

QUOTE

All the VIs for a single project go in a single directory unless they are components intended to be shared among many projects. Within that single directory, I recommend creating subdirectories for each library. I do not recommend that you have any further disk hierarchy. If you create folders within your libraries, so be it, but don't make directories on disk that reflect those folders. Why? Because folders are the organization of your library for presentation as a palette and for providing scope for VIs. It is really annoying to want to change the scope of a VI and have to save it to a new location to keep your disk organization consistent. And it serves no purpose. If the library is a coherent distribution unit, then when you're on disk you're supposed to be moving the entire library as a chunk. Some people complain that that makes it hard to use the "Select a VI..." item in the palette. But I suggest that is what drag-n-drop from the project is for. Use the project window as a pinned palette during development. When you deploy, deploy the library with a .mnu file that is part of the regular palette hierarchy.

One thing that has always been helfpul to me in the non-oo world is to have the top-level folder only contain top-level vis. That's been a self-documenting way to communicate where someone should start when attempting to take over the code. I suppose the key here is to make sure the top level folder only contains the main project, and then within the project, that only main VIs are shown outside of folders.

QUOTE

PS: If your clusters are already typedefs, put the typedef into the project window, popup on it and choose "Convert Contents of Control to Class." This will help you on your way to converting your project over.

Great! Thanks for the help.

Jason Dunham

Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 01:29 PM)

AQ's general thoughts on project, library and VI relationships:

A project *is* a particular LV application. There is a one-to-one correspondence between "something I as a user generate to be an end product" and a single .lvproj file. There is some leniency to this one-to-one relationship if a single chunk of VIs are used to build multiple build targets -- perhaps both an exe and a dll, or multiple flavors of source distribution, for example -- but these are just flavors of the same general deliverable.

One thing I tried and quickly decided was not worthwhile was to link projects. For whatever reason, you can stick a project within a project.

I thought 'this could be cool' (which I now recognize as slang for cross your fingers cause there's probably a reason this isn't being done by your peers already) -- as this could allow me to develop one project that could later be used as a 'component' of another project. For example, I could create a set of common classes could be put in a project that could be used by other project files -- code reuse at its best.

Not so fast! It turns out that if you link projects (by adding a project to a project) then all of the classes/etc in the subproject become locked whether or not a single VI is open by the superparent. That means that while I'm debugging the super project, if I find a problem in a core project, I have to close the super project to make any changes (rather than closing VIs that are located in the superproject). So, in the end I had to remove the linkage between the projects as it didn't buy me anything (if I just included the classes in the super project and removed the subproject, I could edit the classes as if they were owned by only 1 project).

So, in the end, a project does have a 1 to 1 relationship with a LV Application (even though it is possible to 'try' to make it 1 to many) -- a definite shortcoming of the project environment.

Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 05:52 PM)

I wouldn't take this route. Again, the library should be a distribution unit. Your test harness never gets distributed with your production code. So they shouldn't be in a module together. The test harness should be in the project that is used to create the classes.

But if your test harness calls private members of a class then the test harness must be a member of the class -- but, it shouldn't since this violates the "test harness never gets distributed with your production code" rule. It's too bad that LVOOP classes are so unfriendly to test harnesses ;)

Link to comment

ZITAT(Aristos Queue @ Aug 17 2007, 10:29 PM)

Use the project window as a pinned palette during development. When you deploy, deploy the library with a .mnu file that is part of the regular palette hierarchy.

Wait a second... does this mean, there is a way to have a library that comes with it's own .mnu file in my project and whenever I load the project, I get an additional sub-palette in my functions palette?

If this can be done: How exactly? :question:

If not: This would be a great feature for people that don't want to save user data in the programm files directory. :thumbup:

Link to comment

QUOTE(Jim Kring @ Aug 17 2007, 08:55 PM)

But if your test harness calls private members of a class then the test harness must be a member of the class -- but, it shouldn't since this violates the "test harness never gets distributed with your production code" rule. It's too bad that LVOOP classes are so unfriendly to test harnesses ;)

Depending on your view of class testing, this shouldn't be a problem. If the only part of your class that can be invoked is the public API, then a test harness that validates the public API is all you need. If there's a bug in an underlying private subVI, but that bug doesn't affect the public functionality, then who the heck cares? But, yes, your comment is noted. :ninja:

Link to comment

QUOTE(silmaril @ Aug 18 2007, 01:40 AM)

Wait a second... does this mean, there is a way to have a library that comes with it's own .mnu file in my project and whenever I load the project, I get an additional sub-palette in my functions palette?
No. What it means is that if the library is part of your project, you just drag and drop items from the project window to the diagram. If you've created a library for distribution (as a toolkit for others), then add a .mnu file that gets installed with the library.

Your misinterpretation of my comments is a good idea however. I'll pass it along.

Link to comment

QUOTE(Aristos Queue @ Aug 17 2007, 10:29 PM)

AQ's general thoughts on project, library and VI relationships:

...

In the most extreme of stringent coding practices, the project for the shared component has a Source Distribution build. It is used to generate a separate copy of the source code which will be used by all the other projects. The other projects do not ever reference the original source code of the shared component. This protects against unintended edits, and allows you to always regenerate from the shared component's project a clean version of the shared component.

One thing to notice, use different names for the source and the delivered libraries!

Consider a library as a full blown product, just like an executable or dll.

QUOTE

My personal goal is that all VIs should be owned by either an XControl library or an LVClass library.

Be aware that some parts (properties/methods/Data ability) of an XControl should be public or your code will not run.

QUOTE

Plain libraries should only own other libraries for packaging and distribution purposes.

Be aware that trapping a library in another library will change it's name, so dynamic loading will needs to be reviewed

AQ your comments are just on the spot. I have to convince a coworker to use OpenG builder to distribute our user.lib VI as libraries and have them on spot ready after an upgrade.

Ton

Link to comment

QUOTE(Aristos Queue @ Aug 18 2007, 08:52 AM)

Your misinterpretation of my comments is a good idea however. I'll pass it along.

Thank you very much, AQ! :worship:

I would really appreciate a feature to have project-specific function palettes.

The "official NI way" of doing this has several disadvantages (no different library versions for different projects, bad Perforce integration, "illegal" to copy user data to programm files directory...), so I am looking forward to a good way of getting rid of the "user.lib" without loosing it's comfort. :thumbup:

At the moment I am using my project window as a palette, but I am shure, usability can be improved here.

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
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.