TAAFT
Free mode
100% free
Freemium
Free Trial
Deals

Alibaba Java Coding Guidelines

alibaba / Alibaba-Java-Coding-Guidelines

Gitbook for AJCG

1,052 243 Language: null Updated: 2d ago

README

Table of Contents

Preface

We are pleased to present Alibaba Java Coding Guidelines, which consolidates the best programming practices from Alibaba Group's technical teams. A vast number of Java programming teams impose demanding requirements on code quality across projects as we encourage reuse and better understanding of each other's programs. We have seen many programming problems in the past. For example, defective database table structures and index designs may cause software architecture flaws and performance risks. As another example, confusing code structures make it difficult to maintain. Furthermore, vulnerable code without authentication is prone to hackers’ attacks. To address those kinds of problems, we developed this document for Java developers in Alibaba.

This document consists of five parts: Programming Specification, Exception and Logs, MySQL Specification, Project Specification and Security Specification. Based on the severity of the concerns, each specification is classified into three levels: Mandatory, Recommended and Reference. Further clarification is expressed in:
(1) "Description", which explains the content;
(2) "Positive examples", which describe recommended coding and implementation approaches;
(3) "Counter examples", which describe precautions and actual error cases.

The main purpose of this document is to help developers improve code quality. As a result, developers can minimize potential and repetitive code errors. In addition, specification is essential to modern software architectures, which enable effective collaborations. As an analogy, traffic regulations are intended to protect public safety rather than to deprive the rights of driving. It is easy to imagine the chaos of traffic without speed limits and traffic lights. Instead of destroying the creativity and elegance of program, the purpose of developing appropriate specification and standards of software is to improve the efficiency of collaboration by limiting excessive personalization.

We will continue to collect feedback from the community to improve Alibaba Java Coding Guidelines.

1. Programming Specification

Naming Conventions

1. [Mandatory] Names should not start or end with an underline or a dollar sign.

Counter example: _name / __name / \$Object / name_ / name\$ / Object\$

2. [Mandatory] Using Chinese, Pinyin, or Pinyin-English mixed spelling in naming is strictly prohibited. Accurate English spelling and grammar will make the code readable, understandable, and maintainable.

Positive example: alibaba / taobao / youku / Hangzhou. In these cases, Chinese proper names in Pinyin are acceptable.

3. [Mandatory] Class names should be nouns in UpperCamelCase except domain models: DO, BO, DTO, VO, etc.

Positive example: MarcoPolo / UserDO / HtmlDTO / XmlService / TcpUdpDeal / TaPromotion
Counter example: marcoPolo / UserDo / HTMLDto / XMLService / TCPUDPDeal / TAPromotion

4. [Mandatory] Method names, parameter names, member variable names, and local variable names should be written in lowerCamelCase.

Positive example: localValue / getHttpMessage() / inputUserId

5. [Mandatory] Constant variable names should be written in upper characters separated by underscores. These names should be semantically complete and clear.

Positive example: MAX_STOCK_COUNT
Counter example: MAX_COUNT

6. [Mandatory] Abstract class names must start with Abstract or Base. Exception class names must end with Exception. Test case names shall start with the class names to be tested and end with Test.

7. [Mandatory] Brackets are a part of an Array type. The definition could be: String[] args;

Counter example: String args[];

8. [Mandatory] Do not add 'is' as prefix while defining Boolean variable, since it may cause a serialization exception in some Java frameworks.

Counter example: boolean isSuccess; The method name will be isSuccess() and then RPC framework will deduce the variable name as 'success', resulting in a serialization error since it cannot find the correct attribute.

9. [Mandatory] A package should be named in lowercase characters. There should be only one English word after each dot. Package names are always in singular format while class names can be in plural format if necessary.

Positive example: com.alibaba.open.util can be used as a package name for utils;
MessageUtils can be used as a class name.

10. [Mandatory] Uncommon abbreviations should be avoided for the sake of legibility.

Counter example: AbsClass (AbstractClass); condi (Condition)

11. [Recommended] The pattern name is recommended to be included in the class name if any design pattern is used.

Positive example: public class OrderFactory;
public class LoginProxy; public class ResourceObserver;
Note: Including corresponding pattern names helps readers understand ideas in design patterns quickly.

