Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
0% found this document useful (0 votes)
140 views

Java Coding Standards

Uploaded by

venkateshdorai
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
140 views

Java Coding Standards

Uploaded by

venkateshdorai
Copyright
© Attribution Non-Commercial (BY-NC)
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 27

Table of Contents

REVISION HISTORY................................................................................................................... 2
1 SCOPE.............................................................................................................................. 3
2 ECLIPSE PREFERENCE CONFIG FILES........................................................................4
3 JDK FEATURES............................................................................................................... 5
4 SOURCE CODE STRUCTURE......................................................................................... 6
4.1 JAVA SOURCE FILES........................................................................................................ 6
5 NAMING............................................................................................................................ 7
5.1 INTERFACE/CLASS NAMES................................................................................................ 7
5.2 METHOD NAMES.............................................................................................................. 7
5.3 INSTANCE VARIABLE NAMES............................................................................................. 8
6 STATEMENTS................................................................................................................... 9
6.1 SIMPLE STATEMENTS....................................................................................................... 9
6.2 COMPOUND STATEMENTS................................................................................................ 9
6.3 IF, IF-ELSE, IF ELSE-IF ELSE STATEMENTS.........................................................................9
6.4 WHILE STATEMENTS....................................................................................................... 10
6.5 SWITCH STATEMENTS..................................................................................................... 10
6.6 TRY-CATCH STATEMENTS............................................................................................... 11

7 DOCUMENTATION AND COMMENTING.......................................................................12


7.1 TAG COMMENTS............................................................................................................ 13
8 PROGRAMMING PRACTICES.......................................................................................16
8.1 CREATING AND DESTROYING OBJECTS...........................................................................16
8.2 METHODS COMMON TO ALL OBJECTS.............................................................................18
8.3 GENERAL PROGRAMMING...............................................................................................18
8.4 EXCEPTIONS.................................................................................................................. 22
9 TOOL TO FIND BUGS – FINDBUGS..............................................................................23
9.1 STEPS TO CONFIGURE IN ECLIPSE..................................................................................23
10 Unit Testing (EasyMock)............................................................................................... 24

Last Updated: 26/11/2009 12:00:00 PM Page 1


Revision History
Version Date Author(s) Change Description
1.0 21-Sep- Prashant Initial Draft
2009 Neginahal
1.1 29-Oct-2009 Vishal Revankar Revised version

Last Updated: 26/11/2009 12:00:00 PM Page 2


1 Scope
This document provides a set of important guidelines for programming in Java which are
intended to improve overall quality and maintainability of software developed for WCP program.
It presents the Rules and Recommendations about the use of language constructs of Java.

This document in principle a reference document and readers are expected to be Java
programmers.

Last Updated: 26/11/2009 12:00:00 PM Page 3


2 Eclipse Preference Config Files
Most of the below explained Rules and Recommendations are configured in Eclipse
Preferences and exported configuration is shown below. All Java developers should apply
these config files to there workspaces before development.

How to Apply:

Go to WindowsPreferences
Select Java  Code Style Clean Up. Click on Import and select below
cleanup_gynymede.xml.

D:\Tech\Java\coding
standards\cleanup_gynymede.xml

Go to WindowsPreferences
Select Java  Code Style Code Templates. Click on Import and select below
codetemplates_gynymede.xml.

D:\Tech\Java\coding
standards\codetemplate_gynymede.xml

Go to WindowsPreferences
Select Java  Code Style Formatter. Click on Import and select below
formatter_gynymede.xml.

D:\Tech\Java\coding
standards\formatter_gynymede.xml

Alternately, the entire Eclipse Preferences can be applied as below. Note that this might
override the pre-configured local Preferences configurations but, includes other Editor  Save
Changes configurations which are helpful during development.

Go to File  Import. Select General Prefences and browse below preference file.

D:\Tech\Java\coding
standards\eclipse preference.epf

Last Updated: 26/11/2009 12:00:00 PM Page 4


3 JDK Features
The latest JDK features should be used during development.
http://java.sun.com/j2se/1.5.0/docs/relnotes/features.html

