Injeção de dependência

Dec 29 2022
DI é uma técnica amplamente utilizada na programação de software. Até o Google recomenda DI para desenvolvedores Android, o Android possui bibliotecas como Dagger, Hilt para esse fim.

DI é uma técnica amplamente utilizada na programação de software. Até o Google recomenda DI para desenvolvedores Android, o Android possui bibliotecas como Dagger, Hilt para esse fim. DI oferece as seguintes vantagens:

  1. Reutilização de código
  2. Facilidade de refatoração
  3. facilidade de teste

A injeção de dependência é uma técnica que permite que os objetos sejam separados dos objetos dos quais dependem. Vamos dar um exemplo de como implementar DI no 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")!)
    }
}

RemoteClienté injetado DataDownloaddo composer/assembler Client1e Client2. Ele também desacopla o código. Agora podemos testá-los separadamente sem preencher a dependência indesejada. Alguns prós da refatoração de código acima

  1. Facilidade nos testes.
  2. Desenvolvimento mais rápido de novos recursos.
  3. Tempo de compilação do Xcode aprimorado (escreverei um blog separado sobre isso).
  4. Economiza tempo e dinheiro.
  1. Injeção de construtor (explicado acima)
  2. injeção de função
  3. Injeção de propriedade

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")!)
    }
}

Injeção de propriedade: HTTPClient é passado como injeção de propriedade para 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 que ajude! Se você gostou do artigo e deseja ler mais artigos incríveis, siga-me aqui e mostre seu apoio, pois isso me motiva a escrever mais.

Por favor, compartilhe seus comentários para melhorar o conteúdo e sobre o próximo tópico que deseja explorar.

Obrigado a todos pela leitura, boa codificação!!

Referências

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