DevMedia - asp.net, Java, Delphi, SQL e web Design, tudo em um só lugar!
Bem vindo a DevMedia!
LOGIN:     SENHA:
 
 

  Este é um post disponível para assinantes MVP
Este post também está disponível para assinantes da ClubeDelphi DIGITAL ou para quem possui Créditos DevMedia.  Clique aqui para saber mais!


Inversão de Controle e Injeção de Dependência - Revista ClubeDelphi 133

Este artigo mostra o que é e como usar inversão de controle e a injeção de dependência. Você aprenderá na prática, através de um exemplo, como estes princípios de programação orientada a objetos podem ser usados e qual as vantagens que eles traz






Diz-se que um projeto está altamente acoplado quando suas classes e módulos conhecem muito um do outro, criando uma grande dependência entre eles. Isto acontece, na maioria das vezes, devido a uma decisão errada, tomada pelo projetista, que aos pouco encaminha o projeto para um design caótico onde uma simples manutenção de rotina pode desencadear uma série de erros em outro ponto do projeto.

O grande vilão, que pode tornar uma alteração pequena em um verdadeiro desastre é o relacionamento entre as classes, por isso é vantajoso investir o tempo necessário (ou possível), para criar designs onde as classes sejam capazes de se relacionar conhecendo o mínimo uma da outra. Criar classes coerentes que dependem apenas de interfaces é uma das formas de garantir o baixo acoplamento, porém o princípio “programe para interface”, sozinho não ajudará muito.

O problema do alto acoplamento

Podemos medir o quão fortemente as classes de uma aplicação estão conectadas, possuem conhecimento ou dependem de outra classe observando o acoplamento existente em cada caso. Quanto mais acoplada uma classe estiver de outra maior o risco de termos uma combinação dos seguintes problemas:

·         Mudanças numa classe relacionada forçam alterações locais à classe para que o funcionamento seja mantido;

·         O reuso da classe torna-se mais difícil uma vez que sua implementação depende de outras classes;

·         A coesão da classe diminui na medida em que aumenta o acoplamento caso ela assuma parte das responsabilidades de outra classe;

·         A classe não pode ser testada isoladamente já que depende de testes em conjunto com outras classes, aumentando inclusive o esforço de entendimento.

Percebemos rapidamente que diminuindo ao máximo o acoplamento além de evitarmos os problemas mencionados anteriormente tornaremos nossa aplicação mais flexível e fácil de ser mantida, especialmente em equipes com paralelismo de desenvolvimento de atividades correlatas.

Utilizando as corretas técnicas e ferramentas para injeção de dependência, diversos componentes podem ser desenvolvidos paralelamente (aproveitando de recursos como Mock Objects para auxiliar nos testes unitários) e sua aplicação se tornará mais plugável e flexível, exigindo um esforço menor para modificações.

Técnicas para resolver o problema de alto acoplamento

Tomemos como exemplo uma classe chamada ClasseA que depende dos serviços Servico1 e Servico2, conforme a Figura 1.

Se em algum momento necessitarmos substituir ou atualizar alguma das suas dependências, a classe ClasseA sofrerá alterações em seu código, uma vez que está relacionada diretamente com as classes de serviço. Outro ponto é que as implementações concretas das dependências precisam estar disponíveis no momento da compilação da solução. Uma das soluções seria delegar a função de selecionar a implementação da classe concreta para um componente (ou um container) externo.

Em diversas literaturas podemos encontrar esta solução sendo descrita como Padrão de Inversão de Controle (Inversion of Control Pattern, ou simplesmente IoC), onde a Injeção de Dependência é uma das maneiras de a implementarmos (assim como o Service Locator Pattern), conforme observamos na Figura 2. Sendo assim, é correto afirmarmos que a DI é um caso particular de IoC.

A classe ClasseA ao invés de fazer referência à classe concreta passa a referenciar uma interface IServicoA que por sua vez é implementada pelo serviço Servico1, o objeto identificado como Builder fica encarregado de resolver a classe concreta e injetar a dependência na classe ClasseA.

