O que é Injeção e Inversão de dependências?

No mundo da programação, existe uma relação entre os termos injeção e inversão de dependências. Porém, geralmente são mal utilizados no decorrer de um projeto ou pouco conhecidos no desenvolvimento de sistemas digitais.

Neste artigo, iremos apresentar uma breve introdução do que é cada um desses termos e de como utilizá-los corretamente. Mas, para entendê-los, primeiramente devemos compreender o significado de dependências.

O que são dependências?

Quando estamos programando, podemos criar classes para as mais diversas finalidades e funcionalidades. Então, se você instancia um objeto dentro de outra classe, isso automaticamente a torna uma dependência dessa classe. É nítido que não fazemos esse tipo de coisa apenas uma vez durante o projeto. Isso é feito em diversos momentos. Por isso, gera código com forte acoplamento ou baixa coesão segundo os princípios do SOLID.

Codar dessa maneira é um processo quase que natural utilizado pela maioria dos desenvolvedores que ainda estão aprendendo ou desconhecem alguns princípios e consequências que um código fortemente acoplado pode gerar no futuro.

Veja que, no exemplo abaixo, queremos conectar o CreateUserController, para que ele possa criar um User a partir de um repositório CreateUserRepository ao realizar alguma solitação HTTP do tipo POST a determinada rota.

Injeção e Inversão de Dependências 1

Perceba que, utilizando essa abordagem, uma classe começa a depender de uma outra para que a primeira funcione. E isso deve ser evitado desacoplando o uso de um objeto da sua criação, deixando as classes independentes.

Qual o problema gerado por essa abordagem?

Sempre que criamos uma instância de CreateUserController, uma outra instância (com a implementação direta da criação do usuário no banco) de CreateUserRepository deve estar disponível para que haja compilação do nosso código.

Dito isso, podemos pensar que o sentido das dependências segue de tal forma:

  • CreateUserController depende diretamente de CreateUserRepository

Injeção e Inversão de Dependências 2

Injeção de dependência

Podemos dizer que injeção de dependência é basicamente passar via construtor as dependências (já instanciadas fora da classe) que seu componente irá utilizar. Chamamos esse tipo de injeção de Constructor Injection.

Perceba abaixo que melhoramos o nosso código injetando uma instância de CreateUserRepository no construtor de CreateUserController, ao invés de instanciarmos esse repositório diretamente de dentro do nosso controller.

Injeção e Inversão de Dependências 3

Mas isso ainda não é o suficiente!

O CreateUserController ainda depende de CreateUserRepository.

Injeção e Inversão de Dependências 4

Antes de mostrar a solução derradeira para essa situação e ainda falando um pouco sobre a desvantagem que é utilizar esse tipo de abordagem, não poderíamos, por exemplo, ‘mockar’ valores a partir de testes unitários utilizando a classe CreateUserRepository (que faz uma implementação e operações diretamente com um banco de dados SQL) para um banco de dados simulado em memória com o intuito de criar ou utilizar testes unitários. Isso porque nossos testes deixariam de ser unitários, uma vez que estamos dependendo de uma implementação que utiliza a persistência nos dados.

Ou seja, já que amarramos nosso CreateUserController, ele então depende exclusivamente da implementação contida em CreateUserRepository.

Dito isso, o que buscamos de fato? Precisamos inverter as direções! Ao invés de dependermos de implementações, devemos depender de contratos ou interfaces.

Inversão de dependência

O Dependency Inversion Principle é um princípio do SOLID que afirma: dependa de abstrações e não de implementações.

Segundo Uncle Bob, esse princípio pode ser definido assim:

  1. Módulos de alto nível não devem depender de módulos de baixo nível. Ambos devem depender da
    abstração.
  2. Abstrações não devem depender de detalhes. Detalhes devem depender de abstrações.

Então, a inversão de dependência é uma prática que nos permite desacoplar componentes. Agora, veja como se comporta a direção e o fluxo de dependências:

Injeção e Inversão de Dependências 5

 

Neste ponto, nosso CreateUserController aponta para uma interface que abstraímos a criação de um usuário, ao invés da classe concreta CreateUserRepository. Isto é, inserindo uma interface ICreateUserRepository entre os dois componentes: CreateUserController eCreateUserRepository. Dessa forma, iremos ver a seguir como isso se reflete no código:

Injeção e Inversão de Dependências 6

Assim, no CreateUserController, iremos consultar a interface ICreateUserRepository ao invés da classe CreateUserRepository.

Injeção e Inversão de Dependências 7

Dessa forma, acabamos de inverter as dependências.

Qual a real vantagem da Injeção e Inversão de dependências?

Anteriormente, falamos que não seria possível criar nossos testes unitários ‘mockados’ passando um CreateUserRepository em um CreateUserController. Isso porque os testes ficariam lentos e precisaríamos de uma conexão com o banco de dados para executar esse test.

Entretanto, utilizando inversão de dependências podemos escrever uma classe qualquer MockCreateUserRepository, que implementa a interface ICreateUserRepository, e cria em memória um atributo que seja um array de Users para simularmos um banco de dados. Com isso, será possível executarmos testes mais rápidos e de forma íntegra, de acordo com nosso negócio.

Injeção e Inversão de Dependências 8

Conclusão

Passando uma instância dessa classe MockCreateUserRepository para o nosso CreateUserController, você pode escrever um teste unitário utilizando jest sem preocupações com operações reais em um banco de dados.

Lido até aqui, agora você pode ter uma ideia primária de como colocar em prática os princípios da inversão e injeção de dependências em suas classes, utilizando de interfaces como principal aliado. Se tiver em dúvida, lembre-se sempre: dependa de abstrações, e não de implementações.

Veja também:

Introdução ao React JS

Autor: Clidenor Issac de Almeida Cabral.

Rodrigo Gardin

Rodrigo Gardin

CTO da Luby

Gostou do conteúdo? Compartilhe

Últimos posts

Fique por dentro das últimas novidades do mundo da tecnologia com os conteúdos do nosso blog!

Acelere a Transformação Digital da sua Empresa

Basta preencher este formulário ou ligar para +55 11 3055 3404

Fale conosco​

Technology Intelligence

Luby - Latin America

Rua Amália de Noronha, nº 151, 3º Andar, Sala 303
Pinheiros, São Paulo – SP – Brasil
CEP: 05410-010

Luby - North America

1110 Brickell Avenue
Suite 310
Miami – FL
United States

AWS certifications - AWS Partner
AWS certifications - Solutions Architect
Azure logo - Certifications Luby
Google Cloud Partner logo, a symbol of Luby's certifications and recognitions collaboration with Google.
Copyright ©2024 Luby Software LLC. All rights reserved.
Rolar para cima