Kotlin 🌈

Hero image for Kotlin 🌈

Reference Resources

When it comes to Java, most conventions are shared with Kotlin. For generic conventions, we follow:

Formatting

  • Indentation:
    • Only use spaces, no tabs allowed.
    • Use 4 space indents for blocks and 8 space indents for line wraps.
    • It’s also flexible to change the rules too, as there is a recommendation from Google to use 2 space for blocks and 4 space for line wraps too, so, depending on the start of the project, we should always follow the base structure.
  • Blank lines:
    • 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 length: it shouldn’t exceed the screen width, ideally should be no longer than 100 characters.

  • 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.

    // Bad
    fun updatePerson(firstName: String, middleName: String, lastName: String) {
      // Your code
    }
    
    // Good
    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"
    )
    
  • Line amount per class: should be no longer than 600 lines per class.

  • Vertical spacing: it’s very important that you should keep alignment on your new lines to code to be consistent with the current code base in order to have a good experience when doing code reviews.

  • Brace style:

    // Bad
    fun main()
    {
        // Not this
    }
    
    // Good
    fun main() {
        // Your code
    }
    
  • Conditional statements are preferred to be enclosed with braces:

    // Bad
    if (conditionPassed)
        doSomething()
    
    // Good
    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:

// Bad
com.nimble.android_demo

// Good
com.nimble.androiddemo

Properties

  • Must be written in lowerCamelCase with descriptive names:
// Bad
private var temp: Int = -1
private var a: Boolean = false

// Good
private var temporary: Int = -1
private var isValid: Boolean = false
  • Constants must be written in uppercase:
// Bad
const val extra_value = 42

// Good
const val EXTRA_VALUE = 42
  • Acronyms should be treated as words:
// Bad
XMLHTTPRequest
IOStream
URL: String
findPostByID

// Good
XmlHttpRequest
IoStream
url: String
findPostById
  • Example:
class ExampleClass {
    val publicFinalProperty: Int
    var publicProperty: Int = 0
    protected val protectedProperty: Int
    private val url: String

    private fun findRateById(): Int {
        // Your code goes here
    }
}

const val SOME_CONSTANT = 42

Classes and Interfaces

  • Written in UpperCamelCase.

    // Bad
    BaseACTIVITY
    
    // Good
    BaseActivity
    

Methods

  • Written in lowerCamelCase with descriptive names.

    // Bad
    fun setvalue(value: String)
    private fun check()
    
    // Good
    fun setValue(value: String)
    private fun checkStyle() // or private fun validateStyle()
    

Declaration

  • Non-public visibility modifiers should be explicitly defined for classes, methods, and properties:

    // Bad
    var isPrivateProperty: Boolean = false
    public fun publicMethod() {
        // Nope
    }
    
    // Good
    private var isPrivateProperty: Boolean = false
    fun publicMethod() {
        // Your code
    }
    
  • Classes should be one class per source file, although inner classes are still encouraged in some situations.

  • Constants should be declared at the top-level scope and placed at the bottom of the file.

    class SomeClass {
        // Your code
    }
    
    const val SOME_CONSTANT = 42
    private const val SOME_OTHER_CONSTANT = "thisIsAConstant"
    

Class Member Ordering

  • Class members should be ordered in the following manner:
    1. private val/var
    2. overridden val with backing property
    3. 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

  • Comment should follow the Java docs comment style guide, example:

    // Bad
    
    // Two line
    // comments
    
    /**
      * Block comment but mis-aligned
     */
    
    // Good
    
    // One line comment
    
    /*
     * Block comment
     * that is longer than 2 lines
     */
    
     /**
      * Class/method description (Javadoc)
      *
      * @param  url  an absolute URL giving the base location of the image
      * @param  name the location of the image, relative to the url argument
      * @return      the image at the specified URL
      * @see         Image
      */