Coding Style

Coding style is an important part of writing professional, production ready code. It directly affects the comfort of work and should be kept consistent. At RST IT we maintain consistent style across all our projects by enforcing strict rules for iOS and Android apps.

iOS

Our iOS developers chose The Official raywenderlich.com Swift Style Guide as the official coding style for iOS applications. We didn't make any changes to it, thus it won't be described in details here.

Android

Our code guideline is based on the Android Open Source Project code guideline that can be found here.

The code styles below are strict rules, not guidelines or recommendations. We recognise that not all the existing code follows these rules, but we expect all the new code to be compliant.

Don't Ignore Exceptions

void setServerPort(String value) {  
    try {
        serverPort = Integer.parseInt(value);
    }
    catch (NumberFormatException e) {
    }
}

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.
void setServerPort(String value) {  
    try {
        serverPort = Integer.parseInt(value);
    }
    catch (NumberFormatException e) {
        serverPort = 80;  // default port for server
    }
}
  • As a last resort, if you are confident that ignoring the exception is appropriate then you may ignore it, but you must also comment why and provide 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

try {  
    someComplicatedIOFunction();        // may throw IOException
    someComplicatedParsingFunction();   // may throw ParsingException
    someComplicatedSecurityFunction();  // may throw SecurityException
    // phew, made it all the way
}
catch (Exception e) {                 // I'll just catch all exceptions  
    handleError();                      // with one generic handler!
}

Do not do this. In almost all cases it is inappropriate to catch generic Exception or Throwable (preferably not Throwable because it includes Error exceptions). It is very dangerous because it means that Exceptions you never expected (including RuntimeExceptions like ClassCastException) get caught in application-level error handling. It obscures the failure handling properties of your code, meaning if someone adds a new type of Exception in the code you're calling, the compiler won't help you realise you need to handle the error differently. In most cases you shouldn't be handling different types of exception the same way.

The rare exception to this rule is test code and top-level code where you want to catch all kinds of errors (to prevent them from showing up in a UI, or to keep a batch job running). In these cases you may catch generic Exception (or Throwable) and handle the error appropriately.

Fully Qualify Imports

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

  • import foo.*; - potentially reduces the number of import statements.
  • import foo.Bar; - makes it obvious what classes are actually used and the code is more readable for maintainers.

Write Short Methods

When feasible, keep methods small and focused. We recognise that long methods are sometimes appropriate, so no hard limit is placed on method length. If a method exceeds 40 lines or so, think whether it can be broken up without harming the structure of the program.

Define Fields in Standard Places

Define fields either at the top of the file or immediately before the methods that use them.

Limit Variable Scope

Keep the scope of local variables to a minimum. By doing so, you increase the readability and maintainability of your code and reduce the likelihood of error. 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 initialiser. If you don't yet have enough information to initialise a variable sensibly, postpone the declaration until you do.

The exception is try-catch statements. If a variable is initialised with the return value of a method that throws a checked exception, it must be initialised 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 initialised.

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 ALLCAPSWITH_UNDERSCORES.
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;
}

Follow View Naming Conventions in XML files

Type Prefix Example
TextView txtv txtvName
EditText edit editName
Button btn btnSave
ImageView imgv imgvAvatar
RecyclerView rv rvResults
View view viewAvatar
ProgressBar pb pbSaveChanges
DrawerLayout drawer drawerMenu
LinearLayout ll llButtonsContainer
FrameLayout fl flButtonsContainer
RelativeLayout rl rlButtonsContainer
ScrollView scroll scrollButtonsContainer

Use Standard Brace Style

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

class MyClass {  
    int func() {
        if (something) {
            // ...
        } else if (somethingElse) {
            // ...
        } else {
            // ...
        }
    }
}

We require braces around the statements for a conditional. Exception: If the entire conditional (the condition and the body) fit in one line, you may (but are not obligated to) put it all in one line. For example, this is acceptable:

if (condition) {  
    body();
}

and this is acceptable:

if (condition) body();  

but this is not acceptable:

if (condition)  
    body();  // bad!

Be Consistent

Our parting thought: BE CONSISTENT. If you're editing code, take a few minutes to look at the surrounding code and determine its style. If that code uses spaces around the if clauses, you should too. If the code comments have little boxes of stars around them, make your comments have little boxes of stars around them too.

The point of having style guidelines is to have a common vocabulary of coding, so people can concentrate on what you're saying, rather than on how you're saying it. We present global style rules here so people know the vocabulary, but local style is also important. If the code you add to a file looks drastically different from the existing code around it, it throws readers out of their rhythm when they start to read it. Try to avoid this.