Também é importante e necessário, que o projetista saiba como usar uma interface corretamente e para isto ele pode recorrer aos padrões de projetos. A maioria dos padrões de projetos usa interfaces e definem classes coerentes com baixa coesão para solucionar os problemas que se propõem a resolver. Mesmo assim, existem decisões, cujas respostas o projetista não vai encontrar em um padrão de projeto. Por exemplo: é melhor criar uma interface usando uma classe abstrata ou uma interface de fato? A resposta não é tão obvia quanto parece.

Outra forma de diminuir o acoplamento é a inversão de controle ou em inglês Inversion of Control (IoC). Inversão de controle é um princípio de orientação de objetos que define várias formas de simplificar um projeto invertendo o controle natural dos componentes. Existe mais de uma forma de inversão de controle: umas delas é a injeção de dependência.

A injeção de dependência ou em inglês dependency injection (DI), significa que uma classe não deve controlar as suas dependências, evidentemente tornando o projeto mais flexível. Nesta abordagem uma classe recebe suas dependências sem conhecer como elas são criadas ou de onde elas vêm. Pode parecer estranho para quem está escutando isto pela primeira vez, mas é isto mesmo que você leu. De forma superficial a injeção de dependência pode ser explicada assim: se a classe A precisa da classe B, então A não deve executar B.Create().

Como dito, existem outras formas de inversão de controle além da injeção de dependência. Outro exemplo disto está na própria VCL. Quando você cria um formulário e escreve qualquer instrução no evento OnCreate do mesmo, você está usando a inversão de controle, pois não é você quem controla a execução das instruções que você escreveu no evento, mas sim o framework, que neste caso é a VCL. É o framework que decide quando executar o código, e não o contrário.

Tipos de relacionamentos e o que eles têm a ver com DI

A técnica de injeção de dependência atua diretamente na forma como as classes e objetos se relacionam dentro de um projeto, por isto este tópico é dedicado a explicar quais sãos os tipos de relacionamentos existentes e a diferença entre eles. Você pode pular para o próximo tópico se estiver familiarizado aos jargões composição/agregação e já sabe por que dar preferência a eles é (quase sempre) melhor do que criar um relacionamento do tipo herança. "



ATENÇÃO! A exibição deste artigo foi interrompida.


  Este é um post disponível para assinantes MVP
Este post também está disponível para assinantes da ClubeDelphi DIGITAL ou para quem possui Créditos DevMedia.  Clique aqui para saber mais!






    1 COMENTÁRIO

[Fechar]

Este post é fechado - você precisa ter acesso ao post para incluir um comentário.



Devmedia - Equipe De Moderacao
Errata:
Na revista CD 133, no artigo de Inversão de Controle e Injeção de Dependência, há um erro na Figura 8.

Ao invés da classe TNaoComer na interface IGrasnas, e a TGrasnarDoPatoDeBorracha na IComer, o correto é o inverso. 

No Leitor Digital você confere o diagrama correto.
[há +1 mês] - Responder

 



Publicidade
Autor
Rafael Stavarengo

Programador de sistemas a 8 anos, integrante da equipe editorial da revista Clube Delphi. Domínio em Java, PHP e UML. Sólido conhecimento em Design Patterns e metodologia ágeis. Graduado em Análise e Desenvolvimento de Sistemas pela UNIPAR.


Space do autor
Estatísticas
Favorito:
Comentários:
Feedback:
Utilidade:
1   0
[Fechar]

Você precisa estar logado para dar um feedback.

Clique aqui para efetuar o login
[Fechar]


Este post está fechado. Saiba mais sobre a assinatura MVP!
web-03
DevMedia  |  Anuncie  |  Fale conosco
Hospedagem web por Porta 80 Web Hosting
2012 - Todos os Direitos Reservados a web-03