Header Ads

O que é injeção de dependência na programação?

A injeção de dependência é uma técnica de engenharia de software em que os objetos recebem instâncias de outros objetos dos quais dependem. Em vez de buscarem as próprias dependências externas, os objetos devem receber diretamente tudo o que precisam para funcionar.

Um exemplo básico

O termo “ injeção de dependência ” e sua definição pode parecer complexa. Na prática, é um conceito simples. Vejamos duas abordagens para criar um objeto básico. Estamos usando PHP aqui, mas os conceitos se aplicam a todas as bases de código orientadas a objetos.

Sem injeção de dependência

classe UserCreator & # 123;   protegido Mailer $ Mailer;   publicfunction __construct & # 40; & # 41; & # 123; $ this- > Mailer = new Mailer & # 40; & # 41 ;; & # 125;   função pública criar & # 40; string nome de usuário, string $ email & # 41 ;: void & # 123; $ this- > Mailer- > enviar & # 40; $ email, " sua conta ", " Bem-vindo. " & # 41 ;; & # 125;   & # 125;

Com injeção de dependência

classe UserCreator & # 123;   protegido Mailer $ Mailer;   publicfunction __construct & # 40; Mailer $ mailer & # 41; & # 123; $ this- > Mailer = $ Mailer; & # 125;   publicfunction criar & # 40; string $ username, string $ email & # 41 ;: void & # 123; $ this- > Mailer- > send & # 40; $ email, " Your account ", " Welcome. " & # 41 ;; & # 125;   & # 125;

A diferença é sutil, mas significativa. Ambas as classes dependem de uma instância do Mailer. A primeira classe constrói seu próprio Mailer, enquanto a segunda trabalha com um Mailer fornecido pelo mundo externo. A dependência Mailer foi injetada na classe.

Benefícios da injeção de dependência

A principal vantagem da injeção de dependência é o desacoplamento de classes e suas dependências que ela fornece. A injeção de dependência é uma forma de inversão de controle – em vez de classes controlando suas próprias dependências, eles trabalham com instâncias fornecidas por seu ambiente externo.

Em termos mais concretos, injetar suas dependências simplifica a alteração dessas dependências no futuro. Em uma base de código real, Mailer em nosso exemplo acima provavelmente seria uma interface com implementações como SendmailMailer, SendGridMailer e FakeMailer.

Tomando o primeiro exemplo, ter classes construindo diretamente uma das instâncias do Mailer resulta em trabalho extra se você precisar substituir essa implementação do Mailer. Com injeção de dependência, você pode digitar uma dica na interface do Mailer para aceitar qualquer implementação compatível. A implementação a ser usada é determinada pelo mundo externo.

Na maioria das vezes, você usará injeção de dependência em conjunto com um contêiner de injeção de dependência. Os contêineres geralmente se integram à estrutura do aplicativo que você está usando. Eles resolvem e injetam dependências de classe automaticamente.

Solicitar um container para um UserCreator primeiro construiria uma instância do Mailer. Isso seria passado para o UserCreator por meio de seu parâmetro construtor. Você “ conecta ” o contêiner para definir a implementação a ser usada quando uma interface é sugerida pelo tipo. Sob este modelo, alterar o Mailer ativo em toda a base de código requer apenas reconectar o contêiner. Pode ser uma linha de código na configuração do contêiner.

Impactos no teste

A injeção de dependência simplifica a simulação de suas dependências durante o teste. Como as dependências são originadas externamente à classe, você pode fornecer uma implementação falsa em seus testes de unidade:

classe FakeMailer implementa Mailer & # 123; publicfunction send & # 40; string $ to, string $ subject, string $ body & # 41 ;: void & # 123; return; & # 125; & # 125;

Não precisamos enviar o e-mail de boas-vindas ao testar nosso UserCreator. No entanto, seria inevitável no primeiro exemplo, onde o UserCreator sempre constrói seu próprio Mailer ativo. Com a injeção de dependência, podemos fornecer um Mailer especial que satisfaça o contrato da interface, mas elimine os efeitos colaterais.

Acoplamento Frouxo

A injeção de dependências não tem a ver com eliminar totalmente as dependências – eles sempre estarão lá, mas devem ser fracamente acoplados. Pense em uma dependência como algo que fica preso por um período de tempo, não um acessório que fica permanentemente colado.

O acoplamento rígido, como visto no primeiro exemplo, torna o código inflexível que é difícil de realocar. Dependências tornam-se opacas para observadores externos, como executores de teste. As interfaces de sugestão de tipo passadas para sua classe mantêm suas dependências o mais fracamente acopladas possível.

Princípio de responsabilidade única

Uma vantagem final da injeção de dependência é sua capacidade de ajudá-lo a aderir ao Princípio de Responsabilidade Única. Isso afirma que cada classe deve ser responsável por uma única unidade independente de funcionalidade em sua base de código.

Sem injeção, as classes não apenas fornecem funcionalidade, mas também constroem suas próprias dependências. Isso requer que cada classe possua conhecimento detalhado sobre os requisitos de outros subsistemas. Com injeção, a classe &’ o conhecimento do mundo exterior é limitado aos contratos fornecidos pelas interfaces das quais depende.

Conclusão

A injeção de dependência torna mais fácil manter bases de código orientadas a objetos. As classes que constroem suas próprias dependências geralmente são um cheiro de código. Eles acabam acoplados firmemente ao ambiente e são difíceis de testar.

Elevar as dependências das classes que as usam inverte o controle e cria uma separação mais forte de interesses. Você pode pensar nisso como a remoção de constantes codificadas: você nunca escreveria um nome de esquema de banco de dados em sua fonte, pois ele deve residir em um arquivo de configuração.

A implementação do Mailer também é um detalhe de configuração. O UserCreator não deve se preocupar em configurar um sistema de e-mail. É provável que você queira reutilizar o mesmo sistema em outro lugar em sua base de código. A configuração muda com mais frequência do que o código; provavelmente você desejará alterar a forma como os e-mails são enviados muito antes de revisar a exigência comercial de que um e-mail é enviado quando um usuário se inscreve.

Em resumo, a injeção de dependência incentiva seus componentes a solicitar a funcionalidade de que precisam, em vez de pegá-la aos poucos, caso a caso. A fiação da instância no nível do aplicativo por meio de um contêiner expõe as dependências do que elas são: detalhes de configuração que podem mudar. Codifique suas classes para aceitar abstrações do ambiente, em vez de implementações concretas construídas internamente.

Nenhum comentário