De que se trata o artigo

Neste artigo serão apresentados os principais aspectos do pattern conhecido como Injeção de Dependência. A partir disto, serão desenvolvidos exemplos de implementação do mesmo utilizando-se para isto o framework NInject.

Para que serve

O NInject é um container para Injeção de Dependência que procura oferecer uma alternativa simples para a implementação deste padrão. Busca com isto a obtenção de softwares constituídos de componentes com alta coesão e com um baixo acoplamento entre si.

Em que situação o tema será útil

Durante o desenvolvimento de aplicações em camadas é comum que se criem dependências entre diferentes partes de uma aplicação. Mudanças posteriores no escopo do projeto, dependendo da maneira como os componentes da mesma foram estruturados, tendem a ser difíceis de implementar ou, ainda, introduzirem erros imprevistos. A adoção de um framework de Injeção de Dependência como o NInject procura evitar este tipo de situação, já que foca no desenvolvimento de unidades de software com responsabilidades específicas e fracamente acopladas.

Injeção de Dependência com NInject

O padrão de projeto conhecido como Injeção de Dependência, conforme será exposto neste artigo, representa uma alternativa para evitar os possíveis problemas associados à construção de um software em camadas. A adoção deste pattern procura, assim, uma melhor estruturação no desenvolvimento de novas soluções, possibilitando ainda que mudanças sejam menos traumáticas à medida que as aplicações cresçam em tamanho e complexidade. Já o framework open source NInject, que também será apresentado a seguir, é uma implementação do conceito de Injeção de Dependência, tendo por objetivos oferecer simplicidade e facilidade de uso na construção de aplicações voltadas à plataforma .NET. Dois exemplos são utilizados para mostrar sua usabilidade.

Conceber aplicações de software bem estruturadas e flexíveis a mudanças têm sido, via de regra, um dos grandes desafios impostos à área de desenvolvimento de sistemas no decorrer dos anos. As organizações estão cada vez mais sujeitas a transformações repentinas e de profundo impacto. Isto acaba por exigir dos profissionais de Tecnologia da Informação uma resposta rápida ao atendimento de novas demandas ou, ainda, à adaptação de soluções pré-existentes.

Prazos exíguos, equipes reduzidas, falta de planejamento, inexistência de uma modelagem para a solução a ser entregue, dentre outros aspectos, quase sempre resultarão em codificação de baixa qualidade para a solução que será obtida. Isto pode se constituir, futuramente, num verdadeiro pesadelo em situações que exijam adaptações de funcionalidades já criadas anteriormente.

A utilização da técnica de desenvolvimento em camadas, prática amplamente difundida no mercado, procura fornecer meios para a criação de aplicações mais flexíveis. Entretanto, a simples utilização deste tipo de abordagem não garante por si só resultados positivos. Ainda existirá a possibilidade de se chegar a um produto que faz uso de classes de objetos com um alto grau de interdependência; com isto, ajustes que na teoria seriam simples levam a mudanças drásticas em todo um software, aumentando ainda a chance de se introduzirem erros inesperados na solução. A Injeção de Dependência auxilia a resolver esse dilema, desacoplando as camadas criadas.

Injeção de Dependência: uma visão geral

Primeiramente, deve-se levar em conta que a Injeção de Dependência (DI, do inglês Dependency Injection) é na verdade, uma aplicação específica de um conceito mais abrangente conhecido como Inversão de Controle (IoC, do inglês Inversion of Control).

Já a Inversão de Controle é uma técnica na qual um objeto delega a execução de uma atividade a outra classe, ao invés de tentar controlar diversos aspectos que fugiriam do objetivo inicial para o qual havia sido definido. Esta característica é particularmente importante, já que permite o desenvolvimento de classes com um maior grau de coesão, visto que não acumulam um grande número de responsabilidades, o que do contrário dificultaria a manutenção futura das mesmas e resultaria em um software mais propenso a falhas.

Basicamente implementa-se a inversão de controle da seguinte maneira:

· Separa-se “o que” será feito de “quando” a ação será disparada;

· Deve ser garantido que a parte que dispara a ação (“quando”) conheça o mínimo possível daquela que propriamente executa a atividade (“o que”), e vice-versa.

Um exemplo de como o padrão IoC é empregado seria o tratamento de eventos dentro de uma aplicação .NET. Um handler de evento representa “o que” será feito, ao passo que a atividade que dispara o evento corresponde a “quando” este último será acionado.

Conforme já foi mencionado anteriormente, o uso de injeção de dependência também é uma forma de se aplicar o conceito de inversão de controle. Neste caso ao invés de um objeto instanciar todas as classes das quais depende, o mesmo delega a um outro mecanismo (um framework / container de DI ou uma solução interna própria) esta tarefa.

Ao se optar pela utilização de um container o mesmo será responsável pelas seguintes atividades:

· Analisar de quais tipos de objetos uma classe depende;

· Criar os objetos a serem consumidos, podendo ainda controlar o ciclo de vida destes últimos (com um objeto existindo durante apenas a requisição atual num ambiente Web, sendo instanciando como um singleton comum a toda a aplicação etc.);

· Associar as instâncias de objetos criadas à classe consumidora, sendo que a isto se chama “resolver” as dependências.

Um container identificará as dependências através do uso de arquivos XML de configuração ou, ainda, analisando diretamente a estrutura da classe consumidora (o que pode ser auxiliado por meio do uso de atributos associados às declarações que deverão ser resolvidas). Além disso, utilizam-se geralmente interfaces para referenciar os objetos a serem consumidos dentro da classe cliente. É comum também que frameworks de injeção de dependência façam uso de recursos de reflection para resolver dependências.

Já a associação das instâncias de objetos geradas pelo container de Injeção de Dependência é feita, normalmente, através das seguintes técnicas:

· Declarando propriedades que contenham um getter e um setter na classe consumidora;

· Por meio de parâmetros no construtor da classe consumidora.

Além do container NInject que será apresentado mais adiante neste artigo, são também exemplos de frameworks de Injeção de Dependência para a plataforma .NET:

· Spring.NET (baseado no framework Spring, sendo este último um container amplamente difundido entre desenvolvedores da plataforma Java);

...
Quer ler esse conteúdo completo? Tenha acesso completo