Inyección de dependencia

Dec 29 2022
DI es una técnica ampliamente utilizada en la programación de software. Incluso Google recomienda DI a los desarrolladores de Android, Android tiene bibliotecas como Dagger, Hilt para este propósito.

DI es una técnica ampliamente utilizada en la programación de software. Incluso Google recomienda DI a los desarrolladores de Android, Android tiene bibliotecas como Dagger, Hilt para este propósito. DI proporciona las siguientes ventajas:

  1. Reutilización de código
  2. Facilidad de refactorización
  3. Facilidad de prueba

La inyección de dependencia es una técnica que permite separar los objetos de los objetos de los que dependen. Tomemos un ejemplo de cómo implementar DI en iOS.

class HTTPClient {
    func downloadFrom(url: URL) {
        //download data from remote
    }
}

class DataDownload {
    let client = HTTPClient()
    
    func getData(url: URL) {
        client.downloadFrom(url: url)
    }
}

class client {
    let dataDownload: DataDownload
    
    init() {
        self.dataDownload = DataDownload()
        self.dataDownload.getData(url: URL(string: "https://any_http_url.com")!)
    }
}

class FTPClient {
    func downloadFrom(url: URL) {
        //download data from remote
    }
}

class DataDownload {
    let client = FTPClient()
    
    func getData(url: URL) {
        client.downloadFrom(url: url)
    }
}

class client {
    let dataDownload: DataDownload
    
    init() {
        self.dataDownload = DataDownload()
        self.dataDownload.getData(url: URL(string: "https://any_ftp_url.com")!)
    }
}

protocol RemoteClient {
    func downloadFrom(url: URL)
}

class FTPClient: RemoteClient {
    func downloadFrom(url: URL) {
        //download data from remote
    }
}

class DataDownload {
    let client: RemoteClient
    
    init(client: RemoteClient) {
        self.client = client
    }
    
    func getData(url: URL) {
        client.downloadFrom(url: url)
    }
}

class Client1 {
    let dataDownload: DataDownload
    
    init() {
        self.dataDownload = DataDownload(client: FTPClient())
        self.dataDownload.getData(url: URL(string: "https://any_ftp_url.com")!)
    }
}

class Client2 {
    let dataDownload: DataDownload
    
    init() {
        self.dataDownload = DataDownload(client: HTTPClient())
        self.dataDownload.getData(url: URL(string: "https://any_htttp_url.com")!)
    }
}

RemoteClientse inyecta DataDownloaddesde el compositor/ensamblador Client1y Client2. También desacopla el código. Ahora podemos probarlos en separación sin cumplir con la dependencia no deseada. Algunas ventajas de la refactorización de código anterior

  1. Facilidad en la prueba.
  2. Desarrollo más rápido de nuevas características.
  3. Se mejoró el tiempo de compilación de Xcode (escribiré un blog por separado sobre esto).
  4. Ahorra tiempo y dinero.
  1. Inyección de constructor (explicado anteriormente)
  2. Inyección de función
  3. Inyección de propiedad

class ChildViewController: UIViewController {
    func viewDidLoad() { }
    func viewWillAppear() { }
    func viewDidAppear() { }

    func getDataFrom(_ client: RemoteClient, url: URL) {
        client.downloadFrom(url: url)
    }
}

class ParentViewController: UIViewController {
    func viewDidLoad() { }
    func viewWillAppear() { }
    func viewDidAppear() { }

    func present() {
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let vc = storyboard.instantiateViewController(withIdentifier: "ChildViewController") as! ChildViewController
        vc.getDataFrom(client: HTTPClient(), url: URL(string:"https://any-url.com")!)
    }
}

Inyección de propiedad: HTTPClient se pasa como inyección de propiedad a var client.

class ChildViewController: UIViewController {
    var client: RemoteClient?

    func viewDidLoad() { }
    func viewWillAppear() { }
    func viewDidAppear() { }

    func getDataFrom(url: URL) {
        client.downloadFrom(url: url)
    }
}

class ParentViewController: UIViewController {
    func viewDidLoad() { }
    func viewWillAppear() { }
    func viewDidAppear() { }

    func present() {
        let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
        let vc = storyboard.instantiateViewController(withIdentifier: "ChildViewController") as! ChildViewController
        vc.client = HTTPClient()
    }
}

¡Espero eso ayude! Si te gustó el artículo y quieres leer más artículos increíbles, sígueme aquí y muestra tu apoyo, ya que me motiva a escribir más.

Comparta sus comentarios para mejorar el contenido y sobre el próximo tema que desea explorar.

¡Gracias a todos por leer, feliz codificación!

Referencias

  1. https://essentialdeveloper.com
  2. https://developer.android.com/training/dependency-injection