Unofficial Kotlin Style Guide
With the official Kotlin documentation there is an official style guide however it is incomplete/insufficient. This article attempts to provide guidelines for code that is Kotlinic, Kotlin code that is written as Idiomatic Kotlin which is done using a good style. Some programming languages like Java don’t have an official style guide. Note that this article is currently a draft version.
Some of the items in this guide are based on the Kotlin Style Guide GitHub repository.
Naming
- All Kotlin source files (.kt) that don’t contain a single top level element (eg a class) use lowercase letters, which can contain underscores: eg name_printer.kt
- Every top level Kotlin source file that has a single top level element is named after the element: eg HTMLElement
- Classes/enums/objects use the title case naming scheme (well known abbreviations are permitted) and use singular nouns: eg StringFormatter, NOT StringFormatters
- Variables/properties use the camel case naming scheme: eg mainActivity
- Constants use uppercase letters with each word separated by an underscore: eg TXT_FILE_EXT
- If there are multiple Kotlin source files then all of them must be in a package
- Each package is named in lowercase letters containing no special characters: eg fpexercises
- Use of Hungarian Notation for naming is prohibited!
- Avoid using reserved keywords for names
- If a defined function has a single function parameter that initialises an object for a DSL then name the parameter init, eg:
```kotlin
fun parentHtmlElement(tagName: String, init: ParentHtmlElement.() -> Unit) =
createParentHtmlElement(tagName, init)
```
Formatting
- All Kotlin source files use the UTF-8 character encoding
- All Kotlin code including comments are written using the same human language (eg English)
- Only soft tabs (tab characters converted to spaces) are used
- Standard indentation of 4 spaces with each soft tab
- Every major Kotlin element defined (class/object/enum/function) is separated by a single blank line
- Single line lambdas/classes/objects/enums have both curly braces on the same line, eg:
```kotlin
class Person(val firstName: String, val lastName: String, val age: Int){}
```
- Multi line curly brace items have the curly braces on separate lines, eg:
```kotlin
fun printName(name: String) {
println(“ — — — “)
println(“Hello $name”)
println(“ — — — “)
}
```
- Each separate single line if statement should omit the curly braces, eg:
```kotlin
if(name != null) printName(name)
```
- If the if/else if/else blocks contain multiple lines then curly braces must be used, eg:
```kotlin
if(age in 0..3) {
println(“Baby”)
processBaby()
} else if(age in 4..12) {
println(“Child”)
processChild()
} else if(age in 13..17) {
println(“Teenager”)
processTeenager()
} else {
println(“Adult”)
processAdult()
}
```
- Only a single statement is allowed on each line
- Avoid using semicolons to separate multiple statements
- If a defined function has a single function as a parameter then position it as the last parameter, eg:
```kotlin
fun buildString(prefix: String, init: StringBuilder.() -> Unit): String {
// …
}
```
- When using operators in a statement leave other operators before the wrap, eg:
```kotlin
val s = “foo” +
“bar”
```
- Annotations without arguments can be placed on the same line, eg:
```kotlin
@JsonExclude @JvmField
var x: String
```
- A defined class that has multiple parameters in the primary constructor should be formatted like the following:
```kotlin
class C(
val a: String,
val b: String,
val c: String
) : SuperType() {
val d: String = “”
}
```
Classes
- Keep every defined class closed (omit the use of the **open** keyword) unless there is a VERY good reason to open up a class to allow inheritance
- When a class extends a class and implements one or more interfaces then position the name of the super class first before the interface names, eg:
```kotlin
class DivElement : HTMLElement(), Serializable {
// …
}
```
- When modelling data use a Data Class over a Class
- With a Class prefer composition over classic inheritance
- Prefer defining Class properties in the primary constructor instead of in the body
Lambdas
- Use the it keyword to access a parameter for a single argument/single line lambda
- Always define a single lambda parameter for a single argument lambda that is over multiple lines, eg:
```kotlin
list.filter { it > 10 }.map { element ->
processElement(element)
element * 2
}
```
- Prefer defining and using a function instead when a lambda uses more than 4 lines and/or is defined/used multiple times
- Limit lambda nesting to 4 levels
- Use apply function for object initialisation, eg:
```kotlin
val foo = createBar().apply {
property = value
init()
}
ShareCompat.IntentBuilder.from(this).apply {
setChooserTitle(title)
setType(mimeType)
setText(txt)
}.startChooser()
```
- Prefer using the apply/run functions over the with function when dealing with a nullable receiver, eg:
```kotlin
getNullable()?.run {
init()
}
```
Update
Kotlin now has its own official Coding Conventions.