Coding Conventions

This How-To aims at describing some coding conventions that should be used by CS developers. This is just a list of things, each developer and maintainer should check when he/she is working on a class. These coding convention have already been adapted to CS version 3.10 or higher using LabVIEW 8.20 or higher. This list just complements the coding conventions of NI.

  1. Each class is represented by a LabVIEW library (lvlib). Use the LabVIEW project manager with the on-line help enabled to view the class. Remark: CS does not use LabVIEW Object Oriented Programming (LVOOP). No schedule exists for migrating CS to LVOOP.
  2. Is the class documentation in a good shape (description, author, maintainer, ...)? The class documentation is located in the description of the lvlib.
  3. By using the project manager, one should go through all methods of a class.
    1. VI properties:
      1. Protection: All VIs should be unlocked.
      2. Execution: The "reentrant" flag should be checked, in case a method is a "waiting" method having a timeout value. The "reentrant" flag should not be checked, if the method just executes without any sub-VI waiting on something. Reentrant VIs should use code sharing.
      3. Documentation: Is there a good documentation in the VI description?
    2. Error handling: By convention (and recommended by NI) methods should only be executable, if "error in" is not an error. Probably, you need to add an additional "case-structure" for most methods. However, there are two exceptions:
      1. Methods handling attribute data ("get i attribute", "get data to modify", ...) are always executed.
      2. As recommended by NI, methods cleaning up acquired resources ("destructor", ...) are always executed.
    3. Front panel:
      1. Timeout values: The recommended default value for timeouts has been changed from 100ms to 10000ms.
      2. For all controls, the description and tool tips must contain a reasonable description.
      3. For indicators, the description and tool tips must contain a reasonable description.
    4. Block diagram:
      1. Dataflow goes from left to right. All VIs have the inputs of their connector pane at the left and the outputs at the right side.
      2. All case structures, loops, sequences, ... have their "label" enabled containing a short description.
    5. Connector pane:
      1. It is recommended to use the pattern, which has 20 possible connections (amongst the "patterns" it is the second from the right in the lowest line). You can set the default in the LabVIEW.ini: "defaultConPane=4834".
      2. "i ref in"/"i ref out" should be wired to the top left/right connections.
      3. The connection "i ref in" should be set to "required".
      4. "error in"/"error out" sohould be wired to the bottom left/right connections.
      5. "timeout" should be wired to the third connection from the bottom on the left side.
      6. "timed out" should be wired to the third connection fromthe bottom on the right side.
      7. For an example, have a look at the "get data to modify" method of your class.
  4. Data types. Do not use unflatten/flatten string VIs. CS classes should use the following data formats:
    1. When sending/receiving commands (lvmsg, lvnot):
      1. "CoreLib.data 2 byte array" (simple data types), when sending commands with data.
      2. "CoreLib.byte array 2 data" (simple data types), when receiving a command.
      3. When answering a command, the data descriptor for the return data should be specified in "ProcCases".
      4. Complex data types should be converted to simple data types. Example: All LabVIEW waveform data should be transferred as "D:1;D:1;D:N" (t0, Dt, data).
      5. Important: CS commands support exactly the data type supported by DIM. There is only one extension. CS command data may contain arrays of variable size, which are indicated by "T:N", where "T" is replaced by the data type (":N" is a fixed string). Arrays of variable size may be located at any position within the command data.
    2. Service data, used when publishing data via DIM or receiving service data (trendmsg, trendnot) via DIM. One must respect the data types supported by DIM.
      1. Publishing to DIM:
        • Type cast the data to "string" using the LabVIEW typecast VI.
        • Wire that string to the "dis_add_service" or "dis_update_service" VIs.
      2. Receiving data from DIM: Classes that inherited from the CAEObj (or a child) class
        • ... subscribe to DIM service using "trendmsg" or "trendnot" event definitions.
        • ... will receive the data in a raw data format ("CoreDefs.rawDataType.ctl"), which is just an array of unsigned bytes.
        • ... unpack the data to a less raw data format using the "CAEObj.unfold trend data.vi"
        • ... must decide what to do, if there is "no link" to the server publishing the data
        • ... must decide what to do, if the "type descriptor" does not match
        • ... in case, "no link" is false and "type descriptor" is correct, type cast the less raw data to the desired data type by using the LabVIEW typecast VI.
      3. Complex data types should be converted to simple data types. Example: All LabVIEW waveform data should be transferred as "D:1;D:1;D" (t0, Dt, data).
      4. Important: Only the last datum of a service may be an array of variable size. The description of such an array is "T", where "T" is the type of the data.
      5. In case of question: Refer to the documentation of DIM.
  5. Organization of VI files in the file system. All VIs and the lvlib of a class are located below one common folder CLASSNAME. It is no longer recommended to place public/protected/private methods in dedicated folders, as it was done with CS including version 3.00. Although no longer required due to the separate name space when using lvlibs, it is recommended to prefix the CLASSNAME to each VI name.
  6. Organization of class methods in the project manager.
    1. Each class should be represented by an individual library (lvlib)
    2. Each lvlib should contain three folders, "public", "protected", "private" and "inheritance". Optionally, one may use additional folders "typedefs" and "forFriendsOnly".
    3. "public"
      1. The access scope should be set to "public".
      2. Contains all public methods.
      3. Methods can be used by all classes or libraries. However, a public method of a class may only be used, if an object of that class is instantiated.
    4. "protected"
      1. The access scope should be set to "public".
      2. Contains all protected methods
      3. Strict Convention: Methods may only be used by THIS class and child classes.
    5. "private"
      1. The access scope should be set to "private".
      2. Contains all private methods.
      3. Private methods may only used by THIS class. Otherwise the code will not be executable.
    6. "inheritance"
      1. The access scope should be set to "public".
      2. Contains VIs needed for possible future inheritance.
    7. "typedefs"
      1. Contains strict typedef'd controls (ctl), that are needed to use the methods of the class.
      2. There is no strict recommendation on the access scope. In general, the "typedefs" folder is just a way to ease searching for ctls, that are are needed for using public methods. Typically, the access scope should be set to "public".
    8. "forFriendsOnly"
      1. The access scope should be set to "community".
      2. Contains "private" methods that may also be accessed by friend classes.
      3. Restricting the access to "forFriendsOnly" methods may be controlled by selecting the "Friends" ins project library properties of the class.
      4. For an example on "forFriendsOnly", have a look at the BaseProcess class.
  7. Other
    1. In case a class is child of BaseProcess class
      1. please use the Database and DSC-SharedVariable Tools to create a default database entry for the class
      2. export the database entry to an ini-file "CLASSNAME_db.ini"
      3. put the ini-file to the class folder.
    2. In case the database configuration of your class is more complex, create a "CLASSNAME_mapping.ini" file for your class. Refer to the Database and DSC-SharedVariable Tools for more details.
    3. In case your class requires using Shared Variables (as OPC Gateway or SCADA functionality), create a "CLASSNAME_SVTemplate.csv" file for your class. Refer to the Database and DSC-SharedVariable Tools for more details.
    4. In case the class is a (device) class of which objects are used via the "GOG", create an example "*.gog" file that contains the typical configuration of such an object. The "*.gog" file can be used as an example and imported into a GOG by the end users.
    5. Each class should provide a method "CLASSNAME.get library version.vi", that allows to retrieve its version during runtime. That method should be added to the "contents.vi" so that is can be called dynamically during runtime.
    6. Use menus for GUI objects (File->Close, Window->Open, Help->About...,...)
  8. For conventions about using colors and GUI design have a look here.

-- DietrichBeck - 18 Dec 2007
Topic revision: r23 - 2010-11-05, DietrichBeck
 
This site is powered by FoswikiCopyright © by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding GSI Wiki? Send feedback
Imprint (in German)
Privacy Policy (in German)