Code style - ankidroid/Anki-Android GitHub Wiki
Version 1.0, September 2010. Copyright © 2010. Ported from repo
This document lists the recommendations applied to AnkiDroid, an Android project based on Anki.
If you find any error on this document or any inconsistency between the recommendations presented here and the automatic checkstyle and formatter, please open an issue.
Each recommendation is presented as a rule followed by examples
In this document the words must, should and can are used to convey the importance of a recommendation. A must requirement has to be followed, a should is a strong recommendation and a can is a general suggestion.
TODO
Any violation to the guide is allowed if it enhances one of the following, by order of importance (higher levels cannot be sacrificed for lower levels):
- Logical Structure
- Consistency
- Readability
- Ease of modifications
com.company.application.ui
com.sun.eng
edu.cmu.cs.bovik.cheese
class Line;
class AudioSystem;
int age;
float availableWidth;
private long mLongVariable;
private int mIntVariable;
private static MyClass sSingleton;
public static final int SOME_CONSTANT = 42;
public static final int COLOR_RED = 1;
public static final int COLOR_GREEN = 2;
public static final int COLOR_BLUE = 3;
Method names should be verbs in mixed case, with the first letter in lowercase and with the first letter of each internal word capitalized.
getName();
computeTotalWidth();
Functions (methods with a return) should be named after what they return and procedures (void methods) after what they do.
-
employee.getName();
// NOT:employee.getEmployeeName();
-
boolean isLoaded;
// NOT:boolean isNotLoaded; -
boolean isError;
// NOT:boolean isNotError;
-
computeAverage();
// NOT:compAvg(); -
ActionEvent event;
// NOT:ActionEvent e; -
catch (Exception exception) {
// NOT:catch (Exception e) {
-
getCustomerId();
// NOT:getCustomerID(); -
exportHtmlSource();
// NOT:exportHTMLSource();
-
void setView(View view);
// NOT:void setView(View v); -
``// NOT:
void setView(View aView); -
void close(Database database);
// NOT:void close(Database db); -
// NOT:
void close(Database sqliteDB);
-
author.getName();
-
author.setName(name);
-
point.getX();
-
point.setX(3);
is prefix should be used for boolean variables and methods. Alternatively and if it fits better, has, can and should prefixes can be used.
boolean isVisible;
boolean isOpen();
boolean hasLicense();
boolean canEvaluate();
boolean shouldAbort = false;
valueSet.computeAverage();
matrix.computeInverse();
vertex.findNearestVertex();
matrix.findSmallestElement();
node.findShortestPath(Node destinationNode);
initializeViews();
Variables with a large scope should have very descriptive (and usually long) names, variables with a small scope can have short names.
for (int i = 0; i < downloads.size(); i++) {
statements;
}
ArrayList downloads;
int[] points;
int numPoints = points.length();
int employeeNumber;
int comicNumber;
class CustomException extends Exception {
...
}
class MySingletonClass {
private final static MySingletonClass sInstance = new MySingletonClass();
private MySingletonClass() {
...
}
public static MySingletonClass getInstance() { // NOT: get() or instance()...
return sInstance;
}
}
-
<string name="good_example_key">Example value</string>
// NOT:Example value
<TextView android:id="@+id/good_id_example" // NOT: <TextView android:id="@+id/badIdExample"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
/> />
public class ExampleActivity extends Activity {
...
}
Test method names should be composed by a name representing what is being tested and a name stating which specific case is being tested, separated with underscore.
testMethod_specificCase1
testMethod_specificCase2
void testIsDistinguishable_protanopia() {
ColorMatcher colorMatcher = new ColorMatcher(PROTANOPIA)
assertFalse(colorMatcher.isDistinguishable(Color.RED, Color.BLACK))
assertTrue(colorMatcher.isDistinguishable(Color.X, Color.Y))
}
if (condition) {
statements;
...
}
if ((condition1 && condition2)
|| (condition3 && condition4)
||!(condition5 && condition6)) {
doSomethingAboutIt();
}
- Opening brace "{" appears at the end of the same line as the declaration statement.
- Ending brace "}" takes up an entire line by itself and it is intended at the same level that its correspondent opening statement.
- Braces are mandatory, even for single-statements or empty blocks.
class MyClass {
int func() {
if (something) {
// ...
} else if (somethingElse) {
// ...
} else {
// ...
}
}
}
// NOT:
if (condition) body();
if (condition)
body();
-
After and before operators.
-
Before an opening brace.
-
After Java reserved words.
-
After commas.
-
After semicolons in for statements.
-
After any comment identifier.
-
a = (b + c) * d;
// NOT:a=(b+c)*d -
if (true) {
// NOT:if (true){ -
while (true) {
// NOT:while(true) { -
doSomething(a, b, c, d);
// NOT:doSomething(a,b,c,d); -
for (i = 0; i < 10; i++) {
// NOT:for(i=0;i<10;i++){ -
// This is a comment
// NOT://This is a comment
/** // NOT: /**
* This is a javadoc *This is a javadoc
* comment *comment
*/ */
- Between sections of a source file.
- Between class and interface definitions.
- Between the local variables in a method and its first statement.
- Before a block or single-line comment.
- Between logical sections inside a method, to improve readability
if (condition) {
statements;
}
if (condition) {
statements;
} else {
statements;
}
if (condition) {
statements;
} else if (condition) {
statements;
} else {
statements;
}
for (initialization; condition; update) {
statements;
}
while (condition) {
statements;
}
do {
statements;
} while (condition);
switch (condition) {
case ABC:
statements;
// falls through
case DEF:
statements;
break;
case XYZ:
statements;
break;
default:
statements;
break;
}
try {
statements;
} catch (Exception exception) {
statements;
}
try {
statements;
} catch (Exception exception) {
statements;
} finally {
statements;
}
Comments should not be used to compensate for or explain bad code. Tricky or bad code should be rewritten.
// This is a comment NOT: //This is a comment
/** NOT: /**
* This is a javadoc *This is a javadoc
* comment *comment
*/ */
while (true) { // NOT: while (true) {
// Do something // Do something
something(); something();
} }
/**
* Return lateral location of the specified position.
* If the position is unset, NaN is returned.
*
* @param x X coordinate of position.
* @param y Y coordinate of position.
* @param zone Zone of position.
* @return Lateral location.
* @throws IllegalArgumentException If zone is <= 0.
*/
public double computeLocation(double x, double y, int zone)
throws IllegalArgumentException
{
...
}
// Comment spanning
// more than one line.
All public classes and all public and protected methods within public classes should be documented using Javadoc conventions.
If a collection of objects can not be qualified with its type, it should be followed by a comment stating the type of its elements.
private Vector points; // of Point
private Set shapes; // of Shape
For separation comments within differents parts of a file, the following forms should be used (depending on its level of importance):
//*********************
//
//*********************
//---------------------
//
//---------------------
-
// TODO: Calculate the new order
// NOT:// TODO -> Calculate the new order -
// FIXME: Fix the synchronization algorithm
// NOT:fixme: Fix the synchronization algorithm
The TODO comment should be used to indicate pending tasks, code that is temporary, a short-term solution or good enough but not perfect code.
- All logs should be written in English.
- The use of logs in release should be strictly restricted to the necessary ones.
- Logs should be terse but still understandable.
- Logs must never contain private information or protected content.
- System.out.println() or printf (in native code) must never be used.
- The ERROR level should only be used when something fatal has happened, and it is not recoverable
- The WARNING level should be used when something serious and unexpected happened, but you can recover
- The INFORMATIVE level should be used to note something interesting to most people
- The DEBUG level should be used to note what is happening on the device that could be relevant to investigate and debug unexpected behaviours.
- The VERBOSE level should be used for everything else.
- A DEBUG log should be inside an if (LOCAL_LOGD) block.
if (LOCAL_LOGD) {
Timber.d("Debugging application");
}
- A VERBOSE log should be inside an if (LOCAL_LOGV) block.
if (LOCAL_LOGV) {
Timber.v("Infroming about current state");
}
The import statements must follow the package statement. import statements should be sorted by importance, grouped together by packages and leaving one blank line between groups.
The ordering of packages according to their importance is as follows:
- Android imports
- Third parties imports (com, junit, net, org)
- Java imports (java and javax)
- Within each group, the order of imports is alphabetical, considering that capital letters come before lower letters (e.g. Z before a).
import android.widget.TextView;
import android.widget.ToggleButton;
import com.ichi2.utils.DiffEngine;
import com.tomgibara.android.veecheck.util.PrefSettings;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.app.Activity; // NOT: import android.app.*;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
- Class/Interface documentation.
- class or interface statement.
- Class (static) variables in the order public, protected, package (no access modifier), private.
- Instance variables in the order public, protected, package (no access modifier), private.
- Constructors.
- Methods.
- Inner classes.
Android Components (Activity, Service, BroadcastReceiver and ContentProvider) declarations should be organized in the following manner:
- Component documentation.
- class statement.
- Class (static) variables in the order public, protected, package (no access modifier), private.
- Instance variables in the order public, protected, package (no access modifier), private.
- Constructors.
- Lifecycle methods (ordered following the natural lifecycle, from creation to destruction).
- Other methods.
- Inner classes.
If one function calls another, they should be vertically close, and the caller should be above the callee, if at all possible.
Methods that perform similar tasks or have similar naming should be vertically close.
- access modifier: public, protected or private
- abstract
- static
- final
- transient
- volatile
- synchronized
- native
- strictfp
-
public static double square(double a);
// NOT:static public double square(double a);
int level;
int size;
- // NOT:
int level, size;
i++;
j++;
```// NOT: <del>i++; j++;</del>
### Static variables or methods must always be accessed through the class name and never through an instance variable.
`AClass.classMethod(); `// NOT: <DEL>anObject.classMethod();</del>
### The incompleteness of split lines must be made obvious.
```java
totalSum = a + b + c +
d + e;
method(param1, param2,
param3);
setText("Long line split" +
"into two parts.");
-
floatValue = (int) intValue;
// NOT:floatValue = intValue;
-
int[] points = new int[20];
// NOT:int points[] = new int[20];
Variables should be initialized where they are declared and they should be declared in the smallest scope possible.
-
double total = 0.0;
// NOT:double total = 0; -
double speed = 3.0e8;
// NOT:double speed = 3e8; double sum;
sum = (a + b) * 10.0;
-
double probability = 0.5;
// NOT:double probability = .5;
Numerical constants (except, in some cases, -1, 0 and 1) should not be coded directly. Use constants instead.
private static final int TEAM_SIZE = 11;
...
Player[] players = new Player[TEAM_SIZE];
- // NOT:
Player[] players = new Player[11];
-
a = b + c;
// NOT:d = (a = b + c) + r; d = a + r;
The assignment operator should not be used in a place where it can be easily confused with the equality operator.
// NOT:
if (c++ = d++) {
...
}
Parenthesis should be used liberally in expressions involving mixed operators in order to make the precedence clear.
-
if ((a == b) && (c == d))
// NOT:if (a == b && c == d)
If an expression containing a binary operator appears before the ? in the ternary ?: operator, it should be parenthesized.
-
(x >= 0) ? x : -x;
// NOT:x >= 0 ? x : -x;
bool isFinished = (elementNo < 0) || (elementNo > maxElement);
bool isRepeatedEntry = elementNo == lastElement;
if (isFinished || isRepeatedEntry) {
...
}
// NOT:
if ((elementNo < 0) || (elementNo > maxElement)|| elementNo == lastElement) {
...
}
boolean isOk = openDatabase(databasePath);
if (isOk) {
...
} else {
...
}
InputStream stream = File.open(fileName, "w");
if (stream != null) {
...
}
// NOT:
if (File.open(fileName, "w") != null)) {
...
}
maxim = -1; // NOT: for (i = 0, maxim = -1; i < 100; i++) {
for (i = 0; i < 100; i++) { maxim = max(maxim, value[i]);
maxim = max(maxim, value[i]); }
}
boolean isFound = false; // NOT: boolean isFound = false;
while (!isFound) { ...
... while (!isFound) {
} ...
}
// NOT:
void setServerPort(String value) {
try {
serverPort = Integer.parseInt(value);
} catch (NumberFormatException e) {
}
}
try {
someComplicatedIOFunction(); // may throw IOException
someComplicatedParsingFunction(); // may throw ParsingException
someComplicatedSecurityFunction(); // may throw SecurityException
} catch (IOException exception) {
handleIOError();
} catch (ParsingException exception) {
handleParsingError();
} catch (SecurityException exception) {
handleSecurityError();
}
// NOT:
try {
someComplicatedIOFunction(); // may throw IOException
someComplicatedParsingFunction(); // may throw ParsingException
someComplicatedSecurityFunction(); // may throw SecurityException
} catch (Exception exception) {
handleError();
}
At the same level of the element's name, it should only appear the xmlns attribute or the id attribute, in this order.
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/example_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<RelativeLayout android:id="@+id/example_id"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<RelativeLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
// NOT:
<RelativeLayout android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<RelativeLayout android:id="@+id/example_id"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
>
<EditText android:id="@+id/answer_field" // NOT: <EditText android:id="@+id/answer_field"
android:layout_width="fill_parent" android:layout_width="fill_parent" android:layout_height="wrap_content"
android:layout_height="wrap_content" android:maxLines="2" android:visibility="gone"/>
android:maxLines="2"
android:visibility="gone"
/>
Attributes should be grouped by type (layout properties, text properties…) and within the same type, they should be ordered alphabetically.
<TextView android:id="@+id/example_id"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textColor="#ffffff"
android:textSize="24sp"
/>
// NOT:
<TextView android:id="@+id/example_id"
android:layout_height="wrap_content"
android:textColor="#ffffff"
android:layout_width="fill_parent"
android:textSize="24sp"
/>
<TextView android:id="@+id/example_id"
android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:textSize="24sp"
android:textColor="#ffffff"
/>
<LinearLayout // NOT: <LinearLayout
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" >
>
We avoid using experimental features in languages as a general rule.
As an exception - it may be that an experimental feature is nearing general release - that is the API for it is known to be fixed and stable, at which point use of the feature may be accepted if there is a compelling technical reason to do so.
What | Naming Convention | GOOD Examples | BAD Examples |
---|---|---|---|
Package | lower case | com.company.application.ui | com.company.Application.Ui |
Class | nouns, mixed case, starting with uppercase | AudioSystem | audioSystem |
Variable | mixed case, starting in lowercase | availableWidth | AvailableWidth, available_width |
Non-public, non-static field | mixed case, starting with "m" | mLongVariable | longVariable, LongVariable |
Static field | mixed case, starting with "s" | sSingleton | singleton, staticVariable |
Constant | uppercase, using underscore to separate words | SOME_CONSTANT | some_constant |
Method | verbs, mixed case, starting with lowercase | getName() | get_name() |
String key | lowercase, using underscore to separate words | good_example_key | badExampleKey |
XML element identifier | lowercase, using underscore to separate words | good_id_example | badIdExample |
120 characters
Wrapping lines: 8 spaces with no tabs Braces style 1TBS braces style: class declarations, method declarations, block statements
Between sections of a source file Between class and interface definitions
Between methods
Between local variables in a method and its first statement Before a block or single-line comment Between logical sections inside a method
Copyright/ID comment package declaration import statements
Class/Interface documentation class or interface statement Class (static) variables in the order public, protected, package (no access modifier), private Instance variables in the order public, protected, package (no access modifier), private Constructors Methods Inner classes
Component documentation class statement Class (static) variables in the order public, protected, package (no access modifier), private Instance variables in the order public, protected, package (no access modifier), private Constructors Lifecycle methods (ordered following the natural lifecycle, from creation to destruction) Other methods Inner classes
Android imports, third parties imports (alphabetically), Java imports (java and javax)
public protected private abstract static final transient volatile synchronized native strictfp
- [1] Code Complete, Steve McConnel - Microsoft Press
- [2] Clean Code, Robert C. Martin - Prentice Hall
- [3] Java Coding Style Guide, Achut Reddy - Sun Microsystems, Inc. http://cs.bilgi.edu.tr/pages/standards%5Fproject/java%5FCodingStyle.pdf
- [4] Java Code Conventions http://java.sun.com/docs/codeconv/html/CodeConvTOC.doc.html
- [5] Android Code Style Guidelines for Contributors http://source.android.com/source/code-style.html
- [6] Coding Standards for Java from Geosoft http://geosoft.no/development/javastyle.html