Table of Contents

Naming

Class names

Use PascalCase, which starts with an uppercase letter.

class CarModel(val modelName: String)
class UserProfile(val userId: Int, val userName: String)
class PaymentService(val paymentGateway: String)

Interface names

Use the same convention as classes, but prefix with I only if it is common in your codebase or necessary for clarity.

interface IStorage {
    fun store(data: String)
    fun retrieve(): String
}

interface IRepository<T> {
    fun getById(id: Int): T
    fun save(item: T)
}

Abstract class names

Follow the same conventions as class names, often using terms like Base or Abstract to indicate abstraction.

abstract class AbstractShape {
    abstract fun calculateArea(): Double
}

abstract class BaseRepository<T> {
    abstract fun findById(id: Int): T?
}

Functions and Methods

Function names: Use camelCase, starting with a lowercase letter.

fun fetchUserData(userId: Int): User {
    // fetch user logic
}

Extension functions: Also use camelCase, and the function name should make sense in the context of the extended class.

fun String.isEmailValid(): Boolean {
    return this.contains('@') && this.contains('.')
}

fun Int.isOdd(): Boolean {
    return this % 2 != 0
}

Variables

Variable names: Use camelCase for variables.

val companyName = "pelagornis"
val totalCount = 100

Constants: Use uppercase with underscores.

const val API_KEY = "qwodciabs1"
const val BASE_URL = "https://api.pelagornis.com"

Parameters

Function parameters: Use descriptive names in camelCase.

fun setUserName(userName: String) {
    println("User name set to: $userName")
}

Boolean parameters: Use “is” or “has” for booleans to indicate state or possession.

fun isActive(user: User): Boolean {
    return user.status == "active"
}

Kotlin Style Rules

No trailing spaces

Remove unnecessary trailing spaces from the end of lines.

Line Length

Limit lines to 120 characters for readability.

Indentation

Use 4 spaces per indentation level. Avoid using tabs.

Curly braces

Always use braces for conditionals and loops, even when the block is a single statement.

if (condition) {
    doSomething()
}

Avoid nested lambdas

If a lambda expression is too nested, consider refactoring the code to improve readability.

// Instead of
list.filter { item ->
    anotherList.any { it == item }
}
// Use a helper function
fun isItemInList(item: Item) = anotherList.contains(item)
someList.filter(::isItemInList)

Visibility Modifiers

Use explicit visibility modifiers. Avoid using default visibility unless it’s necessary.

private val userName: String

Type Inference and Explicit Types

Prefer Kotlin’s type inference whenever possible, but provide explicit types when they improve readability or when dealing with complex types.

val totalAmount = 100.0 // inferred as Double
val user: User = fetchUser() // explicit type when needed

Kotlin Formatting Rules

Function declarations

Always use spaces between function parameters for better readability.

fun calculatePrice(item: Item, discount: Double): Double {
    return item.price - (item.price * discount)
}

No spaces before function parentheses

// Wrong
fun exampleFunction () {
    // ...
}

// Right
fun exampleFunction() {
    // ...
}

Single-line lambdas

If the lambda is a single line, keep it on the same line.

val list = listOf(1, 2, 3)
val doubled = list.map { it * 2 }

Multi-line lambdas

Use braces and align the body properly.

val list = listOf(1, 2, 3)
val result = list.map { 
    val newValue = it * 2
    newValue + 1 
}

Control Statements

fun isEven(number: Int): Boolean {
    return number % 2 == 0
}

Data classes

Use data keyword for classes that are used as plain data holders and contain no behavior other than storing data.

data class User(val name: String, val age: Int)