Best Practices

Best Practices

 

Best Practices

·            Portability Considerations

·            Documentation

o   Minimum Documentation Requirements

·            Naming Conventions

o   Project/Bundle Names

o   Package Names

o   General Java Naming Best Practices

·            Error Handling

·            Optimization

·            Logging

o   Log Levels

o   Message Contents and Labels

 

 

Best Practices

ESF has been developed with certain “Best Practices” guidelines.  For developers writing their own implementations of ESF bundles, it is not required to use these guidelines, nor does Eurotech explicitly guarantee their consistent use throughout the framework. The guidelines are provided here to give developers some additional information into the goals, organization, and use of ESF.  (The following guidelines are based on “Best Practices,” last edited 2009-04-03 21:33:55 and are subject to change without notice.)

 

Portability Considerations

A major goal of ESF is portability.  Code should provide the same functionality across multiple operating systems, JVMs, and/or hardware architectures but should not require specific interface/implementation bundles to do so.  In most cases, interaction with specific operating systems, JVMs, and architectures can be minimal. 

 

For instance, when a method requires a system call, it should structure the call in reference to the operating system the code is running on.  The following code shows an example of setting an Ethernet IP address. 

 

if(os.equals("Linux")) {

      command = "ifconfig " + ip_interface + " " + ip_address + " netmask " + netmask;

} else if (os.equals("Windows XP")) {

      command = "netsh interface ipv4 set address" + " name=" + ip_interface + " source="

             + ip_type + " address=" + ip_address + " mask=" + netmask + " gateway=" + gateway;

} else {

      LogUtility.logError(LABEL + "Unsupported ESF operating system"); return false;

}

 

In the previous example, “os” is an instance of an ISystemManagerService.  This service is used to retrieve information about the operating system, JVM, and architecture that the code is running on.  This service is covered in Example 3 - System Manager Service.

 

Documentation

Minimum Documentation Requirements

·         All API bundles should be well documented using standard Javadoc practices.  See How to Write Doc Comments for the Javadoc Tool for recommended practices and conventions in Javadoc comments.

 

Naming Conventions

Project/Bundle Names

·         All Eurotech ESF bundles should start with com.esf.  Customer bundles should typically start with com.customername.

·         All Eurotech 'device' bundles (those bundles that abstractly define a device) should start with com.esf.device.

·         All API (interface) bundles should end in .service.

 

Package Names

·         Package names should generally reflect the Project Name they are in.  For example, the package com.esf.device.ethernet.service should be in a project called com.esf.device.ethernet.service.  The implementation class should generally be in a separate project called com.esf.device.ethernet and should be in the class com.esf.device.ethernet.  The implementation bundles activator should be in com.esf.device.ethernet.bundle.

 

General Java Naming Best Practices

·         Typical naming conventions for Java should be adhered to (see http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html).

 

Error Handling

As a general rule, Exceptions and Throwables should be used instead of return values to indicate a fault. Exceptions and Throwables are useful in that they provide much more information than a simple boolean or int can. If the method being written is fundamentally a void method, define it as such. Any errors generated in the method should be passed to the caller in the form of an Exception rather than a return code.

 

Optimization

Do not use the String '+' operator. Use the StringBuffer class instead.

 

Logging

Whenever significant events occur within code, a message should be logged using the IEsfLoggerService bundle.

 

Log Levels

Log Levels are use to differentiate between the different types of log messages that are received when ESF bundles are run. There are six log levels used:

 

      0 = LOG_LEVEL_NONE         (Set a process to this level if no messages are desired in the system log.)

      1 = LOG_LEVEL_ERROR        (Log something that didn’t work as expected.)

      2 = LOG_LEVEL_WARNING      (Log something that may or may not be a problem.)

      3 = LOG_LEVEL_INFO         (Informational messages, avoid verbose or frequent messages.)

      4 = LOG_LEVEL_DEBUG        (Verbose messages, for providing debugging information.)

      5 = LOG_LEVEL_DUMP         (Detailed dumps of data, such as a list of hex bytes from a serial data stream, etc.)

 

(Note that the Service Activator Toolkit, org.eclipse.soda.sat.core.util, supplies a different logging mechanism, LogUtility, that provides system-wide logging levels and is limited to ERROR, WARNING, INFO, and DEBUG).

 

Each bundle has its own private member controlling its log level. The log level for any bundle can be set dynamically during system operation using an API call, such as

 

      public void setLevel(int logLevel) throws Exception;

 

The following Java code makes use of logging functions during operation to provide status and debugging information.  Depending on what logging level this particular bundle is operating at, the logger service determines whether or not to include the message in the Equinox log file.  Log messages that are output at a level lower than the bundle’s current logLevel will be discarded.

 

      public void LogError(String message);

      public void LogWarning(String message);

      public void LogInfo(String message);

      public void LogDebug(String message);

 

The log level for a bundle can be set as a command line argument dynamically in the OSGi command console, or the log level for a bundle (or all bundles) can be obtained using the following commands.

 

      setesfloglevel [bundle_id] [log_level]

      getesfloglevel [bundle_id]

      getesfloglevel

 

Message Contents and Labels

A log message should be short, informative, and start with a label corresponding to the package and class where the log was executed.  If lengthy iterative processes are used to extract logDebug messages (such as a string of byte values in a communications message), the code should probably check that its own logLevel is set to logDebug before spending the system resources building up the debug message.

 

Labels are private, static, final strings associated with every class. Labels are used to keep track of the location of log messages. The use of labels is mandatory and is a vital aspect in keeping logging messages consistent across ESF. A label should be the first variable that is created within a class and should always contain the full package name as well as the class name. For a class called Example in a package called com.esf.example, the label declaration would be

 

private static final String LABEL = "com.esf.example.Example: ";