Last Updated: 26/11/2009 12:00:00 PM Page 5


4 Source Code Structure
Uniform source code structure and formatting are fundamental for an adequate collaboration
between programmers. The rules and recommendations in this chapter define a consistent
code formatting style to be applied during development.

4.1 Java Source Files


Rule: Use the following structure for all implementation files
 Start with the beginning comment which includes Copyright information.
 Follow with package and import statements.
 Put class and interface definitions at the end of the file.

Rule: Do not use the wildcard (“*”) notation in import statements

Rule: Use the following order to declare members of a class


 Class variables (declared static).
 Instance variables.
 Constructors.
 finalize method (destructor) if necessary.
 Class methods (declared static).
 Methods.
 set/get
Additionally, inside each one of these groups, declare members with a higher visibility first. That
is, start with public members, continue with package visible members (not qualified), move to
protected members, and end with private members.

Rule: When indenting the code inside declaration and control structures, always use four
additional spaces with respect to the previous level.

Rule: Avoid lines longer than 80 characters.

Rule: Leave two blank lines between sections of a source file.

Rule: Leave one blank line:


 Between methods.
 Between the local variable definitions in a method or compound statement and its first
statement.

Recommendation: Separate the groups of statements in a method using single blank lines

Last Updated: 26/11/2009 12:00:00 PM Page 6


5 Naming
This chapter is concerned with standards of naming within Java source code.

Rule: Use American English for naming variables.

Rule: Restrict variables to the ASCII character set.


Files containing non-ASCII identifiers may not display properly in some platforms and may be
hard to edit properly.

Recommendation: Avoid long (e.g. more than 20 characters) identifiers.

Recommendation: Use abbreviations sparingly and consistently.


Although abbreviating words in identifiers should be generally avoided, it is sometimes
necessary to do it in order to prevent identifiers from becoming excessively long. In such a
case, ensure that the same abbreviation is always used for the same term.

5.1 Interface/Class Names


Rule: Use nouns or adjectives when naming interfaces.
Use nouns to name interfaces that act as service declarations. Use adjectives to name
interfaces that act as descriptions of capabilities.

Example:
An interface declaring a service:
public interface ActionListener
{

}

Interfaces declaring object capabilities:


public interface Runnable
{
….
}

Rule: Use nouns when naming classes. The implemented classes should have name according
to <interface name>Impl format.

Example: ActionListenerImpl

Rule: Pluralize the names of classes that group related attributes, static services or constants.
Example:
PolicyOperations
PageRanges

5.2 Method Names


Rule: Use verbs to name methods. Use lower-case for the first word and capitalize only the first
letter of each subsequent word that appears in a method name.

Example
insertElement()

Last Updated: 26/11/2009 12:00:00 PM Page 7


computeTime()
save()

TODO: Standardise the verbs used for business operations. For example, updateEmployee Vs.
EditEmployee and computeSalary Vs. calculateSalary.

5.3 Instance Variable Names


Rule: Use nouns to name variables and attributes.

Rule: Qualify instance variable references with ‘this’ to distinguish them from local variables.

Example

public class Employee{


private String name;

public String getName(){

return this.name; // Correct


return name // Wrong!

}
}

Rule: Use upper-case letters for each word and separate each pair of words with an underscore
when naming Java constants.

Example
CUSTOMERS_COUNT

Last Updated: 26/11/2009 12:00:00 PM Page 8


6 Statements

6.1 Simple Statements


Rule: Put single variable definitions in separate lines.

Example
Instead of writing,
int counter, total; // Wrong!
write
int counter;
int total;

Rule: Put single statements in separate lines.

Example
Instead of writing
counter = initial; counter++; // Wrong!
write
counter = initial;
counter++;

6.2 Compound Statements


Compound statements are statements that contain lists of statements enclosed in braces
"{ statements }". See the following sections for examples.

Rule: The enclosed statements should be indented one more level than the compound
statement.

6.3 if, if-else, if else-if else Statements


