Clean Code in Kotlin: Principles and Practical Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Clean Code in Kotlin: Principles and Practical Examples



Clean Code is not just a trendy term, but a fundamental skill for professional developers. In the context of Kotlin, a modern and concise language, the principles of clean code take on special significance. Kotlin allows you to write expressive code, but without discipline, it's easy to create a confusing architecture. In this article, we will break down the key principles of Clean Code using Kotlin examples that will help you write code understandable to colleagues and to yourself six months later.



1. Meaningful Names: The Key to Code Readability



Proper naming is the first step towards clean code. Variable, function, and class names should answer the questions "why?", "what?", and "how?". Kotlin offers powerful tools for this.



Bad example:

fun calc(a: Int, b: Int): Int {    val c = a + b * 2    return c}


Good example (Clean Code):

fun calculateDiscountedPrice(basePrice: Int, discountPercent: Int): Int {    val discountAmount = basePrice * discountPercent / 100    return basePrice - discountAmount}


In the good example, every name speaks for itself. calculateDiscountedPrice is a verb describing the action. basePrice and discountPercent are nouns that accurately convey the essence of the data. Kotlin supports named arguments, which makes function calls even more transparent:

val finalPrice = calculateDiscountedPrice(basePrice = 1000, discountPercent = 20)


Important rules:

  • Avoid single-letter names (except for loop indices).
  • Use camelCase for variables and functions.
  • For boolean values, use prefixes like is, has, can (e.g., isActive, hasPermission).


2. Functions: One Function — One Task



The Single Responsibility Principle applies not only to classes but also to functions. A function should do only one thing and do it well. Kotlin, with its functional capabilities, simplifies this practice.



Bad example (function does too much):

fun processUser(userId: String) {    val user = database.findUser(userId)    if (user != null) {        user.name = user.name.uppercase()        database.updateUser(user)        sendEmail(user.email, "Welcome!")    }}


Good example (splitting into small functions):

fun processUser(userId: String) {    val user = findUserOrThrow(userId)    val updatedUser = user.apply { name = name.uppercase() }    updateUserInDatabase(updatedUser)    sendWelcomeEmail(updatedUser.email)}

private fun findUserOrThrow(userId: String): User { return database.findUser(userId) ?: throw IllegalArgumentException("User not found")}

private fun updateUserInDatabase(user: User) { database.updateUser(user)}

private fun sendWelcomeEmail(email: String) { sendEmail(email, "Welcome!")}


Now each function is responsible for one logical step. This makes testing, debugging, and code reuse easier. Kotlin functions can be local (nested), allowing you to encapsulate logic without creating extra classes.



3. Working with Nullable Types and Elegant Error Handling



Clean Code implies explicit management of uncertainty. Kotlin introduces nullable types (?) and powerful operators for safe handling. Using !! (non-null assertion) is a sign of bad code. Instead, use safe calls and the Elvis operator.



Bad example (risk of NPE):

fun getCity                

Blogs

Book Recommendations