2015 - JAVA Coding Best Practices
2015 - JAVA Coding Best Practices
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
IV. Abbreviations
DB Database
DTO Data Transfer Object
OOP Object Oriented Programming
PROD Production
3 / 39
Coding Best Practices
1 Performance
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);
}
}
5 / 39
Coding Best Practices
//for each
Pitfall DO NOT create a List from an Array however!!!
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
7 / 39
Coding Best Practices
2 Resources management
8 / 39
Coding Best Practices
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
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
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)
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
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
15 / 39
Coding Best Practices
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.
4.1.3 OOP - Use inner class in order to avoid using member attributes
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);
}
17 / 39
Coding Best Practices
18 / 39
Coding Best Practices
4.1.7 OOP - Isolation between the generic algorithm and detail implementation
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
doC();
}
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();
}
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();
}
}
22 / 39
Coding Best Practices
}
}
23 / 39
Coding Best Practices
4.2 Others
4.2.1 The interface java.io.Serializable must be understood properly
24 / 39
Coding Best Practices
5 Code Maintenance
25 / 39
Coding Best Practices
5.2 Maintainability
5.2.1 Avoid using instanceof method
26 / 39
Coding Best Practices
27 / 39
Coding Best Practices
}
Description Make client code complex unnecessarily
// Client
List customers =
ClientService.instance().getCustomers();
// process customer list
28 / 39
Coding Best Practices
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) {
…
}
29 / 39
Coding Best Practices
} catch(IOException ex){
// log the error
} finally{
if (output != null) {
output.close();
}
}
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();
}
31 / 39
Coding Best Practices
Or in the query
Description
32 / 39
Coding Best Practices
the installation.
Good code /
behavior
33 / 39
Coding Best Practices
6 Code reliability
34 / 39
Coding Best Practices
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
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
Type Reusability
7.1.2 Sorting
Problem Sorting
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);
}
}
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