The if-else class of statements should have the following form. Each condition should be
documented.

if (condition)
{
statements;
} //end if

if (condition)
{
statements;
}
else
{
statements;
} //end else if

if (condition)
{
statements;

Last Updated: 26/11/2009 12:00:00 PM Page 9


} else if (condition)
{
statements;
}
else
{
statements;
} //end else if

Recommendation: if statements always use braces {}. Avoid the following error-prone form:

if (condition) //AVOID! THIS OMITS THE BRACES {}!


statement;

6.4 while Statements


A while statement should have the following form:

while (condition)
{
statements;
}

An empty while statement should have the following form with documentation.

while (condition);

6.5 switch Statements


A switch statement should have the following form:

switch (condition)
{
case ABC:
statements;
/* falls through */

case DEF:
statements;
break;

case XYZ:
statements;
break;

default:
statements;
break;
}

Rule: Every time a case falls through (doesn't include a break statement), add a comment
where the break statement would normally be. This is shown in the preceding code example
with the /* falls through */ comment.

Last Updated: 26/11/2009 12:00:00 PM Page 10


Rule: Every switch statement should include a default case. The break in the default case is
redundant, but it prevents a fall-through error if later another case is added.

6.6 try-catch Statements


A try-catch statement should have the following format:

try
{
statements;
}
catch (ExceptionClass e)
{
statements;
} //end try catch

A try-catch statement may also be followed by finally, which executes regardless of whether or
not the try block has completed successfully.

try
{
statements;
}
catch (ExceptionClass e)
{
statements;
} finally
{
statements;
} // end finally

Last Updated: 26/11/2009 12:00:00 PM Page 11


7 Documentation and Commenting
The rules and recommendations in this chapter are concerned with how to write appropriate
source level documentation for Java in such a way that the Javadoc tool can produce high
quality reference documentation from them.

Rule: Document public, protected, package, and private members.

Rule: In documentation, below keywords and names should be used within code>...</code>
tags.

 Java keywords
 package names
 class names
 method names
 interface names
 field names
 argument names
 code examples

The <code> ... </code> tags tell HTML browsers to render the content in a style different from
that of normal text, so that these elements will stand out.

Example:
/**
* This can take <code>null </null> values
*/

Rule: Wrap full code examples appearing in documentation comments with <pre> ... </pre>
tags.
The <pre> ...</pre> tags are used to tell HTML browsers to retain the original formatting,
including indentation and line ends, of the “preformatted” element.

Example:
/**<pre> {
* Integer n = numbers.get("two");
* if (n != null) {
* System.out.println("two = " + n);
* }}</pre>
*/

Rule: It is encouraged to add links for API names using the @link tag.

Rule: Add description beyond the API name.


The best API names are "self-documenting", meaning they tell you basically what the API does.
If the doc comment merely repeats the API name in sentence form, it is not providing more
information. For example, if method description uses only the words that appear in the method
name, then it is adding nothing at all to what you could infer. The ideal comment goes beyond
those words and should always reward you with some bit of information that was not
immediately obvious from the API name.

Last Updated: 26/11/2009 12:00:00 PM Page 12


Avoid - The description below says nothing beyond what you know from reading the method
name. The words "set", "tool", "tip", and "text" are simply repeated in a sentence.

/**
* Sets the tool tip text.
*
* @param text The text of the tool tip.
*/
public void setToolTipText(String text) {…}

Preferred - This description more completely defines what a tool tip is, in the larger
context of registering and being displayed in response to the cursor.

/**
* Registers the text to display in a tool tip. The
* text displays when the cursor lingers over the
* component.
*
* @param text The string to display. If the text
* is null, the tool tip is turned off for this
* component.
*/
public void setToolTipText(String text) {

7.1 Tag Comments


Use the following Rules to create comments for each tag:
@author
If the author is unknown, use "unascribed" as the argument to @author.
@param
Parameter names are lowercase by convention. The data type starts with a lowercase letter
to indicate an object rather than a class. The description is most usually a phrase, starting
with a lowercase letter and ending without a period, unless it contains a complete sentence or
is followed by another sentence (as described further below).

When writing the comments themselves:


 Prefer a phrase to a sentence.
 Giving a phrase, do not capitalize, do not end with a period.
@param x a phrase goes here
 Giving a sentence, capitalize it and end it with a period.
@param x This is a sentence.
 When giving multiple sentences, follow all sentence rules.
@param x This is sentence #1. This is sentence #2.
 Giving multiple phrases, separate with a semi-colon and a space.
@param x phrase #1 here; phrase #2 here

Last Updated: 26/11/2009 12:00:00 PM Page 13


 Giving a phrase followed by a sentence, do not capitalize the phrase.
However, end it with a period to distinguish the start of the next sentence.
@param x a phrase goes here. This is a sentence.
@return
Omit @return for methods that return void and for constructors; include it for all other
methods, even if its content is entirely redundant with the method description. Having an
explicit @return tag makes it easier for someone to find the return value quickly. Whenever
possible, supply return values for special cases (such as specifying the value returned when
an out-of-bounds argument is supplied).

@deprecated
The @deprecated description in the first sentence should at least tell the user when the API
was deprecated and what to use as a replacement. Only the first sentence will appear in the
summary section and index. Subsequent sentences can also explain why it has been
deprecated. When generating the description for a deprecated API, the Javadoc tool moves
the @deprecated text ahead of the description, placing it in italics and preceding it with a bold
warning: "Deprecated". An @see should be included that points to the replacement method:
 The standard format is to create a pair of @deprecated and @see tags.
For example:
/**
* @deprecated As of JDK 1.1, replaced by setBounds
* @see #setBounds(int,int,int,int)
*/
If the member has no replacement, the argument to @deprecated should be "No
replacement".
@since
Specify the product version when the Java name was added to the API specification
(if different from the implementation). For example, if a package, class, interface or
member was added to the WCP at SR1 add :
/**
* @since SR1
*/

@exception
An @exception tag should be included for any checked exceptions (declared in the throws
clause), as illustrated below, and for any unchecked exceptions that the caller might
reasonably want to catch, with the exception of NullPointerException. Errors should not be
documented, as they are unpredictable.

/**
* @exception IOException If an input or output exception
* occurred
*/
public void f() throws IOException {
// body
}

Rule: Label empty statements.


Empty blocks may be confusing for programmers trying to understand the code. Making them
explicit helps to prevent such confusion.

Last Updated: 26/11/2009 12:00:00 PM Page 14


Rule: Use end-line comments to explicitly mark the logical ends of conditionals loops,
exceptions, enumerations, methods or classes.

The end-line comments must have the format


// end <keyword>

Example
If{

} // end if

TODO: If required we need to create custom tags to indicate product versions at each source
files.

Last Updated: 26/11/2009 12:00:00 PM Page 15


8 Programming Practices

8.1 Creating and Destroying Objects

Recommendation: Consider static factory methods instead of constructors

i) One advantage of static factory methods is that, unlike constructors, they have names.
ii) A second advantage of static factory methods is that, unlike constructors, they are not
required to create a new object each time they’re invoked.
iii) A third advantage of static factory methods is that, unlike constructors, they can return
an object of any subtype of their return type.
Disadvantages
Cannot be sub classed.

