.NET

20 jan, 2009

O padrão de inversão de controle (IoC)

Publicidade

Adotar boas práticas no processo de desenvolvimento de software deixou de ser um diferencial para ser uma questão de sobrevivência.

O cenário atual aponta para uma grande demanda por software de qualidade com prazo e custos cada vez mais reduzidos. Não há mais lugar para desculpas como falta de recursos ou de tempo. Ou você oferece o que o mercado deseja ou está fora.

Usar padrões é uma das atitudes que beneficia o projeto pois facilita o reuso, os testes e permite uma melhor manutenabilidade do produto.

Este artigo apresenta o padrão inversão de controle (IoC) também conhecido como injeção de dependência (há uma certa polêmica quanto a essa correspondência…)

Se você nunca ouviu falar em inversão de controle (IoC) saiba que este padrão é muito usado em projetos orientados a objeto e utiliza conceitos como interface, herança e polimorfismo e tem como objetivo reduzir o acoplamento, facilitar o reuso e os testes no projeto de software.

Neste artigo vou dar um enfoque prático ao assunto e procurar mostrar como usar a inversão de controle (IoC) no seu projeto de software .NET. Vamos lá…

Antes de iniciar creio que seria bom lembrar algumas definições importantes que serão usadas neste artigo:

Nota: Veja detalhes sobre o assunto no meu artigo : http://www.macoratti.net/vbn_oopc.htm

1- Objeto

  • Um objeto é a representação de um modelo abstrato definido em uma classe;
  • Um objeto é uma instância de uma classe;
  • O estado de um objeto é o conjunto de suas propriedades;
  • Cada objeto tem o seu próprio estado;
  • O comportamento de um objeto são as funções (métodos) que afetam suas propriedades e/ou as propriedades de outros objetos;

2- Classe

  • Uma classe é o modelo a partir do qual os objetos serão criados;
  • Um objeto é uma instância de uma classe;
  • Uma classe define as propriedades e o comportamento que cada uma de suas instâncias(objetos) possuirá;
  • Classes podem se comunicar em entre si trocando informações (dados, parâmetros, controles,etc.);

3- Acoplamento

  • Acoplamento é o nível de dependência/conhecimento que pode existir entre as classes;
  • Uma classe com acoplamento fraco não é dependente de muitas classes para fazer o que ele tem que fazer;
  • Uma classe com acoplamento forte depende de muitas outras classes para fazer o seu serviço;
  • Uma classe com acoplamento forte é mais difícil de manter, de entender e de ser reusada;

4- Coesão

  • Coesão é o nível de integralidade interna de uma classe; (Veja o principio da responsabilidade única – SRP)
  • A coesão mede o grau que um classe ou seus métodos fazem sentido, ou seja, quão claro é o entendimento do que a classe ou método possui;
  • Uma classe com alta coesão possui responsabilidades bem definidas e são difíceis de serem desmembradas em outras classes;
  • Uma classe com baixa coesão possui muitas responsabilidades, geralmente que pertencem a outras classes, e podem ser facilmente desmembradas em outras classes;
  • Uma classe com baixa coesão é difícil de entender, manter e reusar;

Portanto quanto mais forte o acoplamento e mais baixa a coesão de uma classe mais difícil ela será de entender, manter e ser reusada.

Agora vamos à parte prática onde irei mostrar como podemos aplicar o padrão inversão de controle.

Nota: Todos os códigos mostrados foram obtidos usando o Visual Basic 2005 Expres Edition

Abaixo temos o código da classe A (A.vb) que usa uma outra classe B (B.vb):

Public Class A

    Private b As B
                                             
    Public Sub New()
        b = New B()
         Console.WriteLine("Foi criado o objeto b")
    End Sub

End Class

A classe A acessa diretamente a classe B criando uma instância da classe no seu construtor.

Vamos supor que :

  • A classe B é uma classe concreta com um construtor padrão;

O código da classe B é dado a seguir:

Public Class B

    Public Sub New()
        Console.WriteLine("Foi criada uma instância da classe B")
    End Sub
End Class

Neste exemplo temos um forte acoplamento entre a classe A e a classe B pois quem controla a criação de uma instância da classe B é a classe A. A classe A é responsável por obter uma referência a classe B.

Qualquer alteração que ocorra na classe B vai afetar diretamente a classe A pois esta possui uma referência a classe B.

Como fazer com que a classe A não seja afetada pelas mudanças feitas na classe B sem perder a referência para a classe B ?

Como diminuir o acoplamento entre a classse A e a classe B?

Podemos fazer isso usando o padrão inversão de controle (IoC).

Nota: Existem frameworks que usam o padrão IoC e que efetuam a injeção de dependência.

Vemos abaixo a classe A(A.vb) ajustada para usar o padrão IoC:

Public Class A
   Private b As B

   Public Sub New()
   End Sub

   Public Sub setB(ByVal b As B)  
       Me.b = b
   End Sub
End Class

Agora a classe A obtém uma referência da classe B usando o método setB();

– Dessa forma a classe A pode obter uma referência da classe B sem saber como a classe B é instanciada

– A classe B pode ser uma interface, classe abstrata ou mesmo uma classe concreta.

– Não existe mais nenhum acoplamento entre a classe A e a classe B;

– Qualquer alteração feita na classe B não afeta a classe A e vice-versa;

Se houver uma alteração no método da classe B, a classe A deverá ser alterada também mas a criação do objeto b não tem a sua implementação na classe A, podemos usar o método setB() para injetar o objeto b.

Perceba que tudo isto que foi colocado usa princípios básicos da programação orientada a objetos e não existe segredo algum, então quando se ouve falar que “O framework Spring usa a injeção de dependêcia…” ele esta basicamente usando os recursos que expusemos neste artigo.

Obs: O “Unity Application Block” do “Enterprise Library 4.0” é um container de inversão de controle baseado na biblioteca “ObjectBuilder2” do “Entreprise Library” e que foi lançado como uma alternativa às já tradicionais bibliotecas “Spring.NET” (uma versão da famosa biblioteca Spring do mundo Java), “Castle Windsor”, “StructureMap”, “ObjectBuilder” etc.

Referências: