Clean code in Java, Java EE: How to get rid of code and design debt

67
Clean Code in Java, Java EE : How to get rid of code & design debt Madhura Oak Project Manager Intellect Design Arena Ltd.

Transcript of Clean code in Java, Java EE: How to get rid of code and design debt

Page 1: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code in Java, Java EE : How to get rid of code & design debt

Madhura Oak

Project ManagerIntellect Design Arena Ltd.

Page 2: Clean code in Java, Java EE: How to get rid of code and design debt

Code Debt

Page 3: Clean code in Java, Java EE: How to get rid of code and design debt

1. Use of method to get switch case value

private static final String _ALPHABETS = "ALPHABETS";private static final int _ALPHABETS_NO = 1;

private int getSwitchId(String value) {if(value.equals(_ALPHABETS)) {

return _ALPHABETS_NO;}...

}

int switchId = getSwitchId(data);switch(switchId) {

case _ALPHABETS_NO: ...

}

Page 4: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use enum

private enum DataType { ALPHABETS,ALPHA_NUMERIC,NUMERIC,SWIFT,ALL,DATE,TIME

}

switch(DataType.valueOf(data)) {case ALPHABETS:

...}

Page 5: Clean code in Java, Java EE: How to get rid of code and design debt

2. Mixing error handling with output

public void create(Map<String,Object> results) throws Exception {//validate conditionif(condition) {

results.set("ERROR_CODE","CONDITION VIOLATED"); }

}

Map<String,Object> results = new HashMap<>();create(results);if(results.containsKey("ERROR_CODE")) {

...}

Page 6: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use Exceptionspublic void create(Map<String,Object> results) throws Exception {

//validate conditionif(condition) {

throw new ConditionViolatedException();}

}

try {Map<String,Object> results = new HashMap<>();create(results);

}catch(ConditionViolatedException exp) {

}

Page 7: Clean code in Java, Java EE: How to get rid of code and design debt

3. If..else blocks without braces

if(condition) do something

else do something else

Page 8: Clean code in Java, Java EE: How to get rid of code and design debt

Use curly braces for if..else blocks

