Category Archives: C#

Inversão de Controle (IoC)

Senhoras e Senhores leitores desse blog, preparem-se para um momento marcante desse…blog….

[rufam os tambores]

Vamos falar sobre Inversão de Controle e Injeção de Dependência !!

[Fogos de artifícios explodem, papéis picados e coloridos caem sobre a multidão e a multidão vai ao delírio!]

Ao ler isso, você pode cair em 3 situações

1- Você vê as pessoas vibrando em volta de você, mas ainda não sabe o porque de tanta euforia. Você ainda não tem certeza do que venha ser Injeção de Dependência. Então, limpe os papeis picado que cai sobre seus ombros e vamos fazer parte dessa multidão que vai ao delírio, com todos sabendo exatamente do que estamos falando!

2- Você vibra com um soco no ar! E diga-se por passagem, Já era tempo !!

3- Você já sabe tudo sobre isso e zomba aqueles que estão vibrando, pulando, como se fosse uma grande novidade. Ficará só mais um momento nesse blog para vangloriar-se de sua superioridade! Noobs!

Por que toda a galera foi ao delírio ?

Para explicar o conceito de Inversão de Controle, vamos a um exemplo simples.

Vejamos o Controller abaixo

public class ClientesController : Controller
{
      public ActionResult Index()
      {
            var cliente = new Cliente();
            var todosClientes = cliente.TodosClientes();
            return View(todosClientes);
      }
 }
 

O código acima compila e executa sem nenhum erro, isto é, supondo que temos um método chamado TodosClientes que nos retornaria do banco de dados todos os nossos clientes cadastrados.

What’s the Big Deal ? O que há de errado então ?

Bom, eu, particularmente, não diria que há algo errado, mas diria que está fora dos padrões de qualidade. Minha opinião!

O problema no código acima é o que chamamos de Alto Acoplamento (lembrando que sempre buscamos desenvolver um código de Baixo Acoplamento e Alta Coesão).

Fazendo uma rápida análise no código acima, podemos listar as seguintes responsabilidades da classe ClientesController:

1- Ela instancia um Cliente.
2- Está buscando todos os clientes da base.
3- Passa todos esses clientes para uma view e retornar a view.

Agora vamos listar o que há de mal nessa classe.

1- Ela cria uma instância de um Cliente
Ao instanciar um cliente na nossa classe ClientesController criamos uma dependência da classe Cliente, o que faz com que qualquer alteração no cliente, afete diretamente o nosso controller, o que certamente prejudicaria a manutenção do código.

2- Está buscando todos os clientes da base de dados
Vamos pensar no teste unitário nesse caso. Os testes unitários devem ser independentes de conexão. Ao testarmos a classe Controller, o que aconteceria?

Temos uma forte dependência com o nossa conexão com o banco de dados para para que seja possível o retorno dos clientes, o que impossibilitaria mockar o Cliente.

Como Resolver ?

E é aí que entra a Inversão de Controle, em outras palavras, vamos inverter o controle na classe ClientesController, tirando qualquer responsabilidade vinculada à classe Cliente, e passaremos isso para uma outra classe, ou interface.

Mas de que Modo? Como faço essa inversão de controle ?

Injeção de Dependência!

Existem 3 maneiras de fazermos a nossa famosa injeção de dependência

1- Via Construtores
2- Nas Propriedades
3- Via Interface:

Então vamos praticar cada um deles, editando o nosso código inicial

Primeiro vamos injetar dependência com Construtores

public class ClientesController : Controller
{
     private ICliente _cliente;
     public ClientesController(ICliente cliente)
     {
          _cliente = cliente;
     }
     public ActionResult Index()
     {
          var todosClientes = _cliente.TodosClientes();
          return View(todosClientes);
     }
}

Com esse código, você já ganha um novo amigo!, o cara lá do teste! Easypeasy fazer amizades !!

Agora vamos ver como ficaria a injeção de dependência utilizando as propriedades, Getters e Setters

public class ClientesController
{
    private ICliente _cliente;
    public ClientesController()
    {
    }
    public ICliente Cliente
    {
        get  {
           if (_cliente != null)
               return _cliente;
        }
        set  {
           meuPedido = value;
        }
    }
 }


Bom, e temos alguma restrição de quando usar um e quando usar outro método ?

Pode-se dizer que a injeção de dependência por propriedades é preferível quando os construtores não possuem nenhum argumento, o que faz com que seja bem fácil você criar o objeto em produção e testá-lo.

Mas vamos eleger um vencedor aqui então!

Meu voto vai para a injeção de dependência via construtores.

Por Que ?

Uai, porque com isso eu garanto a ordem de inicialização, o que previne uma dependência circular em meu projeto, enquanto que com injeção de propriedades você não saberia bem ao certo em qual ordem você deve chamar cada get/set.

Bom, outras opiniões, serão bem vindas nos coments !!

até a próxima !