Recommendation: Consider a builder when faced with many constructor parameters

The Builder pattern is a good choice when designing classes whose constructors or static
factories would have more than a handful of parameters, especially if most of those
parameters are optional. Client code is much easier to read and write with builders than
with the traditional telescoping constructor pattern, and builders are much safer than
JavaBeans.

// Builder Pattern
public class NutritionFacts {
private final int servingSize;
private final int servings;
private final int calories;
private final int fat;
private final int sodium;
private final int carbohydrate;

public static class Builder {


// Required parameters
private final int servingSize;
private final int servings;
// Optional parameters - initialized to default
private int calories = 0;
private int fat = 0;
private int carbohydrate = 0;
private int sodium = 0;
public Builder(int servingSize, int servings) {
this.servingSize = servingSize;
this.servings = servings;
}
public Builder calories(int val) {
calories = val;
return this;
}
public Builder fat(int val) {
fat = val;
return this;
}

Last Updated: 26/11/2009 12:00:00 PM Page 16


public Builder carbohydrate(int val) {
carbohydrate = val;
return this;
}
public Builder sodium(int val) {
sodium = val;
return this;
}
public NutritionFacts build() {
return new NutritionFacts(this);
}
}
private NutritionFacts(Builder builder) {
servingSize = builder.servingSize;
servings = builder.servings;
calories = builder.calories;
fat = builder.fat;
sodium = builder.sodium;
carbohydrate = builder.carbohydrate;
}
}

