Principios SOLID en Kotlin: aplicación avanzada y práctica

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Principios SOLID en Kotlin: teoría y práctica a nivel avanzado



SOLID es un conjunto fundamental de principios de diseño orientado a objetos, introducido por Robert Martin. En el contexto de Kotlin, que combina las mejores características de la POO y la programación funcional, estos principios adquieren nuevas posibilidades de implementación. En este artículo, examinaremos cada principio a nivel avanzado, utilizando las capacidades únicas del lenguaje: funciones inline, delegación, clases selladas y funciones de extensión.



1. Principio de Responsabilidad Única (SRP) y delegación



El principio de responsabilidad única establece: una clase debe tener solo una razón para cambiar. En Kotlin, para cumplir con SRP, se utiliza a menudo el patrón Delegación (Delegation). La palabra clave by permite delegar automáticamente la implementación de una interfaz a otro objeto.



Problema: La clase UserService es responsable de la lógica de negocio, el registro y el envío de correos electrónicos.



// ❌ Violación de SRPclass UserService {    fun registerUser(email: String, password: String) {        // Lógica de negocio        println("Usuario registrado")        // Registro        log("Usuario registrado: $email")        // Envío de correo        sendEmail(email, "¡Bienvenido!")    }

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


Solución usando delegación:



// ✅ Cumplimiento de SRP mediante delegacióninterface 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("Enviando correo a $to: $body")}

class UserService( private val logger: Logger, private val emailSender: EmailSender) : Logger by logger, EmailSender by emailSender { // 👈 Delegación

fun registerUser(email: String, password: String) { println("Usuario registrado") log("Usuario registrado: $email") send(email, "¡Bienvenido!") }}

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


El uso de by permite evitar código repetitivo y separar claramente las responsabilidades. La clase UserService ahora solo se encarga del registro, mientras que el registro y el envío se delegan a clases separadas.



2. Principio Abierto/Cerrado (OCP) y clases selladas



El principio abierto/cerrado: las clases deben estar abiertas para la extensión, pero cerradas para la modificación. En Kotlin, las clases selladas y las funciones de extensión son ideales para esto.



Problema: La función processPayment usa when con verificación de tipo, y al agregar un nuevo método de pago, debe modificarse.



// ❌ Violación de OCPfun processPayment(type: String, amount: Double) {    when (type) {        "card" -> println("Procesando pago con tarjeta: $amount")        "paypal" -> println("Procesando pago con PayPal: $amount")        else -> throw IllegalArgumentException("Tipo de pago desconocido")    }}


Solución con clases selladas:



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

// Función cerrada para modificaciónfun processPayment(method: PaymentMethod, amount: Double) { // Cuando aparezcan nuevas subclases, el compilador requerirá su manejo

Blogs

Book Recommendations