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.

Atenção: esse artigo tem um vídeo complementar. Clique e assista!

De que se trata o artigo

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 trazem.

Em que situação o tema é útil

A inversão de controle torna um projeto mais escalável e simples de entender. Este é um conhecimento obrigatório para qualquer programador que se preze. Este artigo ajudará você a entender porque a herança deve ser evitada explicando onde a inversão de controle pode ser usada para substituí-la.

Inversão de Controle e Injeção de Dependência

Como desenvolvedores de software, estamos sempre preocupados em criar um projeto escalável, e nos esforçamos para isto. Para atingir este objetivo é possível usar padrões, técnicas e até filosofias de desenvolvimento diferentes. Indiferente de como sua equipe escolheu trabalhar, todo projeto flexível tende para o mesmo lado: diminuir o acoplamento entre as classes. Este artigo explica como usar a inversão de controle para diminuir o acoplamento e apresenta algumas opções para injetar automaticamente as dependências de uma classe a fim de conseguir um projeto mais flexível.

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 poucos 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.

Figura 1. Dependência entre classes

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. "

[...] continue lendo...

Artigos relacionados