Se você já ouviu falar mas não sabe ao certo o que é Dependency Injection ou como a utilizar em Golang, nesse artigo espero te ajudar a sanar as duas dúvidas.
Para que todos estejam na mesma página, antes de ver como utilizar, vamos falar um pouco sobre o que é essa tal Dependency Injection ou DI para os íntimos.
Podemos definir DI (Dependency Injection) como uma técnica onde os módulos recebem todas ou parte de suas dependências de forma indireta, ou seja, por parâmetro em uma função/método ou sendo passada diretamente para o campo de uma struct, onde tais parâmetros ou campos não tenham um tipo definido, mas sim uma interface.
Vantagens da Dependency Injection
Utilizar essa técnica ajuda com que nosso código tenha baixo acoplamento, o que torna a tarefa de refatorar partes do sistema muito mais fácil.
Outra vantagem é facilidade na hora de escrever testes, já que ao invés de ter que fazer mocks complexos de alguns serviços (principalmente serviços de cloud providers, filas e bancos de dados), você pode escrever pequenos “clients” que simulem o comportamento esperado.
Para deixar um pouco mais claro, vamos imaginar um cenário onde temos um service que precisa se comunicar com uma fila.
Ao desenvolver sem DI, muito provavelmente você vá importar o client da fila diretamente no service. Embora isso não vá gerar muito problema na hora de desenvolver, com certeza te trará uma certa dor de cabeça na hora de escrever os testes da aplicação, já que seu software utiliza um serviço externo a ele.
Agora, caso ele fosse desenvolvido com DI, essa dor de cabeça praticamente não existiria, já que a dependência estaria sendo injetada no service e não instanciada direto nele.
Dependecy Injection na prática
Para ficar mais claro, vamos levar em consideração a seguinte definição de interface.
E que as funções do service tenham sido implementadas como métodos de uma struct, onde um de seus campos é privado e do mesmo tipo da interface que definimos acima. Assim, dentro dos métodos, ao invés de utilizar o client da fila diretamente, utilizamos-o através desse campo privado.
Assim, nossa aplicação poderá instanciar o ServiceA passando o client real que se conecta com a fila, enquanto nossos testes passarão alguma implementação básica que simule os comportamentos esperados.
Existem vários outros casos onde DI é muito relevante, como por exemplo conexão com banco de dados, logs e router http.
Espero que tenha ficado claro.
Qualquer dúvida, é só deixar nos comentários.
Até a próxima!