Introdução: Por que SOLID é importante em Kotlin?
SOLID é um acrônimo de cinco princípios fundamentais da programação orientada a objetos, formulados por Robert Martin. No contexto do Kotlin, uma linguagem multiplataforma moderna, esses princípios adquirem importância especial. O Kotlin combina tanto POO quanto recursos funcionais, permitindo escrever código mais flexível e sustentável. A adesão aos princípios SOLID ajuda os desenvolvedores a criar sistemas que são fáceis de escalar, testar e manter.
Neste artigo, analisaremos cada um dos cinco princípios com exemplos específicos em Kotlin, da teoria à implementação prática. Você aprenderá como evitar antipadrões típicos e tornar seu código mais limpo.
1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única
Teoria: Cada classe deve ter apenas um motivo para mudar. Em outras palavras, a classe deve ser responsável por apenas uma funcionalidade ou tarefa.
Prática em Kotlin: Frequentemente, os desenvolvedores violam o SRP colocando em uma única classe a lógica de processamento de dados, validação e trabalho com serviços externos.
Exemplo de violação:
class UserManager { fun saveUser(user: User) { // Salvar no banco de dados println("User saved to DB") }
fun sendEmail(user: User, message: String) { // Enviar email println("Email sent to ${user.email}") }
fun validateUser(user: User): Boolean { // Validação de dados return user.name.isNotEmpty() }}Aqui, UserManager é responsável por salvar, enviar email e validar. Se a lógica de envio de email mudar, essa classe terá que ser alterada, o que pode quebrar o salvamento de dados.
Versão corrigida com SRP:
class UserRepository { fun save(user: User) { println("User saved to DB") }}
class EmailService { fun send(user: User, message: String) { println("Email sent to ${user.email}") }}
class UserValidator { fun validate(user: User): Boolean { return user.name.isNotEmpty() }}Agora, cada classe tem uma única responsabilidade, o que simplifica o teste e a modificação do código.
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. Isso significa que você deve ser capaz de adicionar novos comportamentos sem alterar o código existente.
Prática em Kotlin: Use abstrações (interfaces ou classes abstratas) e polimorfismo. Em Kotlin, sealed class e expressões when são excelentes para isso.
Exemplo de violação:
class AreaCalculator { fun calculate(shape: Any): Double { return when (shape) { is Circle -> Math.PI * shape.radius * shape.radius is Square -> shape.side * shape.side else -> throw IllegalArgumentException("Unknown shape") } }}Para adicionar uma nova forma (por exemplo, Triangle), seria necessário modificar o método calculate.
Versão corrigida com OCP:
interface Shape { fun area(): Double}
class Circle(private val radius: Double) : Shape { override fun area() = Math.PI * radius * radius}
class Square(private val side: Double) : Shape { override fun area() = side * side}
class Triangle(private val base: Double, private val height: Double) : Shape { override fun area() = 0.5 * base * height}
class AreaCalculator { fun calculate(shape: Shape) = shape.area()}Agora, para adicionar uma nova forma, basta criar uma nova classe que implemente a interface