InfoQ

InfoQ

Notícias

Meus Favoritos

Faça oLogin ou Cadastre-se para ativar o recurso de favoritos por tempo ilimitado.

O conteúdo foi adicionado aos favoritos!

Houve um erro ao adicionar aos favoritos! Por favor, tente novamente.

Desacoplando sua aplicação do seu framework de injeção de dependências

Postado por Mike Bria , traduzido por Lucas Souza em 27 Jan 2010

Seções
Desenvolvimento,
Processos e Práticas,
Arquitetura Corporativa,
Arquitetura e Design
Tópicos
Arquitetura ,
Design ,
SOA ,
Ruby ,
Agile ,
.NET ,
Java ,
Design Orientado a Objeto
Tags
Guice ,
Dependency Injection

Injeção de dependências tornou-se nos últimos anos uma das abordagens mais usadas na Orientação a Objetos, graças a técnicas como TDD e Testes Automatizados e mais alguns fatores. Muitas vezes é comum utilizarmos alguns frameworks de injeção de dependências para nos auxiliar. O uso de injeção de dependências tornou-se tão comum que na nova versão Java EE 6, umas das novidades é a parte de Dependency Injection ou como é mais conhecida CDI (JSR 299).

Bob Martin mais conhecido como Uncle Bob nos passa algumas dicas em seu artigo escrito recentemente. Umas das dicas é:

...Eu não quero que o código do framework de injeção de dependências esteja espalhado por todo o código da minha aplicação. Eu quero manter o framework bem desacoplado e longe do corpo principal do meu código.

Para mostrar mais especificamente o que quis dizer, Uncle demonstrou isso utilizando como exemplo uma classe de BillingService que tem algumas dependências que são passadas atráves de seu construtor:

public class BillingService {
	...
	BillingService(CreditCardProcessor processor, TransactionLog transactionLog) {
		this.processor = processor;
		this.transactionLog = transactionLog;
	}
	...
}

Ele demonstra primeiro um pequeno código para criar uma instância da classe BillingService que utiliza o framework Guice(Framework de injeção de dependências do Google)

public static void main(String[] args) {
	Injector injector = Guice.createInjector(new BillingModule());
	BillingService billingService = injector.getInstance(BillingService.class);
	billingService.processCharge(2034, "Bob");
}

Depois de analizar o código, Uncle chegou a conclusão que agora sempre que precisamos de uma instância de BillingService, podemos obtê-las de forma extremamente simples atráves do Guice sem nos preocuparmos com as suas dependências. Porém agora teremos uma forte dependência com o Guice quando precisarmos de uma instância de BillingService.

Segundo Uncle acabamos com um problema, mas temos outro problema em mãos:

Injeção de Dependências é apenas uma forma especial de Inversão de Dependências. Eu penso que Inversão de Dependências é tão importante que eu quero inverter as dependências no Guice. Eu não quero um monte de dependências do Guice espalhadas pelo meu código.

Depois ele nos mostra atráves de uma simples Factory como podemos reduzir a dependência da nossa aplicação com os frameworks de DI:

public static void main(String[] args) {
	Injector injector = Guice.createInjector(new BillingModule());
	BillingService.factory = new BillingServiceFactory(injector);
}
...
// Deep in the bowels of my system.
BillingService billingService = BillingService.factory.make();
billingService.processCharge(2034, "Bob");

 Uncle explica com mais detalhes porque essa abordagem alternativa pode ser útil e como nos ajuda a diminuir o acoplamento com os frameworks de DI:

Eu gosto disso porque agora todo o Guice em um lugar bem definido. Eu não quero ter código do Guice por toda minha aplicação. Preferencialmente, eu tenho factories que tem o código do Guice. Guice Factories que mantém o código do Guice longe de toda minha aplicação. O que é melhor, se eu quiser substituir o Guice por algum outro framework de DI, eu sei exatamente quais classes teriam de ser mudadas, e como mudá-las. Portanto eu mantenho o Guice desacoplado da minha aplicação.

Um dos pontos interessantes da explicação do Uncle é que em todos os exemplos que ele mostra, é possível ver o uso de Injeção de Dependência, ou seja, o princípio e a idéia estão sempre sendo mantidos. Como as dependências da classe BillingService são resolvidas, estão sempre fora da própria classe, o que é de fato muito bom. Para ilustrar melhor isso, ele conclui o artigo mostrando um teste utilizando o Junit para a classe BillingService que utiliza simples"tests doubles" de TransactionLog e CreditCardProcessor. No teste ele constata que não importa qual mecanismo ele está utilizando para injetar as dependências, o teste sempre passará.

(Gary Bernhardt postou um artigo muito interessante destacando que o uso de "tests doubles" pode ser prudente quando utiliza-se Java ou outras linguagens estaticamente tipadas, mas não necessariamente em linguagens dinâmicas como Python)

E você, usa Injeção de Dependências? Usa algum framework para fazer isso? Se você usa ou não, o que você pensa disso?

JSR-299 e padronização da DI por Alessandro Lazarotti Enviado
  1. Voltar ao topo

    JSR-299 e padronização da DI

    por Alessandro Lazarotti

    Acredito que em tempos de padronização da DI pelo JavaEE, tentar desacoplar o framework de injeção em novos projetos é algo desnecessário. No passado, mesmo não estando 100% de acordo com o texto (na maioria des vezes isso seria excesso de preciosismo), sua utilidade pode ser de alguma relevâcia. Em novos projetos, se deseja ter independência de implementação utilize o que é padrão de fato, no caso CDI.

Conteúdo Educacional

Formando equipes de alto desempenho, parte 1: Início e fases de evolução

Nesta primeira parte de uma série sobre equipes de alto desempenho e gerenciamento Agile, veja uma introdução geral e uma apresentação dos estágios de formação das equipes.

Business Model Canvas, passo a passo

O Business Model Canvas é uma ferramenta estratégica para a construção visual de novos produtos ou serviços. Conheça cada um dos seus elementos e como preencher o Canvas, passo a passo.

Google Apps Script, Parte 2: Google Docs, triggers e envio de emails

Nessa segunda e última parte de uma série sobre o Google Apps Script, conheça como funciona o envio de emails, a conversão de documentos e como criar menus e triggers.

Serviços de cloud computing PaaS: um guia para desenvolvedores Java

Este artigo avalia seis dos mais importantes fornecedores de serviços de cloud computing PaaS para desenvolvedores Java, analisando critérios como desempenho, escalabilidade e tecnologias suportadas.

Canvas de Modelo de Negócios: uma contribuição para o sucesso de Startups

O Canvas de Modelo de Negócios é um novo modo de comunicar e suportar a validação iterativa, incremental e empírica de modelos de negócio de startups e novos produtos substituindo o plano de negócios.

Entrevista com Rebecca Parsons Parte 2: Agile Distribuído, Arquitetura vs. Design e SOA

Nesta segunda e última parte de uma entrevista exclusiva para InfoQ Brasil, Rebecca Parsons, CTO da ThoughtWorks, fala sobre o Agile Distribuído e técnicas para definição de arquiteturas.

Entrevista com Rebecca Parsons Parte 1: Agile nas Empresas e Arquitetura Evolucionária

Nessa primeira parte de uma entrevista com a CTO da ThoughtWorks, veja recomendações sobre formas de construir e arquitetar sistemas para obter o máximo de flexibilidade e responsividade a mudanças.

Agile das equipes à organização: o papel do gerente, estratégias e dicas para a adoção

Os gerentes de projetos podem assumir o papel crítico de liderar a introdução do Agile. Vejas conceitos, dicas e técnicas para apoiar esse processo de mudanças.