if(condition) {//do something

}else {

//do something else}

Page 9: Clean code in Java, Java EE: How to get rid of code and design debt

4. Avoid creation of unused objects

public String getColumns(List<Field> fields) {String column = "";StringBuilder columns = new StringBuilder();for(Field field : fields) {

column = field.getColumn();columns.append(column);columns.append(",");

}return columns.toString();

}

Page 10: Clean code in Java, Java EE: How to get rid of code and design debt

5. Redundant code

List<String> countries = new ArrayList<String>();countries.add(countryCode);if (countries != null && !countries.isEmpty()) {

for (String countryCode : countries) {//do some action

Page 11: Clean code in Java, Java EE: How to get rid of code and design debt

6. Unused EJB References

@EJB(name = "RetryTimer", mappedName = "ejblocal:retryTimer")private IRetryTimer retryTimerBean;

Page 12: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Ensure your code is minimal

Less code means less maintenance. Presence of unused variables could not only add to the clutter in code but also would cause unnecessary memory allocation.

Page 13: Clean code in Java, Java EE: How to get rid of code and design debt

7. Variables declared in procedural style – at the start of method

public String getColumns(List<Field> fields) {String column = "";StringBuilder columns = new StringBuilder();for(Field field : fields) {

column = field.getColumn();columns.append(column);columns.append(",");

}return columns.toString();

}

Page 14: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code - Declare variable only where required

public String getColumns(List<Field> fields) {StringBuilder columns = new StringBuilder();for(Field field : fields) {

String column = field.getColumn();columns.append(column);columns.append(",");

}return columns.toString();

}

Page 15: Clean code in Java, Java EE: How to get rid of code and design debt

8. Use of String literals in multiple classes

if(validate.equals("Y")) {

}

Page 16: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Option 1- Create a class for constants

public class Constants {public static final String Y = "Y";

}

if(validate.equals(Constants.Y)) {

}

Page 17: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Option 2 – Define constants in properties file

Constants.propertiesVALIDATION_FLAG=Y

public class Constants {private ResourceBundle bundle = ResourceBundle.getBundle("Constants");public static final String VALIDATION_FLAG =

bundle.getProperty("VALIDATION_FLAG");}

//usage in codeif(validate.equals(Constants.VALIDATION_FLAG)) {

}

Page 18: Clean code in Java, Java EE: How to get rid of code and design debt

9. Using StringBuffer as local variable

public String getUpdateQuery() {StringBuffer updateQuery = new StringBuffer();...return updateQuery.toString();

}

Page 19: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use StringBuilder for local variables

public String getUpdateQuery() {StringBuilder updateQuery = new StringBuilder();...return updateQuery.toString();

}

Page 20: Clean code in Java, Java EE: How to get rid of code and design debt

10. Declaring redundant default constructor

public class RuntimeDAO {public RuntimeDAO() {}

}

Page 21: Clean code in Java, Java EE: How to get rid of code and design debt

11. Using default constructor to initialize member variables

private List<String> documentTypeIds;

public class RuntimeDAO {public RuntimeDAO() {

documentTypeIds = new ArrayList<>();}

}

Page 22: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use default constructor only when required

private List<String> documentTypeIds = new ArrayList<>();

public class RuntimeDAO {

}

Page 23: Clean code in Java, Java EE: How to get rid of code and design debt

12. Names do not reveal intentionprivate void addRequiredProdDbTable(

Map<String,List<IwFieldData>> tableFieldMap) {Map<String,String> txnTables = mProductEntity.getTXNTables();for(String tableName : txnTables.keySet()) {

if(!tableFieldMap.containsKey(tableName) && !mProductEntity.isMultiOptTable(tableName)) {

tableFieldMap.put(tableName, new ArrayList<IwFieldData>());}

}}

Page 24: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use intention revealing names

private void addNonMultiOptTxnTables(Map<String,List<IwFieldData>> tableFieldMap) {

Map<String,String> txnTables = mProductEntity.getTXNTables();for(String tableName : txnTables.keySet()) {

if(!tableFieldMap.containsKey(tableName) && !mProductEntity.isMultiOptTable(tableName)) {

tableFieldMap.put(tableName, new ArrayList<IwFieldData>());}

}}

Page 25: Clean code in Java, Java EE: How to get rid of code and design debt

13. clone() does shallow cloningpublic class Field implements Cloneable {

private List<String> columnValues;}

Field fieldCopy = (Field)field.clone();//both field and fieldCopy refer to same columnValues list

Page 26: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Deep Cloningpublic class Field implements Cloneable {

private List<String> columnValues;

public Field createCopy() {try {

Field copy = clone();copy.columnValues =

(List<String>)columnValues.clone();}catch(CloneNotSupportedException exp) {

//do nothing}

}}

Page 27: Clean code in Java, Java EE: How to get rid of code and design debt

14. Using Date to calculate time difference

Date startDate = new Date();/* code */Date endDate = new Date();long executionTime = startDate.getTime() – endDate.getTime();

Page 28: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use System.currentTimeMillis()

long startTime = System.currentTimeMillis();/* code */long endTime = System.currentTimeMillis();long executionTime = endTime – startTime;

Page 29: Clean code in Java, Java EE: How to get rid of code and design debt

15. Incorrect way of comparing string

if (sleepTime != null && sleepTime != "") {

Page 30: Clean code in Java, Java EE: How to get rid of code and design debt

Clean code – Use equals whether String is not null and not empty

if ("".equals(sleepTime)) {

If sleepTime is null it returns false, so null check is not needed.

Page 31: Clean code in Java, Java EE: How to get rid of code and design debt

16. Common codecatch(InterruptedException exp) { AppException exp = new AppException();

exp.addError(Constants.ERROR_CODE, "EXP005");exp.addError(Constants.ERROR_MESG, exp.getMessage());throw exp;

}catch(SQLException exp) {

AppException exp = new AppException();exp.addError(Constants.ERROR_CODE, "EXP011");exp.addError(Constants.ERROR_MESG, exp.getMessage());throw exp;

}catch(Exception exp) { AppException exp = new AppException();

exp.addError(Constants.ERROR_CODE, "EXP003");exp.addError(Constants.ERROR_MESG, exp.getMessage());throw exp;

}

Page 32: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Refactor common code in private method

private AppException createAppException(String errorCode) {AppException exp = new AppException();exp.addError(Constants.ERROR_CODE, errorCode);exp.addError(Constants.ERROR_MESG, exp.getMessage());return exp;

}

//codecatch(InterruptedException exp) {

throw createAppException("EXP005");}catch(SQLException exp) {

throw createAppException("EXP011");}catch(Exception exp) {

throw createAppException("EXP003");}

Page 33: Clean code in Java, Java EE: How to get rid of code and design debt

Initializing constant values multiple times

public class Constants {ResourceBundle resbundle; //read from properties file

public static String TIMEOUT =resbundle.getProperty("TIMEOUT");

}

Every time Constants.TIMEOUT is referred, it will fetch the property from the file.

Page 34: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Declare constants with final keyword

public class Constants {ResourceBundle resbundle; //read from properties file

public static final String TIMEOUT =resbundle.getProperty("TIMEOUT");

}

Final variables are initialized only once

Page 35: Clean code in Java, Java EE: How to get rid of code and design debt

Collections

Page 36: Clean code in Java, Java EE: How to get rid of code and design debt

1. Not using generics, Use of Iterator

private List getTableColumns(Map tableFieldListMap) {Set tables = tableFieldListMap.keySet();Iterator iterator = tables.iterator();while(iterator.hasNext()) {

String tableName = (String)iterator.next();...

}}

Page 37: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use generics, for..each loop

private List<String> getTableColumns(Map<String,Field> tableFieldListMap) {for(String tableName : tableFieldListMap.keySet()) {

...}...

}

Page 38: Clean code in Java, Java EE: How to get rid of code and design debt

2. Using collection framework classes as method parameters and

variablesprivate ArrayList fieldDetails = new ArrayList();private HashMap linkedFields = new HashMap();

private void setTransactionParams(Hashtable params) {...

}

Page 39: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use collection framework interfaces, use generics

private List<Field> fieldDetails = new ArrayList<>();private Map<String,FieldProperties> linkedFields = new

HashMap<>();

private void setTransactionParams(Map<String,Object> params) {...

}

Page 40: Clean code in Java, Java EE: How to get rid of code and design debt

3. Collections.synchronizedMappublic class ServiceLocator {

Map<String,Object> cache;

public ServiceLocator() {cache = Collections.synchronizedMap(

new HashMap<String, Object>()); }

}

Page 41: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – ConcurrentHashMap has better performance than Collections.synchronizedMappublic class ServiceLocator {

ConcurrentMap<String,Object> cache;

public ServiceLocator() {cache = new ConcurrentHashMap<String, Object>());

}}

Page 42: Clean code in Java, Java EE: How to get rid of code and design debt

4. Use of Hashtable

Map<String,String> parameters = new Hashtable<>();

Page 43: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – ConcurrentHashMap has better performance than Hashtable

Map<String,String> parameters = new ConcurrentHashMap<>();

Page 44: Clean code in Java, Java EE: How to get rid of code and design debt

5. Using classnames as method parameters

private void setParameters(HashMap<String,String> parameters) {

}

Page 45: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use interfaces instead of classes

private void setParameters(Map<String,String> parameters) {

}

Page 46: Clean code in Java, Java EE: How to get rid of code and design debt

Exception Handling

Page 47: Clean code in Java, Java EE: How to get rid of code and design debt

1. Using e.printStackTrace() to print exception stack trace

When log4j is configured in application, do not use e.printStackTrace() as it could print the exception stack trace in log files other than the intended ones.

Page 48: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use logger.fatal to print exception stack trace

logger.fatal(e);

Page 49: Clean code in Java, Java EE: How to get rid of code and design debt

2. Printing exception stack trace on console

When a java class is called from console, exception stack trace is printed on console when an exception occurs.

Page 50: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Print user friendly error messages on console

Printing an exception stack trace on console is of no use if your application is being used by a client. It will keep your client wondering what went wrong.

Instead of printing exception stack trace on console, handle all exceptions and throw a user friendly exception message which tells the client what went wrong and what corrective action needs to be taken to avoid its occurrence.

Page 51: Clean code in Java, Java EE: How to get rid of code and design debt

3. NumberFormatException is not handled when Integer.parseInt() is

called

String strPeriod = null;//read string value for periodint period = Integer.parseInt(strPeriod);

Page 52: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code - While using Integer.parseInt() always remember to

handle NumberFormatException

String strPeriod = null;//read string value for periodint period = 0;try {

int period = Integer.parseInt(strPeriod);}catch(Exception exp) {

…}

Page 53: Clean code in Java, Java EE: How to get rid of code and design debt

4. Logging exception stack trace multiple times

//method 1catch(SQLException exp) {

log.fatal("Exception occurred:", exp);throw exp;

}

//method 2try {

//call method 1}catch(Exception exp) {

log.fatal("Exception occurred:", exp);}

