Inyección de Dependencias en Kotlin: guía sencilla para principiantes

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

¿Qué es la Inyección de Dependencias y por qué es necesaria en Kotlin?



La Inyección de Dependencias (DI, por sus siglas en inglés) es uno de los principios clave de diseño en el desarrollo moderno, especialmente en Kotlin. Si estás comenzando tu camino en la programación, este concepto puede parecer complejo. En realidad es simple: La Inyección de Dependencias es una forma de pasar las dependencias de un objeto desde el exterior, en lugar de crearlas dentro del propio objeto.



Analicemos con un ejemplo cotidiano. Imagina que horneas un pastel. En lugar de moler la harina tú mismo, recolectar los huevos y batir la mantequilla cada vez (crear dependencias internamente), simplemente vas a la tienda y compras los ingredientes listos (obtienes las dependencias desde el exterior). DI funciona bajo el mismo principio: "solicitas" componentes listos, en lugar de crearlos manualmente.



En Kotlin, DI es especialmente importante porque el lenguaje se usa activamente para crear aplicaciones Android, soluciones de servidor con Ktor y microservicios. Sin DI, el código se vuelve fuertemente acoplado, difícil de probar y mantener. Con DI obtienes:

  • Flexibilidad — reemplazar fácilmente una implementación por otra
  • Capacidad de prueba — se pueden insertar objetos mock
  • Limpieza del código — las clases no saben cómo se crean sus dependencias


El problema sin Inyección de Dependencias



Consideremos una situación típica. Tenemos una clase UserService que trabaja con una base de datos. Sin DI, se ve así:



class UserService {    private val database = Database() // Acoplamiento fuerte

fun getUser(id: Int): User? { return database.query("SELECT * FROM users WHERE id = $id") }}


¿Cuáles son los problemas aquí? Primero, UserService crea la instancia de Database por sí mismo. Si queremos reemplazar la base de datos real por una de prueba (por ejemplo, en memoria), tendríamos que cambiar el código dentro de la clase. Segundo, las pruebas unitarias se vuelven imposibles — no podemos insertar una base de datos falsa. Tercero, la clase viola el principio de responsabilidad única (SRP): no solo maneja usuarios, sino que también gestiona la creación de la base de datos.



Imagina que hay docenas de dependencias así — el código se convierte en un "espagueti", donde todo está conectado con todo. Precisamente para resolver este problema existe la Inyección de Dependencias.



Implementación manual de la Inyección de Dependencias



La forma más simple de inyectar dependencias es pasarlas a través del constructor. Esto se llama inyección por constructor. Reescribamos nuestro ejemplo:



class UserService(private val database: Database) {    fun getUser(id: Int): User? {        return database.query("SELECT * FROM users WHERE id = $id")    }}

// Uso:val database = Database()val userService = UserService(database)


Ahora UserService no sabe cómo se crea Database. Simplemente recibe una instancia lista. Podemos reemplazar fácilmente la base de datos:



class FakeDatabase : Database() {    override fun query(sql: String): User? {        return User(1, "Usuario de prueba")    }}

// En pruebas:val fakeDb = FakeDatabase()val userService = UserService(fakeDb)


Este enfoque se llama DI manual. Para proyectos pequeños es suficiente. Simplemente creas todas las dependencias en un solo lugar (por ejemplo, en main() o en una clase contenedora especial) y las pasas donde se necesitan.



Sin embargo, el DI manual tiene una desventaja: cuando el proyecto crece, la cantidad de dependencias se vuelve enorme. Tendrás que rastrear manualmente el orden de creación de objetos y pasarlos a través de varios niveles. Aquí es donde los frameworks de DI vienen al rescate.



Inyección de Dependencias con Koin



Koin es un framework de DI popular para Kotlin que no requiere generación de código

Blogs

Book Recommendations