Friday 16 January 2015

Write Standards Code in (Java/Android)




Conventions

We follow standard Java coding conventions. We add a few Android specific rules.

Package and Import Statements

The first non-comment line of most Java source files is a package statement. After that, import statements can follow. For example:

package java.awt;

import java.awt.peer.CanvasPeer;

Order Import Statements

The ordering of import statements is:

1.     Android imports

2.     Imports from third parties (com, junit, net, org)

3.     java and javax

To exactly match the IDE settings, the imports should be:

·         Alphabetical within each grouping, with capital letters before lower case letters (e.g. Z before a).

·         There should be a blank line between each major grouping (android, com, junit, net, org, java, javax).

Fully Qualify Imports

When you want to use class Bar from package foo, there are two possible ways to import it:

import foo.*; import foo.Bar;

Use the latter for importing all Android code. An explicit exception is made for java standard libraries (java.util.*, java.io.*, etc.) and unit test code (junit.framework.*)

Number per Line

One declaration per line is recommended since it encourages commenting. In other words,

int level; // indentation level int size; // size of table

Class and Interface Declarations

When coding Java classes and interfaces, the following formatting rules should be followed:

No space between a method name and the parenthesis “(“ starting its parameter list

Open brace “{” appears at the end of the same line as the declaration statement

  Closing brace “}” starts a line by itself indented to match its corresponding opening statement, except when it is a null statement the “}” should appear immediately after the “{“

class Sample extends Object { int ivar1;

int ivar2;

Sample(int i, int j) { ivar1 = i;

ivar2 = j;

}

int emptyMethod() {}

...

}

·         Methods are separated by a blank line

Use Spaces for Indentation

We use 4 space indents for blocks. We never use tabs. When in doubt, be consistent with code around you.

We use 8 space indents for line wraps, including function calls and assignments. For example, this is correct:

Instrument i =

someLongExpression(that, wouldNotFit, on, one, line);

and this is not correct:

Instrument i =

someLongExpression(that, wouldNotFit, on, one, line);

Follow Field Naming Conventions

·         Non-public, non-static field names start with m.

·         Static field names start with s.

·         Other fields start with a lower case letter.

·         Public static final fields (constants) are ALL_CAPS_WITH_UNDERSCORES.

For example:

public class MyClass {

public static final int SOME_CONSTANT = 42; public int publicField;

private static MyClass sSingleton; int mPackagePrivate;

private int mPrivate; protected int mProtected;

}
Naming Conventions
Naming conventions make programs more understandable by making them easier to read. They can also give information about the function of the identifier-for example, whether it's a constant, package, or class-which can be helpful in understanding the code.


Identifier
Rules for Naming
Examples

Type









The prefix of a unique package name is always written in all-



lowercase ASCII letters and should be one of the top-level



domain names, currently com, edu, gov, mil, net, org, or one



of the English two-letter codes identifying countries as



specified in ISO Standard 3166, 1981.
com.sun.eng

Packages
Subsequent components of the package name vary
com.apple.quicktime.v2


edu.cmu.cs.bovik.cheese


according to an organization's own internal naming





conventions. Such conventions might specify that certain



directory name components be division, department, project,



machine, or login names.







Class names should be nouns, in mixed case with the first



letter of each internal word capitalized. Try to keep your class
class Raster;


names simple and descriptive. Use whole words-avoid


class ImageSprite;

Classes
acronyms and abbreviations (unless the abbreviation is much




more widely used than the long form, such as URL or HTML).






Interfaces
Interface names should be capitalized like class names and
interface IDelegate;

always prefix with capital “I”.
interface IStoring;








Methods should be verbs, in mixed case with the first letter
run();

Methods
lowercase, with the first letter of each internal word
runFast();


capitalized.
getBackground();






Except for variables, all instance, class, and class constants



are in mixed case with a lowercase first letter. Internal words



start with capital letters. Variable names should not start with



underscore _ or dollar sign $ characters, even though both



are allowed.
int i;


Variable names should be short yet meaningful. The choice
char c;

Variables
of a variable name should be mnemonic- that is, designed to
float myWidth;





indicate to the casual observer the intent of its use. One-



character variable names should be avoided except for



temporary "throwaway" variables. Common names for



temporary variables are i, j, k, m, and n for integers; c, d,



and e for characters.







The names of variables declared class constants and of
static final int

Constants
ANSI constants should be all uppercase with words
MIN_WIDTH = 4;

separated by underscores ("_"). (ANSI constants should be
static final int




avoided, for ease of debugging.)
MAX_WIDTH = 999;






Use Standard Brace Style

Braces do not go on their own line; they go on the same line as the code before them. So:

class MyClass { int func() {

if (something) {

//  ...

} else if (somethingElse) {

//  ...

} else {

//  ...

}

}

}


Comment Formats

·         Block comments are used to provide descriptions of files, methods, data structures and algorithms.

·         Short comments can appear on a single line indented to the level of the code that follows.

·         Very short comments can appear on the same line as the code they describe, but should be shifted far enough to separate them from the statements.

·         The // comment delimiter can comment out a complete line or only a partial line. It shouldn't be used on consecutive multiple lines for text comments; however, it can be used in consecutive multiple lines for commenting out sections of code.




Don't Ignore Exceptions

Sometimes it is tempting to write code that completely ignores an exception like this:

void setServerPort(String value) { try {

serverPort = Integer.parseInt(value); } catch (NumberFormatException e) { }

}

You must never do this. While you may think that your code will never encounter this error condition or that it is not important to handle it, ignoring exceptions like above creates mines in your code for someone else to trip over some day. You must handle every Exception in your code in some principled way. The specific handling varies depending on the case.

Acceptable alternatives (in order of preference) are:

·         Throw the exception up to the caller of your method.

void setServerPort(String value) throws NumberFormatException { serverPort = Integer.parseInt(value);

}

·         Throw a new exception that's appropriate to your level of abstraction.

void setServerPort(String value) throws ConfigurationException {

try {

serverPort = Integer.parseInt(value); } catch (NumberFormatException e) {

throw new ConfigurationException("Port " + value + " is not valid.");

}

}

·         Handle the error gracefully and substitute an appropriate value in the catch {} block.

/** Set port. If value is not a valid number, 80 is substituted. */

void setServerPort(String value) { try {

serverPort = Integer.parseInt(value); } catch (NumberFormatException e) {

serverPort = 80;  // default port for server

}

}

·         Last resort: if you are confident that actually ignoring the exception is appropriate then you may ignore it, but you must also comment why with a good reason:

/** If value is not a valid number, original port number is used. */ void setServerPort(String value) {

try {

serverPort = Integer.parseInt(value); } catch (NumberFormatException e) {

//  Method is documented to just ignore invalid user input.

//  serverPort will just be unchanged.

}

}




Don't Catch Generic Exception

Sometimes it is tempting to be lazy when catching exceptions.

Alternatives to catching generic Exception:

·         Catch each exception separately as separate catch blocks after a single try. This can be awkward but is still preferable to catching all Exceptions. Beware repeating too much code in the catch blocks.

·         Refactor your code to have more fine-grained error handling, with multiple try blocks. Split up the IO from the parsing, handle errors separately in each case.

·         Rethrow the exception. Many times you don't need to catch the exception at this level anyway, just let the method throw it.


Use Javadoc Standard Comments


Every file should have a copyright statement at the top. Then a package statement and import statements should follow, each block separated by a blank line. And then there is the class or interface declaration. In the Javadoc comments, describe what the class or interface does.

/*

*  Copyright (C) 2010 The Android Open Source Project

*          
*  Licensed under the Apache License, Version 2.0 (the "License");

*  you may not use this file except in compliance with the License.

*  You may obtain a copy of the License at

*

*         http://www.apache.org/licenses/LICENSE-2.0

*          
*  Unless required by applicable law or agreed to in writing, software

*  distributed under the License is distributed on an "AS IS" BASIS,

*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

*  See the License for the specific language governing permissions and

*  limitations under the License.

*/

package com.android.internal.foo;

import android.os.Blah; import android.view.Yada;

import java.sql.ResultSet; import java.sql.SQLException;

/**

* Does X and Y and provides an abstraction for Z. */

public class Foo {

...

}
Every class and nontrivial public method you write must contain a Javadoc comment with at least one sentence describing what the class or method does. This sentence should start with a 3rd person descriptive verb.


Examples:
 /** Returns the correctly rounded positive square root of a double value. */ static double sqrt(double a) {

...

}

or

/**

*  Constructs a new String by converting the specified array of

*  bytes using the platform's default character encoding.

*/

public String(byte[] bytes) {

...

}


You do not need to write Javadoc for trivial get and set methods such as setFoo() if all your Javadoc would say is "sets Foo". If the method does something more complex (such as enforcing a constraint or having an important side effect), then you must document it. And if it's not obvious what the property "Foo" means, you should document it.

Every method you write, whether public or otherwise, would benefit from Javadoc. Public methods are part of an API and therefore require Javadoc.


Limit Variable Scope


The scope of local variables should be kept to a minimum. Each variable should be declared in the innermost block that encloses all uses of the variable.

Local variables should be declared at the point they are first used. Nearly every local variable declaration should contain an initializer. If you don't yet have enough information to initialize a variable sensibly, you should postpone the declaration until you do.

One exception to this rule concerns try-catch statements. If a variable is initialized with the return value of a method that throws a checked exception, it must be initialized inside a try block. If the value must be used outside of the try block, then it must be declared before the try block, where it cannot yet be sensibly initialized:

// Instantiate class cl, which represents some sort of Set Set s = null;

try {

s = (Set) cl.newInstance();

} catch(IllegalAccessException e) {

throw new IllegalArgumentException(cl + " not accessible"); } catch(InstantiationException e) {

throw new IllegalArgumentException(cl + " not instantiable");

}

// Exercise the set s.addAll(Arrays.asList(args));

But even this case can be avoided by encapsulating the try-catch block in a method:

Set createSet(Class cl) {

// Instantiate class cl, which represents some sort of Set try {

return (Set) cl.newInstance(); } catch(IllegalAccessException e) {

throw new IllegalArgumentException(cl + " not accessible"); } catch(InstantiationException e) {

throw new IllegalArgumentException(cl + " not instantiable");

}

}

...

// Exercise the set Set s = createSet(cl);

s.addAll(Arrays.asList(args));


Loop variables should be declared in the for statement itself unless there is a compelling reason to do otherwise:

for  (int i = 0; i n; i++) { doSomething(i);

}

and

for  (Iterator i = c.iterator(); i.hasNext(); ) { doSomethingElse(i.next());

}

Treat Acronyms as Words


Treat acronyms and abbreviations as words in naming variables, methods, and classes. The names are much more readable:

Good
Bad
XmlHttpRequest
XMLHTTPRequest
getCustomerId
getCustomerID
class Html
class HTML
String url
String URL
long id
long ID

Both the JDK and the Android code bases are very inconsistent with regards to acronyms, therefore, it is virtually impossible to be consistent with the code around you.

Use TODO Comments


Use TODO comments for code that is temporary, a short-term solution, or good-enough but not perfect.

TODOs should include the string TODO in all caps, followed by a colon:

// TODO: Remove this code after the UrlTable2 has been checked in.

and

// TODO: Change this to use a flag instead of a constant.


If your TODO is of the form "At a future date do something" make sure that you either include a very specific date ("Fix by November 2005") or a very specific event ("Remove this code after all production mixers understand protocol V7.").

Sources