0% found this document useful (0 votes)
5 views

2015 - JAVA Coding Best Practices

Uploaded by

Trường Trần
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views

2015 - JAVA Coding Best Practices

Uploaded by

Trường Trần
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 39

JAVA Coding Best

Practices
Coding Best Practices

I. Table of Contents
I. Table of Contents......................................................................................................2
IV. Abbreviations............................................................................................................3
1 Performance..............................................................................................................3
1.1 Object initialization......................................................................................................3
1.1.1 Use StringBuffer (Java) or StringBuilder (C#).............................................................3
1.2 Collection usage..........................................................................................................3
1.2.1 Avoid using Hashtable and Vector..............................................................................3
1.2.2 Use Iterator instead of indexing for loop.....................................................................3
1.2.3 List to array.................................................................................................................3
1.2.4 Arrays.asList(...)..........................................................................................................3
2 Resources management...........................................................................................3
2.1 Resources allocation...................................................................................................3
2.1.1 Use lazy initialization in memory-extensive applications............................................3
2.1.2 Initialize size of collection type....................................................................................3
2.1.3 Should declare local variable just before use..............................................................3
2.2 Resources de-allocation..............................................................................................3
2.2.1 Must not forget to close the stream.............................................................................3
3 Integrity......................................................................................................................3
3.1 Object initialization......................................................................................................3
3.1.1 Use double checked locking when lazy-initializing object in threaded context where
resource is shared.......................................................................................................3
3.2 Comparing objects......................................................................................................3
3.2.1 Comparing two objects ( “==” instead of “.equals”).....................................................3
4 Design related...........................................................................................................3
4.1 Design - OOP..............................................................................................................3
4.1.1 OOP - Encapsulation: declare a data member is public.............................................3
4.1.2 OOP - Encapsulation: Do not make visible things that should not be visible..............3
4.1.3 OOP - Use inner class in order to avoid using member attributes..............................3
4.1.4 OOP – Isolation between technical handlings and business handlings......................3
4.1.5 OOP - Isolation between independent businesses.....................................................3
4.1.6 OOP - Isolation between systems...............................................................................3
4.1.7 OOP - Isolation between the generic algorithm and detail implementation................3
4.1.8 Information expert, correct responsibility....................................................................3
4.1.9 Getter/Setter vs. Overriding........................................................................................3
4.1.10 Decouple with real-implementation / coding to interface............................................3
4.2 Others.........................................................................................................................3
4.2.1 The interface java.io.Serializable must be understood properly.................................3
5 Code Maintenance....................................................................................................3
5.1 Object initialization......................................................................................................3
5.1.1 Declare private constructor for Helper, Utility classes................................................3
5.1.2 Declare constants in classes instead of interfaces.....................................................3
5.2 Maintainability.............................................................................................................3
5.2.1 Avoid using instanceof method...................................................................................3
5.2.2 Return empty list, array in public methods..................................................................3

2 / 39
Coding Best Practices

5.2.3 Do not use Assertion in place of business checking...................................................3


5.2.4 Comparing enum type.................................................................................................3
5.2.5 Must not forget to put try..catch in finally.....................................................................3
5.2.6 The class and method naming must be clear.............................................................3
5.2.7 Documentation: comments in the source code...........................................................3
5.2.8 Use the constants, do not hard-code the value..........................................................3
5.2.9 Do not copy / paste the code or comments.................................................................3
5.2.10 The constants and configurable parameters are different..........................................3
6 Code reliability..........................................................................................................3
6.1 Exception handling......................................................................................................3
6.1.1 Never leave a empty catch block................................................................................3
6.1.2 Be specific in throw clause..........................................................................................3
6.1.3 Pass pertinent data to exception.................................................................................3
7 Miscellaneous............................................................................................................3
7.1 Reuse existing components........................................................................................3
7.1.1 Do not try to create home-built service, or re-invent things........................................3
7.1.2 Sorting.........................................................................................................................3
7.2 Problem solving...........................................................................................................3
7.2.1 You have a PROBLEM...............................................................................................3

IV. Abbreviations
DB Database
DTO Data Transfer Object
OOP Object Oriented Programming
PROD Production

3 / 39
Coding Best Practices

1 Performance

1.1 Object initialization

1.1.1 Use StringBuffer (Java) or StringBuilder (C#)

Problem Use StringBuffer (Java) or StringBuilder (C#)

Type Performance / Object initialization - Java


Bad code / String result = “”;
behavior while (iter.hasNext()){
result += (String)iter.next();
}
return result;

Description Operation on String (immutable) objects creates a lot of short-live


objects.
StringBuffer in java or StringBuilder in C# provide an alternative.
Good code / StringBuffer result = new StringBuffer(“”);
behavior while (iter.hasNext()){
result.append((String)iter.next());
}
return result.toString();

1.2 Collection usage

1.2.1 Avoid using Hashtable and Vector

Problem Avoid using Hashtable and Vector.

Type Performance / Collection usage – Java


Bad code / In un-threaded context:
behavior Vector m_aCollection = new Vector();//ArrayList
m_aCollection.get(i)...
In threaded context:
Hashtable m_aCollection = new Hashtable();//HashMap
if (!m_aCollection.contains(someObject){
m_aCollection.add(someKey, someObject);

4 / 39
Coding Best Practices

}
Description Accesses to Vector or Hashtable are synchronized =>in unthreaded
context, this overhead is unnecessary.
In threaded context, m_aCollection.contains(someObject) and
m_aCollection.add(someKey, someObject); should be in a single
synchronized block. Therefore, the block of code
if (!m_aCollection.contains(someObject){
m_aCollection.add(someKey, someObject);
}
is not correct although Hashtable already provides the synchronization
facility
Good code / Use ArrayList, LinkedList, HashMap … and provide synchronization
behavior block/method if necessary in threaded context.
Un-threaded
List m_aCollection = new ArrayList();
m_aCollection.get(i)...

Threaded
HashMap m_aCollection = new HashMap();
......
synchronized(this){
if (!m_aCollection.contains(someObject){
m_aCollection.add(someKey, someObject);
}
}

1.2.2 Use Iterator instead of indexing for loop

Problem Use Iterator instead of indexing for loop in Collections (List,…)

Type Performance / Collection usage – Java


Bad code / int len = anArrayList.size();
behavior for (int i = 0; i <len; i++){
// do something with anArrayList.get(i)
}
Description Iterator is designed for best performance
Using index is error-prone, so use alternatives if possible
Good code / Iterator iter = anArrayList.iterator();

5 / 39
Coding Best Practices

behavior while (iter.hasNext()){


// do something with iter.next();
}

//for each
Pitfall DO NOT create a List from an Array however!!!

1.2.3 List to array

Problem List to array

Type Collection (Java)


Bad code / MyClass[] result = (MyClass[])myList.toArray(new
behavior MyClass[0]);

Description At the first glance, the above code looks fine. However, the problem
reveals when we look at the implementation / javadoc of the method
toArray(). Here is a brief explanation of what it does:
- Check to see if the size of the input array matches the size of the
list
- If yes, copy the data of the list to that array
- If no, create a new array of the same type (as the input array) and
copy the data of the list to it
Therefore, we can see that the object (new MyClass[0]) is used in a
very short time and after that it is not referred anymore by anyone and
ready for garbage collected. We call such kind of objects short-lived
objects. These objects are a burden for garbage collector.
The better way to do is described below, where we prepare an array
that has the exact size of the list. This way, no new object are created.
Good code / MyClass[] result = (MyClass[])myList.toArray(new
behavior MyClass[myList.size()]);

1.2.4 Arrays.asList(...)

Problem Arrays.asList(...)

Type Collection

6 / 39
Coding Best Practices

Bad code / List list = new ArrayList(array.length);


behavior for (int i = 0; i < array.length; ++i) {
list.add(array[i]);
}
Description In order to convert an array to a list, we do not need to make the code
ourselves. There is a method named asList() in the utilities class Arrays
that does this for us.
The class Arrays also contains some other useful method for array type.

Good code / List list = Arrays.asList(array);


behavior Finding in utility class
Arrays.___
Collections.____
Pitfall Convert an array to a List only when you really need a List. Do not
forget that most utilities (search, sort) for Collections are also available
for arrays in Arrays.

7 / 39
Coding Best Practices

2 Resources management

2.1 Resources allocation


2.1.1 Use lazy initialization in memory-extensive applications

Problem Use lazy initialization in memory-extensive applications.

Type Resources management / Performance / object initialization-Java/C#


Bad code / Suppose m_resource is very costly to initialize and is used sparsely.
behavior class SomeClass {
private Resource m_resource = null;
public SomeClass(){
// m_resource is initialized here
}
public Resource getResource() {
return m_resource;
}
}
Description Only initialize m_resource when necessary.

Good code / Initialize when needed:


behavior public Resource getResource() {
if (m_resource == null){
// initialize m_resource
}
return m_resource
}
Note: in threaded context where the resource is concurrently
accessed/modified, use double-checked locking pattern.

2.1.2 Initialize size of collection type

Problem Initialize size of collection type

Type Resources management /Object initialization - Java


Bad code / ArrayList anArrayList = new ArrayList();
behavior
Description Calling empty constructor creates a Collection of default size, which

8 / 39
Coding Best Practices

might be smaller than expected size. When the collection is about to be


full, the size of the Collection will be extended together with copy
operations, which is resource-consuming.
To avoid this, put an expected size in the constructor.
Good code / ArrayList anArrayList = new ArrayList(expected_size);
behavior

Pitfall Do not try to calculate precisely “expected-size” if this calculation is


complex. Better choose a “best guess” size, easy to calculate.

2.1.3 Should declare local variable just before use

Problem Should declare local variable just before use

Type Resources management


Bad code / BufferedReader input = null;
// some other code here
behavior …


// use the input variable here

try {
input = new BufferedReader( new FileReader(aFile));
// some code here
}catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex){
ex.printStackTrace();
} finally {
}
Description Declaring local variables without using them immediately will
unnecessarily increase their scope. This decreases legibility, and
increases the likelihood of error. It also hinders readability.
Good code / // some other code here

behavior …

try {
BufferedReader input = new BufferedReader( new
FileReader(aFile));
// some code here
}catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex){
ex.printStackTrace();
} finally {
}

9 / 39
Coding Best Practices

2.2 Resources de-allocation


2.2.1 Must not forget to close the stream

Problem Must not forget to close the stream.

Type Resources management


Bad code / ObjectOutput output = null;
try{
behavior //use buffering
OutputStream file = new FileOutputStream(
"something.txt" );
OutputStream buffer = new BufferedOutputStream( file
);
output = new ObjectOutputStream( buffer );
output.writeObject(quarks);
} catch(IOException ex){
// log the error
}

Description Streams represent resources which you must always clean up explicitly,
by calling the close method
Good code / ObjectOutput output = null;
try{
behavior //use buffering
OutputStream file = new FileOutputStream(
"something.txt " );
OutputStream buffer = new BufferedOutputStream( file
);
output = new ObjectOutputStream( buffer );
output.writeObject(quarks);
} catch(IOException ex){
//log
} finally{
try {
if (output != null) {
output.close();
}
} catch (IOException ex ){
// log
}
}

Comment An additional best practice is to put the “grey” code into a method of a
untility class.

10 / 39
Coding Best Practices

11 / 39
Coding Best Practices

3 Integrity

3.1 Object initialization


3.1.1 Use double checked locking when lazy-initializing object in threaded context
where resource is shared

Use double checked locking when lazy-initializing object in threaded


Problem
context where resource is shared.
Type Integrity / Object initialization - Java/C# / Performance
Bad code / class SomeClass {
behavior private Resource m_resource = null;

public Resource getResource() {


if (m_resource == null) {
synchronized {
m_resource = new Resource();
}
}
return m_resource;
}
}
Description Supposed more than one thread arrive at the getResource() method. All
the threads found resource == null. All of them will take turn to initialize
m_resource, which is not desired.
A better way is to check m_resource again to see if some other thread
has already initialized it.
Good code / class SomeClass {
behavior private Resource m_resource = null;

public Resource getResource() {


synchronized {
if (m_resource == null){
m_resource = new Resource();
}
}
return m_resource;
}

12 / 39
Coding Best Practices

}
Note: In JVM prior to 1.5, this pattern does not work. In that case, use
either eager initialization
e.g private Reource m_resource = new Resource();
or synchronized method
e.g public synchronized Resource getResource(){
if (m_resource == null){
m_resource = new Resource();
}
return m_resource;
}
In .NET, see
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpatter
ns/html/ImpSingletonInCsharp.asp
Pitfall That (double checked locking) does not work with all JVM!! But at
minimum, should do the “single checked locking” (i.e. put “syncronized”
at method declaration)

3.2 Comparing objects


3.2.1 Comparing two objects ( “==” instead of “.equals”)

Problem Comparing two objects ( == instead of .equals)

Type Integrity
Bad code / if ( ("abc" + "def") == "abcdef" )
behavior {
......
}
Description When we use the == operator, we are actually comparing two object
references, to see if they point to the same object. We cannot compare,
for example, two strings for equality, using the == operator. We must
instead use the .equals method, which is a method inherited by all
classes from java.lang.Object.
Good code / if ( ("abc" + "def").equals("abcdef") )
behavior {
.....
}
Pitfall Beware of the “default” behaviour of equals. If needed, overwrite it for
your own class!

13 / 39
Coding Best Practices

14 / 39
Coding Best Practices

4 Design related

4.1 Design - OOP


4.1.1 OOP - Encapsulation: declare a data member is public

Problem Encapsulation: declare a data member is public.

Type Design – OOP


Bad code / Bad public class ABC {
smell / behavior …
public String m_msg;

}

Description Declaring fields to be public is usually the wrong thing to do, since the
caller is no longer protected from changes to class implementation.
Declare fields as private. If fields need to be accessed by the caller,
then provide the necessary get and set methods
Good code / public class ABC {
behavior …
private String m_msg;

public String getMsg() {
return m_msg;
}
public void setMsg(String msg) {
m_msg = msg;
}
}
Pitfall Do not do that systematically for all data members!!! ONLY for
necessary ones! (see 4.1.2)

4.1.2 OOP - Encapsulation: Do not make visible things that should not be visible

Encapsulation: Do not make visible things that should not be


Problem visible.
Not also attributes/methods in class but can also be inner classes

15 / 39
Coding Best Practices

Type Design – OOP


Bad code / public class ClassX {
behavior private List m_list;

public List getList() ;


public void setList(List list);

}

Description If m_list is a private data that is updated inside class X, try to hide it
instead of making it visible even via set/getter. The list will be got out via
setter and updated outside at any time and is out of control of ClassX.

Good code / public class ClassX() {


behavior private List m_list;

// try to support only necessary methods.


public int size() {
}
public ConcreateClass get(int index) {
}
….
}

4.1.3 OOP - Use inner class in order to avoid using member attributes

Problem Use inner class in order to avoid using member attributes.

Type Design – OOP


Bad code / public class CalculService {
behavior private double m_salary;
private int m_years;

public double calculateSavingAccount() {


// this method will update m_salary and m_years.
doCalculateSalaryAndYear();
// this method will use m_salary and m_years.

16 / 39
Coding Best Practices

return doCalculateSavingAccount();
}
}

Description This code is not good because we need to initiate CalculService for
every calls (in multi-thread). In this case, we should NOT create a new
public class SalaryAndYear as this class is only used in this service.
This class is also static as it is technically independent on the
CalculService, it is just placed inside CalculsService for being hidden
from outside use.
Good code / public class CalculService {
behavior //
public double calculateSavingAccount() {
SalaryAndYear salAndYear =
doCalculateSalaryAndYear();
return doCalculatesavingAccount(salAndYear);
}

private static class SalaryAndYear {


}
}
Pitfall Some coding guidelines refuse inner classes!

4.1.4 OOP – Isolation between technical handlings and business handlings

Problem Isolation between technical handlings and business handlings

Type Design - OOP


Bad code /
behavior
Description Imagine that we have a service that is responsible for handling a
business feature. And in order to handling that business, it has to do a
lot of technical handlings (parsing file, string, calculate date, build xml
content, …)
 Try to delegate responsibility of handling technical thing to another
private method, or a utility class or another technical service.
 At least, a method should be kept as clean as we can see only either
business or technical handlings inside it, and not see both.
 A class which is responsible for business handling should not have
any public methods for technical handling.

17 / 39
Coding Best Practices

 A class which is responsible for technical handling should not have


any methods for business handling.

Good code / …
behavior

4.1.5 OOP - Isolation between independent businesses

Problem Isolation between independent businesses

Type Design - OOP


Bad code /
behavior
Description Try to isolate separate parts of code into separate methods, classes,
packages, modules, …(if 2 different businesses then at least 2 different
classes / services. Not only 2 different methods)
 Try to delegate responsibility of handling technical thing to another
private method, or a until class or another technical service.
 At least, a method should be kept as clean as we can see only either
business or technical handlings inside it, and not see both.
 A class which is responsible for business handling should not have
any public methods for technical handling.
 A class which is responsible for technical handling should not have
any methods for business handling.

Good code / …
behavior

4.1.6 OOP - Isolation between systems

Problem Isolation between systems

Type Design - OOP


Bad code /
behavior
Description When two different systems, modules need to talk to each other, try to
separate code for interfacing between two systems into separate
classes. For example system A needs to interact to system B.
 Only few of classes of system A should “depend” on system B.

18 / 39
Coding Best Practices

 Other parts of system A should not know much about system B.


 Modification on system B should only impact on the interfacing part
of system A.
Good code / …
behavior

4.1.7 OOP - Isolation between the generic algorithm and detail implementation

Problem Isolation between the generic algorithm and detail implementation

Type Design - OOP


Bad code /
behavior
Description The generic algorithm and detail implementation (see 4.1.6)
 Generic algorithm should be put in the abstract base class. For detail
implementations that the base class can not know how to do, we
introduce abstract methods accordingly.
 A concrete class for a detail implementation will be responsible for
fulfilling detail implementation by implementing abstract methods.
Good code / …
behavior

4.1.8 Information expert, correct responsibility

Problem Information expert, correct responsibility.

Type Design - OOP

Bad code /
behavior
Description It is very important to have correct class be responsible for an
implementation.
(see Information Expert).
Hints to decide which class is proper in order to implement a method by
asking ourselves these questions:
 Which class knows the best about the service that we are going to
implement.
 If we put the implementation in this class, do we have a high
cohesion to other parts of the class. If not, then it may not be the
right class.

19 / 39
Coding Best Practices

 If we put the implementation in this class, do we still have the loose


coupling to other classes. If not, then it can be not the right class as
this service requires so many other information that this class can
not provide.
 If we put this implementation in this class, are the name, the main
objective, the comment about the class still valid and proper.
Good code /
behavior

4.1.9 Getter/Setter vs. Overriding

Problem Getter/Setter vs. Overriding (or “Template Method” pattern)

Type Design - OOP


Bad code / Modify directly on ComponentA
behavior public class ComponentA {
private boolean m_shouldDoBis;
public void doSomeThing() {
init();
doA();
if (m_shouldDoBis) {
doBBis();
// doBBis() can be sometimes, just empty when we
just want to
// skip implementation of doB in some particular
case.
} else {
doB();
}

doC();
}

public void setShouldDoBBis(boolean shouldDoBBis) {


m_shouldDoBis= flagX;
}
public boolean isShouldDoBBis() {
return m_shouldDoBis;
}

20 / 39
Coding Best Practices

}
Description Imagine that we have an existing class that we need to customize in
order to support a new feature or to change the behavior.
The new behavior is not so common and really a kind of particular.
For example:
pubic class ComponentA {
public void doSomeThing() {
init();
doA();
doB();
doC();
}

private void doA() {


..
}

private void doB() {


..
}

}

Now, we need to customize the implementation of doSomeThing a bit in


some special cases in order to do some particular treatments.

Bad points:
1. doBBis() can be, sometimes, specific and should not (or even
can not) be placed in a common component.
2. Very confusing for client code. How to know that we should call
setDoBBis before calling doSomething. What if client code
forgets to call setDoBBis.
setDoBBis is introduced and is very rarely used except for our particular
purpose.
Good code / As doB() in ComponentA can be probably customized, if it is private, it
behavior should be modified to ‘protected’.
public class ComponentA {
protected void doB() {
}

21 / 39
Coding Best Practices

}
Introduce a new class to override doB.
public class ParticularComponentA extends ComponentA{
protected void doB() {
doBBis();
}
}

4.1.10 Decouple with real-implementation / coding to interface

Problem Decouple real-implementation / coding with interface

Type Design - OOP / Maintenance / Object initialization - Java


Bad code / Take the typical case of DataAccess object (DAO). It is likely that the
behavior switch between database (Oracle to SQLSever for example) happens.
OracleCustomerDAO myDAO = new OracleCustomerDAO ();
myDAO.update(...);

Description Whenever a switch between database is required, the line OracleDAO


myDAO = new OracleDAO();
has to be replaced everywhere it occurs.
To improve, code to interface. With that, changes in the real
implementation do not affect the client code.
Good code / Declare an interface
behavior CustomerDAOInterface{
public void update(...);
}
Following are example of possible DAOs with different databases
public class OracleCustomerDAO implements CustomerDAO{
public void update(...){
// real implementation
}
}
public class SQLCustomerDAO implements CustomerDAO{
public void update(...){
// real implementation

22 / 39
Coding Best Practices

}
}

Add a singleton factory


public class DAOFactory{
public CustomerDAO getCustomerDAO(){
// read from configuration file and produce
// corresponding DAO
// this method is responsible for creating DAO
// of specific database, according to
// configuration
}
}
In client code:
CustomerDAO myDAO =
DAOFactory.instance().getCustomerDAO();
myDAO.update(...);

With this way, change in the interface only requires change in


configuration file for the application to work.
Comment In the context of LW containers (e.g. Spring / EL4J) no factory is
required.

23 / 39
Coding Best Practices

4.2 Others
4.2.1 The interface java.io.Serializable must be understood properly

Problem The interface java.io.Serializable must be understood properly

Type Design related


Bad code / Do not implement it for all data objects
behavior
Description

Good code / Only apply it:


behavior
+ Pass the objects via remote: RMI
+ When using some cache libraries that can cache to disk (e.g.
ehCache).
+ ...

24 / 39
Coding Best Practices

5 Code Maintenance

5.1 Object initialization


5.1.1 Declare private constructor for Helper, Utility classes

Problem Declare private constructor for Helper, Utility classes

Type Maintenance / Object initialization - Java


Bad code / public class AHelper{
behavior // no constructor
public static void aHelperFunction(){
// processing
}
}

Description AHelper might be accidentally initialized. To avoid that, add a private


constructor and the class cannot be initialized by invoking any
constructor. The problem is that if AHelper was accidentally initialized, it
creates short-lived objects then the Gabage Collector will collect for
nothing)
Good code / public class AHelper{
behavior private AHelper{
}

public static void aHelperFunction(){


.........
}
}

5.1.2 Declare constants in classes instead of interfaces

Problem Declare constants in classes instead of interfaces

Type Clear code/Object initialization - Java


Bad code / public interface AConstantsInterface{
behavior public static final int AN_INTEGER_CONST = …;
.........
}

25 / 39
Coding Best Practices

public class AConstantsUser implements


AConstantsInterface{
.........
if (AN_INTEGER_CONST == ...){
.........
}
}
Description Interfaces are not intended to be used like that
Very unclear if we have a large amount of unqualified constant names.
Good code / public final class AConstantsClass{
behavior public static final int AN_INTEGER_CONST = ...;
.........
}

public class AConstantUser {


.........
if (AConstantsClass.AN_INTEGER_CONST == .........){
.........
}
}

5.2 Maintainability
5.2.1 Avoid using instanceof method

Problem Avoid using instanceof method

Type Maintainability – Java


Bad code / behavior public void someMethod(Object anObject){
if (anObject instanceof ClassA){
((ClassA) anObject).aMethodA();
} else if (anObject instanceof ClassB){
((ClassB) anObject).aMethodB();
}
...
}

26 / 39
Coding Best Practices

Description Polymorphism could provide much better code here

Good code / public interface AnInterface{


behavior public void aMethod{};
}
public class ClassA implements AnInterface{
public void aMethod{
}
}
public class ClassB implements AnInterface{
Public void aMethod{
}
}
Then in client code
public void someMethod{AnInterface anInstance){
anInstance.aMethod();
}

5.2.2 Return empty list, array in public methods

Problem Return empty list, array in public methods

Type Maintainability – Java/C#


Bad code / behavior public class ClientService{
public List getCustomers(){
...
if (some condition){
result = null;
}
return result;
}
}
Client code fragment
List customers =
ClientService.instance().getCustomers();
if (customers != null){
// process customer list

27 / 39
Coding Best Practices

}
Description Make client code complex unnecessarily

Good code / public class ClientService{


behavior public ArrayList getCustomers(){
...
if (some condition){
result = Collections.EMPTY_LIST
}
return result;
}
}

// Client
List customers =
ClientService.instance().getCustomers();
// process customer list

5.2.3 Do not use Assertion in place of business checking

Problem Do not use Assertion in place of business checking

Type Maintainability, Reliability – Java


Bad code / behavior public void someProcessing(List input){
assert(input != null);
// processing
}
Description Assertion is meant for programming error check and not for business
code
Assertion can be turned off =>validation fails
Assertion cannot throw specific Exception
Good code / public void someProcessing(List input){
behavior if (input != null){
// processing
}
}

28 / 39
Coding Best Practices

Note: However, if someProcessing(List input) is private, then the


use of Assertion is acceptable, since it this case, normally the same
developer will also write the caller of someProcessing and he should
know the input condition of that method. Assertion in this case is used
to prevent programming error.
Comment This is true for public methods, but for private, you can still use
assertions (because that would be programming errors here)

5.2.4 Comparing enum type

Problem Comparing enum type

Type Code maintenance


Bad code / TypeDossierState state = dossier.getState();
behavior if (!(TypeDossierState.CLOSED.equals(state)) {

}

// TypeDossierState is implemented as enum type

Description The general idea of enum type is that we can not create instance of that
class other than the predefined ones. Thus we can actually use the ==
to compare. It is more natural and increases readability.
Good code / TypeDossierState state = dossier.getState();
behavior if (state != TypeDossierState.CLOSED) {

}

5.2.5 Must not forget to put try..catch in finally

Problem Must not forget to put try..catch in finally (if needed)

Type Code maintenance


Bad code / ObjectOutput output = null;
try{
behavior //use buffering
OutputStream file = new FileOutputStream(
"something.txt " );
OutputStream buffer = new BufferedOutputStream( file
);
output = new ObjectOutputStream( buffer );
output.writeObject(quarks);

29 / 39
Coding Best Practices

} catch(IOException ex){
// log the error
} finally{
if (output != null) {
output.close();
}
}

Description Many finally clauses in turn contain a try..catch block. This is


because many of the methods called in a finally clause can
themselves throw an exception
Good code / ObjectOutput output = null;
try{
behavior //use buffering
OutputStream file = new FileOutputStream(
"something.txt " );
OutputStream buffer = new BufferedOutputStream( file
);
output = new ObjectOutputStream( buffer );
output.writeObject(quarks);
} catch(IOException ex){
// log the error
} finally{
try {
if (output != null) {
output.close();
}
} catch (IOException ex ){
// log
}
}

5.2.6 The class and method naming must be clear

Problem The class and method naming must be clear.

Type Code maintenance


Bad code / For example:
behavior
I would like to make a Service to manage the User and do the
authentication for the user
Bad naming:
UserService {
create();
update();
authenticate();
}

30 / 39
Coding Best Practices

Description If you do not know how to name it, please ask the expert or someone
who has more experience.
Good code / So with that example, there are 2 different things:
behavior  User management
 User authentication
So make 2 services for that:

UserManagementService {
createUser();
updateUser();
}

AuthenticationService {
authenticate();
}

5.2.7 Documentation: comments in the source code

Problem Documentation: comments in the source code

Type Code maintenance


Bad code / There is a method:createUser, and its comments are: create
behavior User
=> It is useless comment
Description The code must be documented properly. It must be respected by ALL
developer. Do not put the non-valuable comment. When you change
the code, please check the comment if it is still valid. Make sure that the
comment is matched with your code.
Tip: Think carefully what the code will be developed. Then write them
down: ALL the things in your mind (i.e. the logic or business or
algorithm…)
Good code / Try to think about business of method:
behavior This method will create a new user for the system. It will
be used to logon to the system. When the user is created,
the password must be changed at the first time of logon.

5.2.8 Use the constants, do not hard-code the value

Use the constants, do not hard-code the value.


Problem Try to use the ? to prepare the parameters for SQL. Do not put directly
value!

31 / 39
Coding Best Practices

Type Code maintenance


Bad code / If (value == 1) {
//do something
behavior }

Or in the query

Select user_name, password where visa = ? and active = 1

Description

Good code / If (value == ACTIVE) {


//do something
behavior }
Or in the query
Select user_name, password where visa = ? and active = ?
Try to put it as parameter with the constant ACTIVE

5.2.9 Do not copy / paste the code or comments

Problem Do not copy the code and the comment

Type Code maintenance


Bad code /
behavior
Description If you copy similar code, it is easy to forget to modify the comment and
something the name of parameter.
Solution: make a generic function to reuse in both cases.
Good code /
behavior

5.2.10 The constants and configurable parameters are different

Problem The constants and configurable parameters are different.

Type Code maintenance


Bad code /
behavior
Description If you think the value will be never changed, or if we change it, we have
to rebuild the system. Then put it as constants.
Else make it as configurable parameters, it mean if will be configured
when we install it in different environment (TEST, PROD).
Because if you put too much for the configuration, then it is difficult for

32 / 39
Coding Best Practices

the installation.
Good code /
behavior

33 / 39
Coding Best Practices

6 Code reliability

6.1 Exception handling


6.1.1 Never leave a empty catch block

Problem Never leave a empty catch block

Type Maintainability / Exception handling – Java, C#


Bad code / try{
behavior // do something that might cause exception
}catch(AException aExc){
// do nothing
}

Description There is no easy way to trace back to original source of error.

Good code / try{


behavior // do something that might cause exception
}catch(AException aExc){
// logging
// translate with aExc kept in the new exception OR at
least comment/justification
}

6.1.2 Be specific in throw clause

Problem Be specific in throw clause

Type Maintainability / Exception handling – Java, C#


Bad code / behavior public void aMethod(...) throws Exception

Description Difficult to figure out what specific error has occurred

Good code / public void aMethod(...) throws ASpecificException


behavior

34 / 39
Coding Best Practices

6.1.3 Pass pertinent data to exception

Problem Pass pertinent data to exception.

Type Maintainability / Exception handling – Java, C#


Bad code / behavior public class CustomerDAO{
public CustomerDTO loadCustomer(string customerID)
throws ObjectNotFoundException{
List customerList = ... (select statement)
if (customerList == 0){
throw new ObjectNotFoundException(
“Cannot load customer info”);
}
// further processing
}
...
}
public class CustomerService{
public void processingWith2Customers(
string firstCustomerID, string secondCustomerID)
throws ObjectNotFoundException{

CustomerDTO firstCustomer =
customerDAO.loadCustomer(firstCustomerID);
CustomerDTO secondCustomer =
customerDAO.loadCustomer(secondCustomerID);
// some further processing with firstCustomer and
// secondCustomer
}
...
}
Client code:
try{
customerService.processingWith2Customers(“1”, “2”);
}catch(ObjectNotFoundException exc){
// Oop, do not know which customer is not found.
// If on the GUI, I am to show a message, the best I
// can do is to display a vague message

35 / 39
Coding Best Practices

// “Cannot load customer”


}
Description Difficult to figure out what action should be carried out next, since
there is no or only a little hint from the exception
Good code / public class ObjectNotFoundException{
behavior private string m_objectID;
public string getObjectID{
return m_objectID;
}
...
}
public class CustomerDAO{
public CustomerDTO loadCustomer(string customerID)
throws ObjectNotFoundException{
List customerList = ... (select statement)
if (customerList == 0){
throw new ObjectNotFoundException(
“Cannot load customer info”, customerID);
}
// further processing
}
...
}
public class CustomerService{
public void processingWith2Customers(
string firstCustomerID, string secondCustomerID)
throws ObjectNotFoundException{

CustomerDTO firstCustomer =
customerDAO.loadCustomer(firstCustomerID);
CustomerDTO secondCustomer =
customerDAO.loadCustomer(secondCustomerID);
// some further processing with firstCustomer and
// secondCustomer
}
...
}

36 / 39
Coding Best Practices

Client code:
try{
customerService.processingWith2Customers(“1”, “2”);
}catch(ObjectNotFoundException exc){
// If on the GUI, I am to show a message, at
// least I can tell which customerID cannot be
// loaded, visa exc.getObjectID();
}

37 / 39
Coding Best Practices

7 Miscellaneous

7.1 Reuse existing components


7.1.1 Do not try to create home-built service, or re-invent things

Problem Do not try to create home-built service, or re-invent things.

Type Reusability

Bad code / Implement the sort for collection again.


behavior
Do complicated handlings on string (parse string, …)
Handlings for log.
Implement again a part of common task that other team member has
done.

Description During development, we can easily fall into the situation when we try to
re-invent what already exists (maybe your current language already
supports, or maybe the library you are using or even another team
member has already done such a service). Try to ask when we feel that
the service can be common.
Good code / Use Collections.sort
behavior
Use StringTokenizer, StringBuffer, String API, …
Use reliable third party utilities.
Ask other team member when you think a similar service has been
done.

7.1.2 Sorting

Problem Sorting

Type Reusability - Java


Bad code / None.
behavior

Description When we want to sort an array or a list, do not write the algorithm
yourself. The algorithm is already implemented for you in method

38 / 39
Coding Best Practices

Arrays.sort (for array) and Collections.sort (for List). What you have to
do is to provide a way to compare between two objects you want to
sort. We have two ways to do this:
- Let the object implements the interface Comparable.
- Provide a “Comparator” to compare two objects (see code below).
Good code / Takes for example we want to sort a list persons using their name (case
behavior in sensitive). Here is what we have to do:
- Create a comparator
public class PersonComparator
implements java.util.Comparator {
public int compare(Object o1, Object o2) {
Person p1 = (Person)o1;
Person p2 = (Person)p2;
String s1 = p1.getName().toUpperCase();
String s2 = p2.getName().toUpperCase();
return s1.compareTo(s2);
}
}

- Compare the list


Collections.sort(personList, new PersonComparator());

7.2 Problem solving

7.2.1 You have a PROBLEM

Problem You have a PROBLEM

Type Misc.
Bad code / Try yourself which might be non-standard or good solution
behavior
Description

Good code / ASK someone (more experienced) if you do not know or you have
behavior doubts.
Use GOOGLE to find one solution, do not think you are only one who
has a problem. Check you understand the found solution and that it fits
your needs. If you are not sure, ask someone’s opinion on the solution
you have found on the web…

39 / 39

You might also like