Princípios SOLID em Kotlin: aplicação avançada e prática

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Princípios SOLID em Kotlin: teoria e prática em nível avançado



SOLID é um conjunto fundamental de princípios de design orientado a objetos, introduzido por Robert Martin. No contexto do Kotlin, que combina as melhores características de OOP e programação funcional, esses princípios ganham novas possibilidades de implementação. Neste artigo, examinaremos cada princípio em nível avançado, usando recursos exclusivos da linguagem: funções inline, delegação, classes sealed e funções de extensão.



1. Single Responsibility Principle (SRP) e delegação



O princípio da responsabilidade única afirma: uma classe deve ter apenas um motivo para mudar. Em Kotlin, para cumprir o SRP, o padrão Delegação (Delegation) é frequentemente usado. A palavra-chave by permite delegar automaticamente a implementação de uma interface para outro objeto.



Problema: A classe UserService é responsável pela lógica de negócios, registro de logs e envio de email.



// ❌ Violação do SRPclass UserService {    fun registerUser(email: String, password: String) {        // Lógica de negócios        println("User registered")        // Registro de log        log("User registered: $email")        // Envio de email        sendEmail(email, "Welcome!")    }

private fun log(message: String) { /* ... */ } private fun sendEmail(to: String, body: String) { /* ... */ }}


Solução usando delegação:



// ✅ Cumprimento do SRP através de delegaçãointerface Logger {    fun log(message: String)}

interface EmailSender { fun send(to: String, body: String)}

class ConsoleLogger : Logger { override fun log(message: String) = println("LOG: $message")}

class SmtpEmailSender : EmailSender { override fun send(to: String, body: String) = println("Sending email to $to: $body")}

class UserService( private val logger: Logger, private val emailSender: EmailSender) : Logger by logger, EmailSender by emailSender { // 👈 Delegação

fun registerUser(email: String, password: String) { println("User registered") log("User registered: $email") send(email, "Welcome!") }}

// Usofun main() { val service = UserService(ConsoleLogger(), SmtpEmailSender()) service.registerUser("user@example.com", "pass123")}


O uso de by evita código boilerplate e separa claramente as responsabilidades. A classe UserService agora é responsável apenas pelo registro, enquanto o log e o envio são delegados a classes separadas.



2. Open-Closed Principle (OCP) e classes sealed



Princípio aberto/fechado: as classes devem estar abertas para extensão, mas fechadas para modificação. Em Kotlin, classes sealed e funções de extensão são ideais para isso.



Problema: A função processPayment usa when com verificação de tipo e, ao adicionar um novo método de pagamento, ela precisa ser modificada.



// ❌ Violação do OCPfun processPayment(type: String, amount: Double) {    when (type) {        "card" -> println("Processing card payment: $amount")        "paypal" -> println("Processing PayPal payment: $amount")        else -> throw IllegalArgumentException("Unknown payment type")    }}


Solução com classes sealed:



// ✅ Cumprimento do OCPsealed class PaymentMethod {    data class Card(val number: String, val cvv: String) : PaymentMethod()    data class PayPal(val email: String) : PaymentMethod()    object Cash : PaymentMethod()}

// Função fechada para modificaçãofun processPayment(method: PaymentMethod, amount: Double) { // Quando novas subclasses surgirem, o compilador exigirá que sejam tratadas

Blogs

Book Recommendations