Locked History Attachments

DevelopmentGuide


Coding Style and Conventions

Next the general style used in the Fénix project is discussed. This includes:

  • naming conventions for classes and resources,
  • programming style for classes and methods,
  • IDE configuration to obey these rules,
  • and other conventions for common tasks.

Code formatting

The code formatting is done automatically by the IDE. This helps the developer in keeping the code formatted in an uniform way across the whole project. The IDE comes with several profiles, with different configurations, but the Fénix project is using it's own variation based on Sun's recommendations. See the profile discussion page for the current convention used and the discussion that led to it.

Just use Import in Eclipse preferences Java -> Code Style -> Formatter and select the file EclipseFenixCodeSyle.xml in fenix project root dir

The use of variables

Do not declare/allocate new variables at the beginning of a method: do it on a need basis near the place where they are used. Many variables don't get to be used, either because the code exists normally or due to an exception occurrence.

One thing you should do in the beginning of a method is to prepare your arguments for the rest of the code. Normalize them, filter them, prepare them as you wish.

Try initializing the variable with a well known initial value. Try to avoid initializations like:

   1 Integer foo = null;

Now, consider the following if-else-clause

   1 if (startIndex == null || startIndex.equals("")) {
   2     allValidPersons = filterPersons(persons, username, email, documentIdNumber, nameWords);
   3 } else {
   4     allValidPersons = getValidPersons(nameWords, persons);
   5 }

startIndex's value establishes a decision point in the code, but it is not used in the following methods. Although this is not wrong, it indicates that maybe the decision point should be clear and understandable, without any further reading of the code.

Part of the problem is startIndex having a name not easily related to the type o decision made. Declaring a self-explaining variable can help understanding the code without reading it twice.

   1 boolean usedFromManager = startIndex == null || startIndex.equals("");

The use of logs

Very often you need to print some message. Sometimes as usefull information and very often as debug. In Fénix development the common practice is to use the Log4J framework that is part of the Apache Logging Services.

When you need to log some message you first need do get access to a logger. To have a logger you can just declare a private static field in the class that needs logging.

   1 import org.apache.log4j.Logger;
   2 
   3 class MyClassThatNeedsLogging {
   4     private static final Logger logger = Logger.getLogger(MyClassThatNeedsLoggin.class);
   5 
   6     ...
   7 }

You can automate this by creating an Eclipse Java Editor Template. To do this choose "Window->Preferences->Java->Editor->Templates->New" and use the following pattern:

   1 private static final Logger logger = Logger.getLogger(${enclosing_type}.class);

Further advices on why and how use the logger see Dr. Printf presentation by GoncaloLuiz.


Respect the Architecture

In this section it is described some rules that must be followed to respect the architectural design of the project.

Reading persistent objects

Avoid using the usual persistent support handlers. With the new architecture features, it's possible to bring down the number of entry points to the database. It is much faster to dereference pointers than to read something from the database using the DAO's methods.


Performance Considerations

Premature optimization is the root of all evil...

--- Tony Hoare, Donald Knuth

Having this quote in mind, the following considerations serve as a guideline to how to develop performance oriented code when needed and how to avoid huge bottlenecks that are not perceptible locally, that is, by just looking to the written code.

General

Pay particular attention to iteration cycles: don't include inside them bits of code that should be performed only once.

Java 5.0 specific issues

Avoid as much as possible the boxing/unboxing of Java 5.0, using primitive types when best needed. There's no need of using an Integer object if we are to use it as an iterator in a for iteration, for instance.

Experts say that testing the length of a string is faster than an performing an equals comparison. Use string.length() == 0 instead of string.equals(""). And you can check this by looking into the source code.

Cutting to the chase

If you're having performance issues, don't bother guessing where the problem is. Use a profiling tool to hunt for the bottleneck. This will save you allot of time, and will help to keep your code clean (because you'll probably only need to optimize a tiny portion of the code).

The Fénix application is shipped with a built-in profiling filter that will log the time spent on each request. For this filter to be active all you have to do is to appropriately configure the following properties in your build.properties file:

log.profile.dir=/tmp
log.profile.filename=profileing.log

Analysing this data from your production application servers will give you a good starting point to finding bottlenecks in the applications code. Once you've located a request that takes an exaggerated amount of time to execute, you should run the request locally in a development environment using a complete profiling tool.

You can also consult the set of documented case studies of performance issues that is available.