Hoje irei escrever sobre este tema pois percebo que algumas pessoas desenvolvedoras de software apresentam dificuldades em utilizar os conceitos de injeção de dependência em aplicações reais.
O que é Dependency Injection?
Em primeiro lugar, observe este código:
Este código funciona, mas também gera um problema grave! Quando criamos uma instância de Logger
dentro do construtor de FirstExample
, criamos um forte acoplamento entre essas duas classes.
Imagine se precisarmos implementar esse padrão em diversas classes da nossa aplicação, ou pior, e se em determinado momento seja necessário alterar a forma como Logger
deve ser instanciada?
Dá enjoo só de pensar!
Para resolver isso, podemos transferir a criação da instância de Logger
(dependência) para fora da classe FirstExample
e passa-la em sua construção, por exemplo:
Isso é injeção de dependência, ou seja, quando “injetamos” uma instância de classe dentro de outra, onde a classe “injetada” é a dependência.
Dica de ouro:
Existe um principio muito bacana no SOLID que se chama Princípio da Inversão de Dependência que além de outras coisas sugere que nossas classes dependam de abstrações e não de classes concretas.
Como as abstrações (leia-se interfaces) expõem um contrato de utilização “obrigando” as classes que a implementam a segui-lo, podemos utilizar qualquer classe que firme este contrato como dependência, flexibilizando a implementação e reduzindo o acoplamento.
Sabendo disso, podemos refatorar a classe exemplo substituindo Logger
por LoggerInterface
, uma vez que o componente que estamos utilizando (monolog) implementa a PSR3 que define a LoggerInterface
como padrão de implementação de logs para PHP.
Com a refatoração, o código fica assim:
Como e por que utilizar um container de injeção de dependência?
Um container o quê!?
Em resumo, um container de injeção de dependência serve para entre outras coisas, abstrair o controle sobre quais instâncias devem ser criadas, como será feito (configurando definições, por exemplo) e quando isso é necessário.
Este é o código do nosso exemplo refatorado para a utilização de um container de injeção de dependência:
Na linha 7
estamos declarando a utilização do PHPDI, um container de injeção de dependência muito utilizado em projetos PHP.
O código é basicamente o mesmo que foi utilizado nos últimos exemplos e as mudanças ocorrem de fato a partir da linha 32
, onde criamos uma instância do container. Na linha 34
, através do método addDefinitions()
, definimos as injeções que serão utilizadas em nosso aplicativo.
Na linha 40
, através do método build()
, criamos de fato o nosso container. Na linha 42
, através do método get()
, criamos uma instância de FourthExample
que é atribuída a variável $exampleController
e através dela podemos invocar o mal qualquer método da classe FourthExample
normalmente, sem problemas.
Observação:
Veja que na linha 48
declarei uma forma alternativa de instanciar uma classe através do container utilizando o método call()
, dessa forma, passamos o nome da classe que queremos instanciar e o método que deverá ser invocado seguido de um array com os parâmetros que o método espera receber.
E o que mudou?
Percebam que em nenhum momento precisamos instanciar e/ou “injetar” a(s) dependência(s) necessária(s) para que a classe FourthExample
funcione corretamente, pois o container se encarrega de realizar essa tarefa e essa é uma das grandes sacadas em se utilizar um container de injeção de dependência.
Observação:
Em alguns casos não será necessário configurar as injeções para os nossos aplicativos e para estes casos podemos utilizar um recurso que inclusive, já vem habilitado por padrão com o PHPDI, o autowiring.
Como complemento, sugiro que leiam sobre o recurso de autowiring e como definir injeções manualmente com o componente de injeção de dependência que estamos utilizando.
Criei um projeto que executa todos os exemplos utilizados neste artigo através do terminal. Trata-se de uma aplicação muito básica que gera logs (proposta dos códigos acima), sendo um log para cada exemplo executado. Este é o link do repositório:
Chegamos ao final de mais um artigo e eu espero de verdade que este conteúdo tenha sido útil para você.
Forte abraço e até a próxima!
Testando o Captcha!