← Back to Kotlin Course | Chapter 14: JVM Interop & Best Practices | Lesson 7 of 7

Kotlin Best Practices

Kotlin best practices are the collected wisdom of experienced developers about how to write Kotlin code that stays clear, safe, and easy to maintain over time.

Design for Safety First

Preferring non-null types, val, and sealed classes wherever the domain allows it turns many entire categories of bugs into compile-time errors instead of runtime crashes.

Example: Design for Safety First

markup
sealed class PaymentResult
data class Approved(val transactionId: String) : PaymentResult()
data class Declined(val reason: String) : PaymentResult()

fun describe(result: PaymentResult): String = when (result) {
    is Approved -> "Approved: ${result.transactionId}"
    is Declined -> "Declined: ${result.reason}"
}

fun main() {
    println(describe(Approved("tx_123")))
}

Keep Functions Small and Focused

Breaking logic into small, well-named functions (including local and extension functions) makes each piece easy to understand, test, and reuse on its own.

Example: Keep Functions Small and Focused

markup
fun Int.isPrime(): Boolean {
    if (this < 2) return false
    for (i in 2 until this) {
        if (this % i == 0) return false
    }
    return true
}

fun main() {
    val primes = (2..20).filter { it.isPrime() }
    println(primes)
}

Don't Ignore Compiler Warnings

Warnings about unreachable code, unnecessary safe calls, or unchecked casts often point directly at a real bug or a design that can be made safer -- treating them seriously pays off.

Example: Don't Ignore Compiler Warnings

markup
fun describeNumber(n: Int): String {
    return if (n % 2 == 0) "even" else "odd"
    // Any code placed here would be unreachable, and the compiler would warn about it
}

fun main() {
    println(describeNumber(7))
}

Write Code for the Next Reader

Choosing clear names, favoring well-known idioms over clever tricks, and keeping functions short all serve the same goal: making the code easy for someone else (or future you) to safely understand and change.

Example: Write Code for the Next Reader

markup
fun calculateShippingCost(weightKg: Double, isExpress: Boolean): Double {
    val baseCost = weightKg * 2.0
    return if (isExpress) baseCost * 1.5 else baseCost
}

fun main() {
    println("Shipping cost: ${calculateShippingCost(5.0, true)}")
}
Common Mistakes
  1. Reaching for !! or unsafe casts as a quick fix instead of addressing the underlying design that made a value's type or nullability uncertain.
  2. Writing large, do-everything classes and functions instead of composing small, well-named, single-purpose pieces.
  3. Ignoring compiler warnings, which often point to genuine risks like unreachable code, unused variables, or unsafe casts.
Chapter Summary
  • Prefer immutability (val, read-only collections) and null safety operators over defensive, manual workarounds.
  • Keep functions small and focused, with descriptive names that make comments about *what* the code does mostly unnecessary.
  • Use sealed classes and exhaustive when expressions to make invalid states unrepresentable wherever practical.
  • Pay attention to compiler warnings -- they frequently highlight real, fixable risks in the code.
🔒

Chapter Quiz — Complete all 7 topics to unlock

0/7 topics done

Complete these topics first:

Login to run this code

C/C++/Java/PHP execution requires a free account. Your code is saved — you'll land right back in the editor after logging in.