12. [Recommended] Do not add any modifier, including public, to methods in interface classes for coding simplicity. Please add valid Javadoc comments for methods. Do not define any variables in the interface except for the common constants of the application.

Positive example: method definition in the interface: void f();
constant definition: String COMPANY = "alibaba";
Note: In JDK8 it is allowed to define a default implementation for interface methods, which is valuable for all implemented classes.

13. There are two main rules for interface and corresponding implementation class naming:
  1) [Mandatory] All Service and DAO classes must be interfaces based on SOA principle. Implementation class names should end with Impl.

Positive example: CacheServiceImpl to implement CacheService.

  2) [Recommended] If the interface name is to indicate the ability of the interface, then its name should be an adjective.

Positive example: AbstractTranslator to implement Translatable.

14. [For Reference] An Enumeration class name should end with Enum. Its members should be spelled out in upper case words, separated by underlines.

Note: Enumeration is indeed a special constant class and all constructor methods are private by default.
Positive example: Enumeration name: DealStatusEnum; Member name: SUCCESS / UNKOWN_REASON.

15. [For Reference] Naming conventions for different package layers:
  A) Naming conventions for Service/DAO layer methods
    1) Use get as name prefix for a method to get a single object.
    2) Use list as name prefix for a method to get multiple objects.
    3) Use count as name prefix for a statistical method.
    4) Use insert or save (recommended) as name prefix for a method to save data.
    5) Use delete or remove (recommended) as name prefix for a method to remove data.
    6) Use update as name prefix for a method to update data.
  B) Naming conventions for Domain models
    1) Data Object: *DO, where * is the table name.
    2) Data Transfer Object: *DTO, where * is a domain-related name.
    3) Value Object: *VO, where * is a website name in most cases.
    4) POJO generally point to DO/DTO/BO/VO but cannot be used in naming as *POJO.

Constant Conventions

1. [Mandatory] Magic values, except for predefined, are forbidden in coding.

Counter example: String key = "Id#taobao_" + tradeId;

2. [Mandatory] 'L' instead of 'l' should be used for long or Long variable because 'l' is easily to be regarded as number 1 in mistake.

Counter example: Long a = 2l, it is hard to tell whether it is number 21 or Long 2.

3. [Recommended] Constants should be placed in different constant classes based on their functions. For example, cache related constants could be put in CacheConsts while configuration related constants could be kept in ConfigConsts.

Note: It is difficult to find one constant in one big complete constant class.

4. [Recommended] Constants can be shared in the following 5 different layers: shared in multiple applications; shared inside an application; shared in a sub-project; shared in a package; shared in a class.
  1) Shared in multiple applications: keep in a library, under constant directory in client.jar;
  2) Shared in an application: keep in shared modules within the application, under constant directory;
  Counter example: Obvious variable names should also be defined as common shared constants in an application. The following definitions caused an exception in the production environment: it returns false, but is expected to return true for A.YES.equals(B.YES).
  Definition in Class A: public static final String YES = "yes";
  Definition in Class B: public static final String YES = "y";
  3) Shared in a sub-project: placed under constant directory in the current project;
  4) Shared in a package: placed under constant directory in current package;
  5) Shared in a class: defined as 'private static final' inside class.

5. [Recommended] Use an enumeration class if values lie in a fixed range or if the variable has attributes. The following example shows that extra information (which day it is) can be included in enumeration:

Positive example: public Enum{ MONDAY(1), TUESDAY(2), WEDNESDAY(3), THURSDAY(4), FRIDAY(5), SATURDAY(6), SUNDAY(7);}

Formatting Style

1. [Mandatory] Rules for braces. If there is no content, simply use {} in the same line. Otherwise:
  1) No line break before the opening brace.
  2) Line break after the opening brace.
  3) Line break before the closing brace.
  4) Line break after the closing brace, only if the brace terminates a statement or terminates a method body, constructor or named class. There is no line break after the closing brace if it is followed by else or a comma.

2. [Mandatory] No space is used between the '(' character and its following character. Same for the ')' character and its preceding character. Refer to the Positive Example at the 5th rule.

3. [Mandatory] There must be one space between keywords, such as if/for/while/switch, and parentheses.

4. [Mandatory] There must be one space at both left and right side of operators, such as '=', '&&', '+', '-', ternary operator, etc.