Page 54: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Log exception stack trace only once where it occurs.

//method 1catch(SQLException exp) {

log.fatal("Exception occurred:", exp);throw exp;

}

//method 2try {

//call method 1}catch(Exception exp) {

}

Page 55: Clean code in Java, Java EE: How to get rid of code and design debt

Design Debt

Page 56: Clean code in Java, Java EE: How to get rid of code and design debt

1. Data Access Object (DAO) does multiple things

Anemic EJBs with only transaction boundary

DAO with database manipulation code,

server side pagination andbusiness logic

Page 57: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code - DAO should do only database manipulation

EJB with business logic DAO

Value List Handler for server side pagination

Page 58: Clean code in Java, Java EE: How to get rid of code and design debt

2. Singleton DAO

Session Facade DAO

A single DAO instance is used by multiple Session Façade objects implemented as stateless session beans or POJOs. This slows down application performance as multiple concurrent threads are accessing a single DAO instance.

Page 59: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – DAO should not be singleton

Session Facade DAO

Every Session Façade object (EJB or POJO) can create an instance of DAO.

Page 60: Clean code in Java, Java EE: How to get rid of code and design debt

3. Remote EJB is looked up multiple times in code

for(int i = 0; i < j; i++) {Hashtable<String, String> env = new Hashtable<>();env.put("java.naming.factory.initial",

Environment.APP_INITIAL_CONTEXT_FACTORY);env.put("java.naming.provider.url", Environment.APP_CONTEXT_FACTORY_URL);Context ctx = new InitialContext(env);home = (FeedUploadEJBRemote)ctx.lookup("FeedUploadEJB");…

}

Page 61: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use Service Locator if you are using EJB 2.x with local/remote

client or EJB 3.x with remote client

Client Service Locator

EJB lookup

EJB object

Page 62: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – For EJB 3.x with local client use Dependency

Injection

@EJBprivate FeedUpload feedUpload;

Page 63: Clean code in Java, Java EE: How to get rid of code and design debt

4. Database calls to fetch static values are made within while loop

while(condition) {sleepTime = genericDao.getStaticValue("SLEEP_TIME");

}

Page 64: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Use a cache to store static values. They should read from database only

once ideally during the start of the application. When the static values are modified they should be simultaneously

written in both cache and database. A pub-sub design can also be used to periodically

update cache.

Cache DAOClient

Page 65: Clean code in Java, Java EE: How to get rid of code and design debt

5. Tightly coupled DAOs

EmployeeDAO DepartmentDAO

EmployeeMgmtEJB

Page 66: Clean code in Java, Java EE: How to get rid of code and design debt

Clean Code – Wire DAOs at Service Layer

EmployeeDAO DepartmentDAO

EmployeeMgmtEJB

Page 67: Clean code in Java, Java EE: How to get rid of code and design debt

Thank you!