VB .NET -  Usando a Injeção de Dependência (DI)

 Neste artigo vamos recordar como usar a injeção de dependência usando a linguagem VB .NET.


A injeção de dependência é um padrão de projeto que independe da linguagem usada. Ela é um dos princípios do SOLID onde SOLID é um acrônimo mnemônico para os cinco princípios básicos de programação e design orientados a objetos. Esses princípios foram definidos por Robert C. Martin (também conhecido como 'Tio Bob'). Ele é o autor de muitos livros, incluindo "Clean Code". Um livro que você deve ler.

Na definição forma a Wikipedia diz: "Na engenharia de software, a injeção de dependência é uma técnica pela qual um objeto fornece as dependências de outro objeto. Uma dependência é um objeto que pode ser usado (um serviço). Uma injeção é a passagem de uma dependência para um objeto dependente (um cliente) que o usaria. O serviço é feito parte do estado do cliente. Passar o serviço para o cliente, em vez de permitir que um cliente construa ou encontre o serviço, é o requisito fundamental do padrão".

Antes de continuar leia a definição e veja se entendeu. Eu creio que não fica muito claro, não é mesmo ???

Então vamos por partes...

O que é uma dependência ?

Uma dependência é um objeto que a sua classe precisa para funcionar. Para usar esse objeto geralmente você cria uma instância da classe do objeto.

Public Class DAL
    Private _sql As AcessoSQL
    Public Sub New()
        _sql = New AcessoSQL()
    End Sub
End Class
O construtor padrão da classe DAL cria um objeto da classe AcessoSQL.

Isso significa que a classe DAL é responsável pela criação de um objeto da classe AcessoSQL.

Portanto, existe um forte acoplamento entre a classe DAL e classe AcessoSQL.

A classe DAL possui uma dependência da classe AcessoSQL.

 

A Injeção de Dependência é um tipo de Inversão de Controle e significa que uma classe não mais é responsável por criar ou buscar os objetos dos quais depende.

Isso serve para desacoplar as classes, evitando dependência direta entre elas.

Os resultados são:

  • Obtemos um maior índice de reaproveitamento de código;
  • Permite incluir novas funcionalidades sem alterar as já existentes;
  • Permite criar mocks em testes unitários;

Para realizar a injeção de dependência usamos interfaces e/ou um framework que vai injetar as dependências que precisamos usar.

No nosso exemplo para implementar a injeção de dependência usamos uma interface que foi injetada no construtor da classe DAL para obter uma instância do objeto AcessoSQL :

Public Class DAL
    Private IAcessoSQL As _sql
    Public Sub New(IAcessoSQL as sql)
        _sql = sql 
    End Sub
End Class

Para ficar mais claro o conceito vamos a um exemplo prático.

Usando a injeção de dependência :  o problema

Vou usar um exemplo prático bem simples que adaptei de uma resposta de um tópico no Stackoverflow.

Vou usar um projeto do tipo Console Application usando a linguagem VB .NET.

Este exemplo não utiliza nenhum framework de injeção de dependência para tornar o exemplo mais claro.

Vamos supor que você tem um sistema que processa pagamentos com Boleto, Cartão e Dinheiro e possui uma classe Pagamento que implementa o método efetuarPagamento da seguinte forma:

Public Class Pagamento
    Private Sub efetuarPagamento(ByVal tipo As String, ByVal codigo As Integer, ByVal valor As Double)
        If "BOLETO".Equals(tipo) Then
            Dim integracaoBoletoBanco As New IntegracaoBoletoBanco()
            integracaoBoletoBanco.pagarBoleto(codigo, valor)
        ElseIf "CARTAO".Equals(tipo) Then
            Dim integracaoCartaoBanco As New IntegracaoCartaoBanco()
            integracaoCartaoBanco.pagarCartao(codigo, valor)
        ElseIf "DINHEIRO".Equals(tipo) Then
            Dim integracaoContaBanco As New IntegracaoContaBanco()
            integracaoContaBanco.pagarDinheiro(codigo, valor)
        End If
    End Sub
End Class

