Princípios SOLID em Kotlin: teoria e prática do A ao Z

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: da teoria à prática

\n\n

SOLID é um acrônimo de cinco princípios fundamentais da programação orientada a objetos, formulados por Robert Martin. Esses princípios ajudam a criar código flexível, sustentável e escalável. Neste artigo, vamos detalhar cada princípio SOLID com exemplos do desenvolvimento real em Kotlin.

\n\n

Compreender SOLID é criticamente importante para qualquer desenvolvedor Kotlin, especialmente ao trabalhar com frameworks como Spring Boot ou Ktor. Esses princípios estão na base da arquitetura limpa e dos padrões de projeto.

\n\n

1. Single Responsibility Principle (SRP) — Princípio da Responsabilidade Única

\n\n

Essência: Cada classe deve ter apenas um motivo para mudar. Em outras palavras, a classe deve ser responsável por uma única funcionalidade.

\n\n

Em Kotlin, esse princípio é especialmente importante devido ao suporte ao estilo funcional. Vejamos um exemplo ruim:

\n\n
// ❌ Violação do SRP: a classe lida com logging e trabalho com BD\nclass UserService {\n    fun saveUser(user: User) {\n        // Logging\n        println("Saving user: ${user.name}")\n        // Lógica de negócio\n        validateUser(user)\n        // Trabalho com BD\n        database.insert(user)\n    }\n}\n
\n\n

Vamos corrigir a situação dividindo a responsabilidade:

\n\n
// ✅ Abordagem correta: cada responsabilidade em uma classe separada\nclass Logger {\n    fun log(message: String) = println("[LOG] $message")\n}\n\nclass UserValidator {\n    fun validate(user: User): Boolean = user.name.isNotBlank()\n}\n\nclass UserRepository {\n    fun save(user: User) { /* salvar no BD */ }\n}\n\nclass UserService(\n    private val logger: Logger,\n    private val validator: UserValidator,\n    private val repository: UserRepository\n) {\n    fun saveUser(user: User) {\n        logger.log("Saving user: ${user.name}")\n        if (validator.validate(user)) {\n            repository.save(user)\n        }\n    }\n}\n
\n\n

2. Open-Closed Principle (OCP) — Princípio Aberto/Fechado

\n\n

Essência: As classes devem estar abertas para extensão, mas fechadas para modificação. Novas funcionalidades devem ser adicionadas por meio de herança ou composição, sem alterar o código existente.

\n\n

Em Kotlin, sealed classes e interfaces são ótimas para implementar o OCP:

\n\n
// ❌ Violação do OCP: ao adicionar um novo tipo de figura, é preciso alterar a classe\nclass AreaCalculator {\n    fun calculate(shape: Any): Double = when (shape) {\n        is Circle -> 3.14 * shape.radius * shape.radius\n        is Rectangle -> shape.width * shape.height\n        else -> throw IllegalArgumentException()\n    }\n}\n
\n\n

Implementação correta usando polimorfismo:

\n\n
// ✅ Abordagem correta: novas figuras são adicionadas sem alterar o código existente\ninterface Shape {\n    fun area(): Double\n}\n\nclass Circle(val radius: Double) : Shape {\n    override fun area() = Math.PI * radius * radius\n}\n\nclass Rectangle(val width: Double, val height: Double) : Shape {\n    override fun area() = width * height\n}\n\n// Agora é possível adicionar um triângulo sem alterar o AreaCalculator\nclass Triangle(val base: Double, val height: Double) : Shape {\n    override fun area() = 0.5 * base * height\n}\n\nclass AreaCalculator {\n    fun calculate(shape: Shape) = shape.area()\n}\n
\n\n

3. Liskov Substitution Principle (LSP) — Princípio da Substituição de Barbara Liskov

\n\n

Essência: Objetos de uma classe base devem ser substituíveis por objetos de classes derivadas sem comprometer o funcionamento do programa. A subclasse não deve enfraquecer as pré-condições nem fortalecer as pós-condições.

\n\n

Vejamos o exemplo clássico com retângulo e quadrado:

\n\n
// ❌ Violação do LSP: o quadrado não pode substituir o retângulo\nopen class Rectangle(\n    open var width: Int,\n    open var height: Int\n) {\n    fun area() = width * height\n}\n\nclass Square(sid                

Blogs

Book Recommendations