SOLID Principles in Kotlin: Theory and Practice with Code 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

SOLID principles in Kotlin: from theory to practice



SOLID is an acronym for five fundamental principles of object-oriented design formulated by Robert Martin (Uncle Bob). These principles help create flexible, scalable, and easily maintainable code. In this article, we will break down each SOLID principle with examples from the world of Kotlin, so you can immediately apply them in your projects.



1. Single Responsibility Principle (SRP)



Theory: Each class should have only one reason to change. In other words, a class should be responsible for one clearly defined functionality.



Practice in Kotlin: Let's consider a typical SRP violation where a class handles data processing, output, and validation all at once.



// ❌ SRP violationclass UserManager {    fun registerUser(email: String, password: String) {        if (isValidEmail(email) && isValidPassword(password)) {            saveToDatabase(email, password)            sendWelcomeEmail(email)        }    }

private fun isValidEmail(email: String): Boolean = email.contains("@") private fun isValidPassword(password: String): Boolean = password.length >= 6 private fun saveToDatabase(email: String, password: String) { /* ... */ } private fun sendWelcomeEmail(email: String) { /* ... */ }}


Refactoring with SRP compliance:



// ✅ SRP complianceclass UserValidator {    fun isValidEmail(email: String): Boolean = email.contains("@")    fun isValidPassword(password: String): Boolean = password.length >= 6}

class UserRepository { fun save(email: String, password: String) { /* Saving to database */ }}

class EmailService { fun sendWelcomeEmail(email: String) { /* Sending email */ }}

class UserRegistrationService( private val validator: UserValidator, private val repository: UserRepository, private val emailService: EmailService) { fun registerUser(email: String, password: String) { if (validator.isValidEmail(email) && validator.isValidPassword(password)) { repository.save(email, password) emailService.sendWelcomeEmail(email) } }}


2. Open/Closed Principle (OCP)



Theory: Software entities (classes, modules, functions) should be open for extension but closed for modification. You should be able to add new functionality without changing existing code.



Practice in Kotlin: Use interfaces and polymorphism. Instead of if-else or when for handling different types, create a hierarchy.



// ❌ OCP violationclass DiscountCalculator {    fun calculateDiscount(customerType: String, amount: Double): Double {        return when (customerType) {            "Regular" -> amount * 0.05            "Premium" -> amount * 0.10            "VIP" -> amount * 0.20            else -> 0.0        }    }    // To add "Gold", you need to modify this method!}


// ✅ OCP complianceinterface DiscountStrategy {    fun applyDiscount(amount: Double): Double}

class RegularDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.05}

class PremiumDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.10}

class VIPDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.20}

// New type added without changing existing codeclass GoldDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.15}

class DiscountCalculator { fun calculateDiscount(strategy: DiscountStrategy, amount: Double): Double { return strategy.apply

Blogs

Book Recommendations