Kotlin 🌈
Formatting
Indentation
-
-
- recommendation from Google to use 2 spaces for blocks and 4 spaces for line wraps. So, depending on the start of the project, the team should always follow the base structure.It’s also flexible to change the rules, too, as there is a
Blank Line
-
There must be one blank line after the class declaration and another at the end of the file.
class SomeClass { // Your code }
-
Separate each interface method using a blank line. No need to use a blank line after the interface name.
interface Input { fun firstName(firstName: String) fun lastName(lastName: String) }
Line of Code
Line Breaks
-
If the method declaration exceeds the maximum line length, use a line break before each parameter. For methods with more than two parameters, always use a line break before each one.
fun updatePerson(firstName: String, middleName: String, lastName: String) { // Your code }
fun updatePerson( firstName: String, middleName: String, lastName: String ) { // Your code }
Method calls with more than two arguments are required to have line breaks along with named arguments.
updatePerson( firstName = "John", middleName = "Bob", lastName = "Doe" )
Vertical Spacing
To ensure a good experience during code reviews, developers must maintain consistency in the alignment of their new lines of code with the existing codebase.
Trailing Commas
A trailing comma is a comma symbol placed after the last item of a series of elements:
-
Class properties and parameters:
class Customer( val name: String, val lastName: String, // trailing comma ) class Customer( val name: String, lastName: String, // trailing comma )
-
Function value parameters:
fun powerOf( number: Int, exponent: Int, // trailing comma ) { /*...*/ } constructor( x: Comparable<Number>, y: Iterable<Number>, // trailing comma ) {} fun print( vararg quantity: Int, description: String, // trailing comma ) {}
Unlock the power of trailing commas and enjoy a host of benefits:
The Kotlin style guide encourages using trailing commas, so the team should consider it as optional since the code will still work without them. Therefore, when conducting a code review, kindly avoid asking to add it if it is missing, or refrain from removing it if it is present.
Others
-
Brace style:
fun main() { // Not this }
fun main() { // Your code }
-
Conditional statements are preferred to be enclosed with braces:
if (conditionPassed) doSomething()
if (conditionPassed) { doSomething() } if (someTest) { doSomethingElse() } if (someTest) doSomethingElse() // Still acceptable
For
if/else
blocks where short one-line statements (< max line length) are possible, braces are not required. For example:val someObject = if (isSomethingTrue) thisObject else thatObject if (isSomethingTrue) doSomething() else doSomethingElse()
-
Method chain case:
When multiple methods are chained in the same line * for example when using Builders * every call to a method should go in its own line, breaking the line before the
.
. For example:SomeClass.Builder.with(context) .setAlpha("1") .setCancelable(false) .setExtras(bundle) .build()
-
RxJava chaining style:
fun syncLocations(): Observable<Location> { return locationHelper.getAllLocations() .concatMap { locationService.getLocation(it.id) } .retry { _, throwable -> throwable is Error } }
Naming
Packages
Package names are all lower-case, multiple words concatenated together, without hyphens or underscores:
com.nimble.android_demo
com.nimble.androiddemo
Properties
private var temp: Int = -1
private var a: Boolean = false
private var temporary: Int = -1
private var isValid: Boolean = false
const val extra_value = 42
const val EXTRA_VALUE = 42
XMLHTTPRequest
IOStream
URL: String
findPostByID
XmlHttpRequest
IoStream
url: String
findPostById
class ExampleClass {
val publicFinalProperty: Int
var publicProperty: Int = 0
protected val protectedProperty: Int
private val url: String
private fun findRateById(): Int {
// Your code
}
}
const val SOME_CONSTANT = 42
Classes and Interfaces
-
Written in UpperCamelCase.
BaseACTIVITY
BaseActivity
Methods
-
Written in lowerCamelCase with descriptive names.
fun setvalue(value: String) private fun check()
fun setValue(value: String) private fun checkStyle() // or private fun validateStyle()
Declaration
Visibility Modifiers
-
Non-public visibility modifiers should be explicitly defined for classes, methods, and properties:
var isPrivateProperty: Boolean = false public fun publicMethod() { // Nope }
private var isPrivateProperty: Boolean = false fun publicMethod() { // Your code }
Classes
Constants
-
Should be declared at the top-level scope.
-
Do NOT extract a constant if it does not provide any extra information or insight into the value, and is not for reusability or maintenance simplification.
const val ZERO = 0 private const val ONE = 1 const val EMPTY_STRING = "" class SomeClass { private fun scrollToPosition(index: Int) { if (index != ZERO) { // Your code } } }
const val MAX_API_RETRY_ATTEMPTS = 3 private const val TOKEN_EXPIRED_ERROR = "token_expired" private const val SCROLLING_THRESHOLD = 0 class SomeClass { private fun scrollToPosition(index: Int) { if (index + SCROLLING_THRESHOLD >= lastIndex) { // Your code } } }
Class Member Ordering
-
- private val/var
- overridden val with backing property
- overridden method
-
private
methods should be placed close to the call sites. For example:class SomeClass : BaseClass() { private val form = BehaviorSubject.createDefault(Form()) private var id = -1 private val _enableButton = BehaviorSubject.createDefault(false) override val enableButton: Observable<Boolean> get() = _enableButton override fun firstName(firstName: String) { validateName(firstName) } private fun validateName(name: String) { // Your code } override fun someOtherMethod(something: String) { // Your code } }
Comments
-
For short documentation comments, use
/** */
:// This does a simple calculation fun simpleCalculation() { } // This is a simple class class SimpleClass { }
/** This does a simple calculation */ fun simpleCalculation() { } /** This is a simple class */ class SimpleClass { }
-
For short inlined comments, use
//
sparingly:fun simpleCalculation() { /** * Multiple lines comment is not expected here * The X-coordinate position, starts from 0.0 */ val complexCoordinatesX = 0.0; val complexElevation = -5F; /** Elevation begins from -5 */ }
fun simpleCalculation() { // The X-coordinate position, it starts from 0.0 val complexCoordinatesX = 0.0; val complexElevation = -5F; // Elevation begins from -5 }
-
For longer documentation comments, place the opening
/**
on a separate line, begin each subsequent line with an asterisk, and ensure they are vertically aligned:// Two line // comments fun complexTask() { /*...*/ } /** * Block comment but mis-aligned */ fun complexExecution() { /*...*/ }
/** * Block comment * that is longer than 2 lines */ fun complexTask() { /*...*/ }
-
Use Kotlin style function arguments and expected returns, do not use
@param
and@return
tags:/** * Returns the absolute value of the given number. * @param number The number to return the absolute value for. * @return The absolute value. */ fun abs(number: Int): Int { /*...*/ }
/** * Returns the absolute value of the given [number]. */ fun abs(number: Int): Int { /*...*/ }