5. [Mandatory] Each time a new block or block-like construct is opened, the indent increases by four spaces. When the block ends, the indent returns to the previous indent level. Tab characters are not used for indentation.

Note: To prevent tab characters from being used for indentation, you must configure your IDE. For example, "Use tab character" should be unchecked in IDEA, "insert spaces for tabs" should be checked in Eclipse.
Positive example:

public static void main(String[] args) {
// four spaces indent
String say = "hello";
// one space before and after the operator
int flag = 0;
// one space between 'if' and '('; 
// no space between '(' and 'flag' or between '0' and ')'
if (flag == 0) {
System.out.println(say);
}
// one space before '{' and line break after '{'
if (flag == 1) {
System.out.println("world");
// line break before '}' but not after '}' if it is followed by 'else'
} else {  
System.out.println("ok");
// line break after '}' if it is the end of the block
}
}

6. [Mandatory] Java code has a column limit of 120 characters. Except import statements, any line that would exceed this limit must be line-wrapped as follows:
  1) The second line should be intented at 4 spaces with respect to the first one. The third line and following ones should align with the second line.
  2) Operators should be moved to the next line together with following context.
  3) Character '.' should be moved to the next line together with the method after it.
  4) If there are multiple parameters that extend over the maximum length, a line break should be inserted after a comma.
  5) No line breaks should appear before parentheses.

Positive example:

StringBuffer sb = new StringBuffer();
// line break if there are more than 120 characters, and 4 spaces indent at
// the second line. Make sure character '.' moved to the next line 
// together.  The third and fourth lines are aligned with the second one. 
sb.append("zi").append("xin").
.append("huang")...
.append("huang")...
.append("huang");

Counter example:

StringBuffer sb = new StringBuffer();
// no line break before '('
sb.append("zi").append("xin")...append
("huang");  
// no line break before ',' if there are multiple params
invoke(args1, args2, args3, ...
, argsX);

7. [Mandatory] There must be one space between a comma and the next parameter for methods with multiple parameters.

Positive example: One space is used after the ',' character in the following method definition.

f("a", "b", "c");

8. [Mandatory] The charset encoding of text files should be UTF-8 and the characters of line breaks should be in Unix format, instead of Windows format.

9. [Recommended] It is unnecessary to align variables by several spaces.

Positive example:

int a = 3;
long b = 4L;
float c = 5F;
StringBuffer sb = new StringBuffer();

Note: It is cumbersome to insert several spaces to align the variables above.

10. [Recommended] Use a single blank line to separate sections with the same logic or semantics.

Note: It is unnecessary to use multiple blank lines to do that.

OOP Rules

1. [Mandatory] A static field or method should be directly referred to by its class name instead of its corresponding object name.

2. [Mandatory] An overridden method from an interface or abstract class must be marked with @Override annotation.

Counter example: For getObject() and get0bject(), the first one has a letter 'O', and the second one has a number '0'. To accurately determine whether the overriding is successful, an @Override annotation is necessary. Meanwhile, once the method signature in the abstract class is changed, the implementation class will report a compile-time error immediately.

3. [Mandatory] varargs is recommended only if all parameters are of the same type and semantics. Parameters with Object type should be avoided.

Note: Arguments with the varargs feature must be at the end of the argument list. (Programming with the varargs feature is not recommended.)
Positive example:

public User getUsers(String type, Integer... ids);

4. [Mandatory] Modifying the method signature is forbidden to avoid affecting the caller. A @Deprecated annotation with an explicit description of the new service is necessary when an interface is deprecated.

5. [Mandatory] Using a deprecated class or method is prohibited.

Note: For example, decode(String source, String encode) should be used instead of the deprecated method decode(String encodeStr). Once an interface has been deprecated, the interface provider has the obligation to provide a new one. At the same time, client programmers have the obligation to use the new interface.

6. [Mandatory] Since NullPointerException can possibly be thrown while calling the equals method of Object, equals should be invoked by a constant or an object that is definitely not null.

Positive example: "test".equals(object);
Counter example: object.equals("test");
Note: java.util.Objects#equals (a utility class in JDK7) is recommended.

7. [Mandatory] Use the equals method, rather than reference equality ==, to compare primitive wrapper classes.

