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:
- Inversion of Control Containers and the Dependency Injection pattern. By Martin Fowler. http://martinfowler.com/articles/injection.html
- Containers de Inversão de Controle e o padrão Dependency Injection. By Martin Fowler. Traduzido por Ronald Tetsuo Miura. http://www.javafree.com.br/home/modules.php?name=Content&pa=showpage&pid=4
- Veja o principio da responsabilidade única – SRP