Wednesday, February 8, 2017

Best Practices for a Java Developer

This document is inspired from popular open source communities' coding standards, such as Spring Framework Code Style and Oracle Java Code Conventions. Some of the ideas also come from this great article : 7 reasons clean code matters.
1. General Development rules for Good Developers
Please don’t:
·       commit code that does NOT even compile. Usually this happens when a developer only checks in part of his work.
·       commit code that can't pass tests. If tests fail, it is recommended to update failed tests before checking in changes. The moment a test failed because of the change you made, is the best time to revisit, refactor the test.
·       comment out code that is now obsolete
·       insert comments around each change.
·       make things public which are not required by end users.
·       Combine multiple issues into a single commit, especially if they are unrelated or only loosely related. This is true even if the changes affect the same files.
Please do:
·       comment code whose function is not obvious;
·       update documentation (e.g., javadoc, this wiki, etc.). All public methods should have javadoc explaining what they do.
·       try to provide a unit test that shows a bug was indeed fixed or the new functionality truly works
·       Applying DRY(don't repeat yourself) Principle whenever possible.
2. Java Code Style
The following things may not necessarily be the best practice, but are widely practiced in the world of developers.
2.1 Source file
2.1.1 File encoding: UTF-8
All source files should be encoded in UTF-8.
2.1.2 Enforced uniform column width: 90
We need to strive for consistent line lengths in all source code we write. An industry standard is 80 characters per line. Google recommends 80 or 100 characters per line. Let's make it 90, same as Spring Framework.
2.1.3 Indentation
The issue of using hard tabs or spaces is an ongoing debate in the programming community. Some programmers feel that spaces instead of tabs increase cross-platform functionality. Others, believe the opposite, that hard tabs increase cross-platform functionality.
This is what Spring Framework does
·       Indentation uses tabs (not spaces)
·       Unix (LF), not DOS (CRLF) line endings
·       Eliminate all trailing whitespace
2.1.4 Formatting
Braces mostly follow the Kernighan and Ritchie style (a.k.a., "Egyptian brackets") for nonempty blocks and block-like constructs
·       No line break before the opening brace but prefixed by a single space
// bad practice : no space before opening brace
if(true){
// implementation
}
// bad practice : link break before opening brace
if(true)
{
// implementation
}
·       Line break after the opening brace
// bad practice: no line break after the opening brace
if(true) { //some statement after opening brace
}
·       Line break before the closing brace
// bad practice : no line break before the closing brace
if(true) {
/*some statement before closing brace*/}
// This is good practice
if(true) {
// implementation
}
2.1.5 Naming
·       Constant names use CONSTANT_CASE : all uppercase letters, with words separated by underscores. Constants should be static final
public static final int DEFAULT_QUERY_COUNT = 25;
·       Local variables have no rule, but should be meaningful.
Some of the reasons for this naming conversion.
·       within any code blocks, you are able to tell the scope/type of any variables without any effort
·       'this' keyword can be avoided without causing confliction/confusion or compiler errors
2.1.6 Use of @Override
Always add @Override on methods overriding a method declared in a super type.

2.1.8 Source file structure/organization
The following can be an example how a Java class should be written i.e. how and where to declare variables and so on.
1.     static fields
2.     normal fields (instance variables)
3.     constructors
4.     public and private method
5.     static methods (if any. This should be discouraged, because java static breaks OO)
6.     equals, hashCode, and toString()
7.     getters and setters

EmployeeDAO.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
package com.coding.example;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
// more imports ...
/**
* Document goes here
*
* @author Pritam Banerjee
*/
public class EmployeeDAO {
// 1. static fields
private static final Logger LOGGER = LoggerFactory.getLogger(EndecaQuery.class);
// 2. normal fields(instance variables)
private QueryService _service;
// 3. constructor
public EmployeeDAO () {
}
// 4. methods
public Query createQuery() {
// implementation goes here
}
// 6. equals, hashCode, toString()
@Override
public boolean equals(Object argObj) {
// implementation goes here
}
@Override
public int hashCode() {
// implementation goes here
}
@Override
public String toString() {
// implementation goes here
}
// 7. getters and setters
public QueryService getService() {
   return _service;
}
public void setService(QueryService argService) {
   _service = argService;
}
}
2.2 Test
Each test class should end with a 'Test' suffix, e.g. EmployeeDAOTest. It is also recommended, although not strictly required to name the test with a 'test' prefix, e.g. testEmployeeClassType().

No comments:

Post a Comment