Note: Consider this assignment: Integer var = ?. When it fits the range from -128 to 127, we can use == directly for a comparison. Because the Integer object will be generated by IntegerCache.cache, which reuses an existing object. Nevertheless, when it fits the complementary set of the former range, the Integer object will be allocated in the heap, which does not reuse an existing object. This is a pitfall. Hence the equals method is recommended.

8. [Mandatory] To judge the equivalence of floating-point numbers, == cannot be used for primitive types, while equals cannot be used for wrapper classes.

Note: Floating-point numbers are composed by mantissa and exponent, which is similar to the coefficient and exponent of scientific notation. Most decimal fractions cannot be represented precisely by binary.

Counter example:

    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8f;

    if (a == b) {
        // seems like this block will be executed
        // but the result of a == b is false
    }

    Float x = Float.valueOf(a);
    Float y = Float.valueOf(b);
    if (x.equals(y)) {
        // seems like this block will be executed
        // but the result of x.equals(y) is false
    }  

Positive example:

(1) Specify an error range. Consider two floating-pointing numbers as equal if the difference between them is within this range.

    float a = 1.0f - 0.9f;
    float b = 0.9f - 0.8f;
    float diff = 1e-6f;

    if (Math.abs(a - b) < diff) {
        System.out.println("true");
    }

(2) Use BigDecimal to operate.

    BigDecimal a = new BigDecimal("1.0");
    BigDecimal b = new BigDecimal("0.9");
    BigDecimal c = new BigDecimal("0.8");

    BigDecimal x = a.subtract(b);
    BigDecimal y = b.subtract(c);

    if (x.equals(y)) {
        System.out.println("true");
    }

9. [Mandatory] Rules for using primitive data types and wrapper classes:
  1) Members of a POJO class must be wrapper classes.
  2) The return value and arguments of a RPC method must be wrapper classes.
  3) [Recommended] Local variables should be primitive data types.
  Note: In order to remind the consumer of explicit assignments, there are no initial values for members in a POJO class. As a consumer, you should check problems such as NullPointerException and warehouse entries for yourself.
  Positive example: As the result of a database query may be null, assigning it to a primitive date type will cause a risk of NullPointerException because of autoboxing.
  Counter example: Consider the output of a transaction volume's amplitude, like ±x%. As a primitive data, when it comes to a failure of calling a RPC service, the default return value: 0% will be assigned, which is not correct. A hyphen like - should be assigned instead. Therefore, the null value of a wrapper class can represent additional information, such as a failure of calling a RPC service, an abnormal exit, etc.

10. [Mandatory] While defining POJO classes like DO, DTO, VO, etc., do not assign any default values to the members.

11. [Mandatory] To avoid a deserialization failure, do not change the serialVersionUID when a serialized class needs to be updated, such as adding some new members. If a completely incompatible update is needed, change the value of serialVersionUID in case of a confusion when deserialized.

Note: The inconsistency of serialVersionUID may cause an InvalidClassException at runtime.

12. [Mandatory] Business logic in constructor methods is prohibited. All initializations should be implemented in the init method.

13. [Mandatory] The toString method must be implemented in a POJO class. The super.toString method should be called in in the beginning of the implementation if the current class extends another POJO class.

Note: We can call the toString method in a POJO directly to print property values in order to check the problem when a method throws an exception in runtime.

14. [Recommended] When accessing an array generated by the split method in String using an index, make sure to check the last separator whether it is null to avoid IndexOutOfBoundException.

Note:

String str = "a,b,c,,";
String[] ary = str.split(",");
// The expected result exceeds 3. However it turns out to be 3.
System.out.println(ary.length);  

15. [Recommended] Multiple constructor methods or homonymous methods in a class should be put together for better readability.

16. [Recommended] The order of methods declared within a class is:
public or protected methods -> private methods -> getter/setter methods.

Note: As the most concerned ones for consumers and providers, public methods should be put on the first screen. Protected methods are only cared for by the subclasses, but they have chances to be vital when it comes to Template Design Pattern. Private methods, the black-box approaches, basically are not significant to clients. Getter/setter methods of a Service or a DAO should be put at the end of the class implementation because of the low significance.