No código usado no método efetuarPagamento percebemos que temos 3 dependências que são instâncias diretas de outras classes que precisamos para o método funcionar.

Isso faz com que o código da classe Pagamento seja fortemente acoplado com essas dependências e isso traz diversos problemas sendo o principal delas a necessidade de realizar alterações nesta classse sempre que alguma implementação for alterada.

Como podemos resolver esse problema ?

Usando a injeção de dependência para desacoplar a classe pagamento das instâncias que estão sendo criadas diretamente na classe.

Vamos fazer isso injetando essas dependências usando interfaces.

Aplicando a injeção de dependência

Vamos iniciar criando uma interface que vai definir um método para realizar pagamentos.

Inclua uma interface chamda IPagamentoServico no projeto

Public Interface IPagamentoServico
    Sub Pagamento()
End Interface

A seguir vamos criar as classes PagamentoBoleto, PagamentoCartao e PagamentoDinheiro que implementa a interface e define a sua forma de pagamento:

PagamentoBoleto

Public Class PagamentoBoleto
    Implements IPagamentoServico
    Public Sub Pagamento() Implements IPagamentoServico.Pagamento
        Console.WriteLine("Pagamento com Boleto")
    End Sub
End Class

PagamentoCartao

Public Class PagamentoCartao
    Implements IPagamentoServico
    Public Sub Pagamento() Implements IPagamentoServico.Pagamento
        Console.WriteLine("Pagamento com Cartão de Crédito/Débito")
    End Sub
End Class

PagamentoDinheiro

Public Class PagamentoDinheiro
    Implements IPagamentoServico
    Public Sub Pagamento() Implements IPagamentoServico.Pagamento
        Console.WriteLine("Pagamento com Dinheiro")
    End Sub
End Class

Agora vamos criar uma classe Cobranca onde vamos injetar as dependências dos pagamentos e definir um método Pagamento que usa a instância para realizar o pagamento:

Public Class Cobranca
    Private ReadOnly _pagamentoServico As IPagamentoServico
    Public Sub New(pagamentoServico As IPagamentoServico)
        _pagamentoServico = pagamentoServico
    End Sub
    Public Sub Pagamento()
        _pagamentoServico.Pagamento()
    End Sub
End Class

Para poder definir as formas de pagamentos vamos criar a classe AgenciaCobradora que retorna instãncias das formas de pagamentos:

Public Class AgenciaCobradora
    Public Function GetPagamentoCartaoService() As IPagamentoServico
        Return New PagamentoCartao
    End Function
    Public Function GetPagamentoBoletoService() As IPagamentoServico
        Return New PagamentoBoleto
    End Function
    Public Function GetPagamentoDinheiroService() As IPagamentoServico
        Return New PagamentoDinheiro
    End Function
End Class

Agora é só alegria...

Vamos usar no método Main() do Module1 a nossa implementação com injeção de dependência:

Module Module1
    Sub Main()
        'Cria uma instância da classe AgenciaCobradora
        'Tem acesso aos tipos de pagamentos
        Dim injetor As New AgenciaCobradora
        'define as formas de pagamento
        Dim pagamentoServicoCartao = injetor.GetPagamentoCartaoService
        Dim pagamentoServicoBoleto = injetor.GetPagamentoBoletoService
        Dim pagamentoServicoDinheiro = injetor.GetPagamentoDinheiroService
        'cliente vai pagar com cartão
        Dim clientePagamento As New Cobranca(pagamentoServicoCartao)
        clientePagamento.Pagamento()

        Console.ReadLine()
    End Sub
End Module

Agora nosso código ficou desacoplado e não temos mais dependências diretas que propagam suas alterações.

Usando um framework de injeção de dependência como o Ninject, Unity, etc., podemos refatorar e melhorar ainda mais o nosso código.

Pegue o projeto completo aqui:    Vbn_DI.zip

(disse Jesus) "Não crês tu que eu estou no Pai, e que o Pai está em mim? As palavras que eu vos digo não as digo de mim mesmo, mas o Pai, que está em mim, é quem faz as obras."
João 14:9

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

Referências:


José Carlos Macoratti