Princípios SOLID em Kotlin: da teoria à prática
SOLID é um acrônimo de cinco princípios fundamentais de design orientado a objetos, formulados por Robert Martin (Uncle Bob). Esses princípios ajudam a criar código flexível, escalável e de fácil manutenção. Neste artigo, vamos analisar cada princípio SOLID com exemplos do mundo Kotlin, para que você possa aplicá-los imediatamente em seus projetos.
1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única
Teoria: Cada classe deve ter apenas um motivo para ser alterada. Em outras palavras, a classe deve ser responsável por uma funcionalidade claramente definida.
Prática em Kotlin: Vamos considerar uma violação típica do SRP, onde a classe lida com processamento de dados, saída e validação ao mesmo tempo.
// ❌ Violação do SRPclass 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) { /* ... */ }}Refatoração respeitando o SRP:
// ✅ Respeitando o SRPclass UserValidator { fun isValidEmail(email: String): Boolean = email.contains("@") fun isValidPassword(password: String): Boolean = password.length >= 6}
class UserRepository { fun save(email: String, password: String) { /* Salvar no BD */ }}
class EmailService { fun sendWelcomeEmail(email: String) { /* Enviar 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) — Princípio Aberto/Fechado
Teoria: Entidades de software (classes, módulos, funções) devem estar abertas para extensão, mas fechadas para modificação. Você deve ser capaz de adicionar novas funcionalidades sem alterar o código existente.
Prática em Kotlin: Usamos interfaces e polimorfismo. Em vez de if-else ou when para processar diferentes tipos, criamos uma hierarquia.
// ❌ Violação do OCPclass 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 } } // Para adicionar "Gold", é preciso alterar este método!}// ✅ Respeitando o OCPinterface 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}
// Novo tipo adicionado sem alterar o código existenteclass GoldDiscount : DiscountStrategy { override fun applyDiscount(amount: Double): Double = amount * 0.15}
class DiscountCalculator { fun calculateDiscount(strategy: DiscountStrategy, amount: Double): Double { return strategy.apply