NutritionFacts cocaCola = new NutritionFacts.Builder(240, 8).


calories(100).sodium(35).carbohydrate(27).build();

Rule: Enforce the singleton property with a private constructor or an enum type.

Rule: Enforce noninstantiability with a private constructor.

Occasionally you’ll want to write a class that is just a grouping of static methods and static
fields. Such utility classes were not designed to be instantiated: an instance would be
nonsensical.
In the absence of explicit constructors, however, the compiler provides a public, parameter
less default constructor. So explicitly implement a private constructor.

Rule: Avoid creating unnecessary objects.

It is often appropriate to reuse a single object instead of creating a new functionally


equivalent object each time it is needed. Reuse can be both faster and more stylish.
String s = new String("Vishal"); //avoid
Boolean flag = new Boolean("true"); //avoid

Rule: Eliminate obsolete object references.

Holding onto obsolete references constitutes memory leaks in Java. This means that as
programmers, it is our prime responsibility to not hold onto references that are obsolete.
Object result = elements[--size];
elements[size] = null;

Last Updated: 26/11/2009 12:00:00 PM Page 17


8.2 Methods Common to All Objects

Rule: Always override hashCode when you override equals.

A common source of bugs is the failure to override the hashCode method. You must override
hashCode in every class that overrides equals. Failure to do so will result in a violation of the
general contract for Object.hashCode, which will prevent your class from functioning properly in
conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
If two objects are equal according to the equals(Object) method, then calling the hashCode
method on each of the two objects must produce the same integer result. Failure to follow this
contract is a common source of bugs.

Recommendation: Always override toString.

It would be of great value for logging purposes to override the toString method on objects that
frequently appear in logging statements. A rich toString method would allow clean debugging
statements

8.3 General Programming

Recommendation: Minimize the scope of local variables


i. The most powerful technique for minimizing the scope of a local variable is to declare it
where it is first used.
ii. Prefer for loops to while loops, assuming the contents of the loop variable aren’t needed
after the loop terminates.

Iterator<Element> i = c.iterator();
while (i.hasNext()) {
doSomething(i.next());
}
...
Iterator<Element> i2 = c2.iterator();
while (i.hasNext()) { // BUG!
doSomethingElse(i2.next());
}

The second loop contains a cut-and-paste error:


for (Iterator<Element> i = c.iterator(); i.hasNext(); ) {
doSomething(i.next());
}
...
// Compile-time error - cannot find symbol i
for (Iterator<Element> i2 = c2.iterator(); i.hasNext(); ) {
doSomething(i2.next());
}
iii. Here is another loop idiom that minimizes the scope of local variables:

for (int i = 0, n = expensiveComputation(); i < n; i++) {


doSomething(i);
}

Last Updated: 26/11/2009 12:00:00 PM Page 18


Recommendation: Prefer for-each loops to traditional for loops
i. Prior to release 1.5, this was the preferred idiom for iterating over a collection:

// No longer the preferred idiom to iterate over a collection!


for (Iterator i = c.iterator(); i.hasNext(); ) {
doSomething((Element) i.next()); // (No generics before 1.5)
}

This was the preferred idiom for iterating over an array:

// No longer the preferred idiom to iterate over an array!


for (int i = 0; i < a.length; i++) {
doSomething(a[i]);
}