17. [Recommended] For a setter method, the argument name should be the same as the field name. Implementations of business logics in getter/setter methods, which will increase difficulties of the troubleshooting, are not recommended.

Counter example:

public Integer getData() {
if (true) {
return data + 100; 
} else {
return data - 100;
}
}

18. [Recommended] Use the append method in StringBuilder inside a loop body when concatenating multiple strings.

Counter example:

String str = "start";
for (int i = 0; i < 100; i++) {
str = str + "hello";
}

Note: According to the decompiled bytecode file, for each loop, it allocates a StringBuilder object, appends a string, and finally returns a String object via the toString method. This is a tremendous waste of memory.

19. [Recommended] Keyword final should be used in the following situations:
  1) A class which is not allow to be inherited, or a local variable not to be reassigned.
  2) An argument which is not allow to be modified.
  3) A method which is not allow to be overridden.

20. [Recommended] Be cautious to copy an object using the clone method in Object.

Note: The default implementation of clone in Object is a shallow (not deep) copy, which copies fields as pointers to the same objects in memory.

21. [Recommended] Define the access level of members in class with severe restrictions:
  1) Constructor methods must be private if an allocation using new keyword outside of the class is forbidden.
  2) Constructor methods are not allowed to be public or default in a utility class.
  3) Nonstatic class variables that are accessed from inheritants must be protected.
  4) Nonstatic class variables that no one can access except the class that contains them must be private.
  5) Static variables that no one can access except the class that contains them must be private.
  6) Static variables should be considered in determining whether they are final.
  7) Class methods that no one can access except the class that contains them must be private.
  8) Class methods that are accessed from inheritants must be protected.

Note: We should strictly control the access for any classes, methods, arguments and variables. Loose access control causes harmful coupling of modules. Imagine the following situations. For a private class member, we can remove it as soon as we want. However, when it comes to a public class member, we have to think twice before any updates happen to it.

Collection

1. [Mandatory] The usage of hashCode and equals should follow:
  1) Override hashCode if equals is overridden.
  2) These two methods must be overridden for elements of a Set since they are used to ensure that no duplicate object will be inserted in Set.
  3) These two methods must be overridden for any object that is used as the key of Map.

Note: String can be used as the key of Map since String defines these two methods.

2. [Mandatory] Do not add elements to collection objects returned by keySet()/values()/entrySet(), otherwise UnsupportedOperationException will be thrown.

3. [Mandatory] Do not add nor remove to/from immutable objects returned by methods in Collections, e.g. emptyList()/singletonList().

Counter example: Adding elements to Collections.emptyList() will throw UnsupportedOperationException.

4. [Mandatory] Do not cast subList in class ArrayList, otherwise ClassCastException will be thrown: java.util.RandomAccessSubList cannot be cast to java.util.ArrayList.

Note: subList of ArrayList is an inner class, which is a view of ArrayList. All operations on the Sublist will affect the original list.

5. [Mandatory] When using subList, be careful when modifying the size of original list. It might cause ConcurrentModificationException when performing traversing, adding or deleting on the subList.

6. [Mandatory] Use toArray(T[] array) to convert a list to an array. The input array type should be the same as the list whose size is list.size().

Counter example: Do not use toArray method without arguments. Since the return type is Object[], ClassCastException will be thrown when casting it to a different array type.
Positive example:

List list = new ArrayList(2);
list.add("guan");
list.add("bao");        
String[] array = new String[list.size()];
array = list.toArray(array);

Note: When using toArray method with arguments, pass an input with the same size as the list. If input array size is not large enough, the method will re-assign the size internally, and then return the address of new array. If the size is larger than needed, extra elements (index[list.size()] and later) will be set to null.

7. [Mandatory] Do not use methods which will modify the list after using Arrays.asList to convert array to list, otherwise methods like add/remove/clear will throw UnsupportedOperationException.

Note: The result of asList is the inner class of Arrays, which does not implement methods to modify itself. Arrays.asList is only a transferred interface, data inside which is stored as an array.

String[] str = new String[] { "a", "b" };
List list = Arrays.asList(str); 

Case 1: list.add("c"); will throw a runtime exception.
Case 2: str[0]= "gujin"; list.get(0) will be modified.

8. [Mandatory] Method add cannot be used for generic wildcard with `

0 AIs selected
Clear selection
#
Name
Task