Clean Code in Kotlin: Principles and Examples for Beginners
Clean Code is not just a trendy term, but a fundamental skill for any developer. In the Kotlin language, which combines conciseness and power, writing readable and maintainable code becomes especially important. In this article, we will break down the key principles of Clean Code as applied to Kotlin, provide practical examples, and show how to avoid common mistakes. The material is intended for beginner developers who want to write professional code from day one.
1. Naming Variables, Functions, and Classes
Proper naming is the foundation of clean code. A name should answer the questions: "What is this?" and "Why is it needed?" In Kotlin, camelCase is used for variables and functions, and PascalCase for classes and objects.
Bad example:
val x = 5fun calc(a: Int, b: Int): Int { return a * b + 10}Good example:
val maxRetryCount = 5fun calculateTotalPrice(basePrice: Int, tax: Int): Int { return basePrice + tax}Key rules:
- Avoid abbreviations — replace
usrwithuser, andcalcwithcalculate. - Use verbs for functions —
getUser(),sendEmail(),validateInput(). - Boolean variables should be named with prefixes
is,has,can—isActive,hasPermission. - Avoid redundant information —
userListis better thanlistOfUsersFromDatabase.
2. SOLID Principles in Kotlin
SOLID is a set of five principles of object-oriented programming that help create flexible and easily maintainable systems. Let's look at them with Kotlin examples.
Single Responsibility
A class should have only one reason to change. Separate logic into small, specialized classes.
Bad example:
class UserManager { fun saveUser(user: User) { /* saving to DB */ } fun sendEmail(user: User) { /* sending email */ } fun printReport(user: User) { /* printing report */ }}Good example:
class UserRepository { fun save(user: User) { /* saving to DB */ }}
class EmailService { fun send(user: User) { /* sending email */ }}
class ReportPrinter { fun print(user: User) { /* printing report */ }}Open/Closed
Classes should be open for extension but closed for modification. Use interfaces and inheritance.
interface Shape { fun area(): Double}
class Circle(val radius: Double) : Shape { override fun area() = Math.PI * radius * radius}
class Rectangle(val width: Double, val height: Double) : Shape { override fun area() = width * height}
// Now you can add new shapes without changing existing codeLiskov Substitution
Objects of subclasses should be able to replace objects of the base class without breaking the logic. In Kotlin, this is especially relevant when working with collections and inheritance.
open class Bird { open fun fly() = "Flying"}
class Penguin : Bird() { override fun fly() = throw UnsupportedOperationException("Penguins cannot fly")}// This violates the principle — it's better to move the "ability to fly" into a separate interface3. Working with Functions: Conciseness and Purity
Kotlin offers powerful tools for writing clean functions. Basic rules:
Blogs
Book Recommendations
Read also
GraphQL API with Rust: Step-by-Step Tutorial for Building a Fast Backend