The iterator and the index variable occur three times in each loop, which gives you two
chances to get them wrong. If you do, there is no guarantee that the compiler will catch the
problem.

The for-each loop, introduced in release 1.5, gets rid of the clutter and the opportunity for
error by hiding the iterator or index variable completely. The resulting idiom applies equally to
collections and arrays:

// The preferred idiom for iterating over collections and arrays


for (Element e : elements) {
doSomething(e);
}

When you see the colon (:), read it as “in.” Thus, the loop above reads as “for each
element e in elements.”

ii. The advantages of the for-each loop over the traditional for loop are even greater when it
comes to nested iteration over multiple collections. Here is a common mistake that
people make when they try to do nested iteration over two collections:

// Can you spot the bug?


enum Suit { CLUB, DIAMOND, HEART, SPADE }
enum Rank { ACE, DEUCE, THREE, FOUR, FIVE, SIX, SEVEN, EIGHT,
NINE, TEN, JACK, QUEEN, KING }
...
Collection<Suit> suits = Arrays.asList(Suit.values());
Collection<Rank> ranks = Arrays.asList(Rank.values());
List<Card> deck = new ArrayList<Card>();
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); )
for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
deck.add(new Card(i.next(), j.next()));

Last Updated: 26/11/2009 12:00:00 PM Page 19


// Fixed, but ugly - you can do better!
for (Iterator<Suit> i = suits.iterator(); i.hasNext(); ) {
Suit suit = i.next();
for (Iterator<Rank> j = ranks.iterator(); j.hasNext(); )
deck.add(new Card(suit, j.next()));
}

// Preferred idiom for nested iteration on collections and


arrays
for (Suit suit : suits)
for (Rank rank : ranks)
deck.add(new Card(suit, rank));

iii. Not only does the for-each loop let you iterate over collections and arrays, it lets you
iterate over any object that implements the Iterable interface. This simple interface, which
consists of a single method, was added to the platform at the same time as the for-each
loop.
iv. The for-each loop provides compelling advantages over the traditional for loop in clarity
and bug prevention, with no performance penalty. You should use it wherever you can.
Unfortunately, there are three common situations where you can’t use a for-each loop:
1. Filtering—If you need to traverse a collection and remove selected elements,
then you need to use an explicit iterator so that you can call its remove method.
2. Transforming—If you need to traverse a list or array and replace some or all of
the values of its elements, then you need the list iterator or array index in order to
set the value of an element.
3. Parallel iteration—If you need to traverse multiple collections in parallel, then
you need explicit control over the iterator or index variable, so that all iterators or
index variables can be advanced in lockstep

Rule: Avoid float and double if exact answers are required


i. The float and double types are particularly ill-suited for monetary calculations because it
is impossible to represent 0.1 (or any other negative power of ten) as a float or double
exactly.
For example,
System.out.println(1.03 - .42);

Unfortunately, it prints out 0.6100000000000001.

System.out.println(1.00 - 9 * .10);

According to this program fragment, you get is $0.09999999999999998.

ii. Don’t use float or double for any calculations that require an exact answer. Use
BigDecimal if you want the system to keep track of the decimal point and you don’t mind
the inconvenience and cost of not using a primitive type.

Recommendation: Beware the performance of string concatenation

Using the string concatenation (+) operator repeatedly to concatenate n strings requires time
quadratic in n.

Last Updated: 26/11/2009 12:00:00 PM Page 20


// Inappropriate use of string concatenation - Performs
horribly!
public String statement() {
String result = "";
for (int i = 0; i < numItems(); i++)
result += lineForItem(i); // String concatenation
return result;
}

To achieve acceptable performance, use a StringBuilder in place of a String to store the


statement under construction. (The StringBuilder class, added in release 1.5, is an
unsynchronized replacement for StringBuffer, which is now obsolete.).

public String statement() {


StringBuilder b = new StringBuilder(numItems() * LINE_WIDTH);
for (int i = 0; i < numItems(); i++)
b.append(lineForItem(i));
return b.toString();
}
Note that the second method pre-allocates a StringBuilder large enough to hold the result. Even
if it is detuned to use a default-sized StringBuilder, it is still fifty times faster.

Don’t use the string concatenation operator to combine more than a few strings unless
performance is irrelevant. Use StringBuilder’s append method instead.

Recommendation: Refer to objects by their interfaces

If appropriate interface types exist, then parameters, return values, variables, and fields should
all be declared using interface types.

// Good - uses interface as type


List<Subscriber> subscribers = new Vector<Subscriber>();
rather than this:
// Bad - uses class as type!
Vector<Subscriber> subscribers = new Vector<Subscriber>();

If you get into the habit of using interfaces as types, your program will be much more flexible. If
you decide that you want to switch implementations, all you have to do is change the class
name in the constructor (or use a different static factory).

For example, the first declaration could be changed to read

List<Subscriber> subscribers = new ArrayList<Subscriber>();

and all of the surrounding code would continue to work. The surrounding code was unaware of
the old implementation type, so it would be oblivious to the change.
If you use the interface to refer to the object; your program will be more flexible.

Last Updated: 26/11/2009 12:00:00 PM Page 21


8.4 Exceptions

Rule: Use checked exceptions for recoverable conditions and runtime exceptions for
programming errors
The Java programming language provides three kinds of throwables: checked exceptions,
runtime exceptions, and errors.
i. Use checked exceptions for conditions from which the caller can reasonably be expected
to recover.
For example, suppose a checked exception is thrown when an attempt to make a
purchase with a gift card fails because the card doesn’t have enough money left
on it. The exception should provide an accessor method to query the amount of
the shortfall, so the amount can be relayed to the shopper.

ii. Use runtime exceptions to indicate programming errors. The great majority of runtime
exceptions indicate precondition violations.
For example, the contract for array access specifies that the array index must be
between zero and the array length minus one. ArrayIndexOutOfBoundsException
indicates that this precondition was violated.
iii. If it isn’t clear whether recovery is possible, you’re probably better off using an unchecked
exception.

Rule: Don’t ignore exceptions

While this advice may seem obvious, it is violated often enough that it bears repeating.
When the designers of an API declare a method to throw an exception, they are trying to tell
you something. Don’t ignore it! It is easy to ignore exceptions by surrounding a method
invocation with a try statement with an empty catch block:

// Empty catch block ignores exception - Highly suspect!


try {
...
} catch (SomeException e) {
}

An empty catch block defeats the purpose of exceptions, which is to force you to handle
exceptional conditions.

At the very least, the catch block should contain a comment explaining why it is appropriate to
ignore the exception.

Last Updated: 26/11/2009 12:00:00 PM Page 22


9 Tool to find Bugs – FindBugs
It is a program which uses static analysis to look for bugs in Java code. It uses class or JAR
files looking for potential problems by matching the bytecodes against a list of bug patterns.

9.1 Steps to configure in Eclipse


1. Update the Eclipse with plug-in http://findbugs.cs.umd.edu/eclipse/
2. After development is completed, run the FindBugs to make sure there is no high priority
defects reported.

TODO: How to customize FindBugs in Eclipse i.e. should we enable automatic check etc.

Last Updated: 26/11/2009 12:00:00 PM Page 23


10 Unit Testing (EasyMock)
Before we begin development, we will develop our test. Tests are structured by grouping
methods that perform a test together in a test case. A test case is a class that extends
junit.framework.TestCase. So in this case, we will begin by developing the test case for
LoginService. To start, in your test directory, create a new class named LoginServiceTest and
make it extend junit.framework.TestCase.

The lifecycle of a test execution consists of three main methods:


 public void setUp()
setUp is executed before each of the test. It is used to perform any setup required before
the execution of your test. Your implementation will override the default empty
implementation in TestCase.
 public void testSomething()
testSomething is the actual test method. You may have many of these within a single test
case. Each one will be executed by your test runner and all errors will be reported at the
end.
 public void tearDown()
tearDown is executed after each test method. It is used to perform any cleanup required
after your tests.

So to begin flushing out our test case, we'll start with the setUp method. In this method, we'll
instantiate an instance of the service to be tested. We'll also create our first mock object,
UserDAO. You can see the source of our test below.

import junit.framework.TestCase;
import static org.easymock.EasyMock.createStrictMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.easymock.EasyMock.eq;
/**
* Test case for LoginService.
*/
public class LoginServiceTest extends TestCase{

private LoginServiceImpl service;


private UserDAO mockDao;

/**
* setUp overrides the default, empty implementation provided by
* JUnit's TestCase. We will use it to instantiate our required
* objects so that we get a clean copy for each test.

Last Updated: 26/11/2009 12:00:00 PM Page 24


*/
@Override
public void setUp() {
service = new LoginServiceImpl();
mockDao = createStrictMock(UserDAO.class);
service.setUserDAO(mockDao);
}
}
EasyMock works by implementing the proxy pattern. When you create a mock object, it creates
a proxy object that takes the place of the real object. The proxy object gets it's definition from
the interface you pass when creating the mock. We will define what methods are called and
their returns from within our test method itself.

When creating a mock object, there are two types, a mock and a strict mock. In either case, our
test will tell the mock object what method calls to expect and what to return when they occur. A
basic mock will not care about the order of the execution of the methods. A strict mock, on the
other hand, is order specific. Your test will fail if the methods are executed out of order on a
strict mock. In this example, we will be using a strict mock.

The next step is to create our actual test method (for reference, we will not be implementing a
tearDown method for this test case, it won't be needed in this example). In our test method, we
want to test the following scenario:

Even with the very basic method we want to test above, there are still a number of different
scenarios that require tests. We will start with the "rosy" scenario, passing in two values and
getting a user object back. Below is the source of what will be our new test method.

...
/**
* This method will test the "rosy" scenario of passing a valid
* username and password and retrieveing the user. Once the user
* is returned to the service, the service will return true to
* the caller.
*/
public void testRosyScenario() {
User results = new User();
String userName = "testUserName";
String password = "testPassword";

Last Updated: 26/11/2009 12:00:00 PM Page 25


expect(mockDao.loadByUsernameAndPassword(userName,
password)))
.andReturn(results);

replay(mockDao);
assertTrue(service.login(userName, password));
verify(mockDao);
}
...

So let's go thru the code above. First, we create the expected result of our DAO call, results. In
this case, our method will just check to see if an object was returned, so we don't need to
populate our user object with anything, we just need an empty instance. Next we declare the
values we will be passing into our service call. The password hash may catch you off guard. It's
considered unsafe to store passwords as plain text so our service will generate an MD5 hash of
the password and that value is the value that we will pass to our DAO.

The next line is a very important line in our test that alot happens, so let's walk thru it step by
step:

1. expect(mockDao.loadByUsernameAndPassword(userName,password)
This is a call to the static method EasyMock.expect. It tells your mock object to expect
the method loadByUsernameAndPassword to be called with the arguments.
2. .andReturn(results);
This tells our mock object what to return after this method is called.

The final three lines are the ones that do the testing work. replay(mockDao); tells EasyMock
"We're done declaring our expectations. It's now time to run what we told you".
assertTrue(service.login(userName, password)); does two things: executes the code to be
tested and tests that the result is true. If it is false, the test will fail. Finally, verify(mockDao); tells
EasyMock to validate that all of the expected method calls were executed and in the correct
order.

So that's it for the test. Now all we have to do is write the code to make it pass. You can find
that below.

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class LoginServiceImpl implements LoginService {

private UserDAO userDao;

public void setUserDAO(UserDAO userDao) {


this.userDao = userDao;
}

@Override
public boolean login(String userName, String password) {

Last Updated: 26/11/2009 12:00:00 PM Page 26


boolean valid = false;
User results =
userDao.loadByUsernameAndPassword(userName,
password);
if(results != null) {
valid = true;
}

return valid;
}
}

Last Updated: 26/11/2009 12:00:00 PM Page 27

You might also like