gerenciamento de dependências

Post on 11-Jan-2016

7 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

PDF - explicando gerenciamento de dependências e inversão de controle

TRANSCRIPT

Gerenciamento de Dependências

por David Paulo Magalhães Araújo

Aplicativos referidos na apresentação

● JDK 6 ● Spring 2.5 ● Eclipse

Fontes

Spring Recipes, A Problem-Solution Approach http://www.springsource.org Google e Diversos sites da Internet

Índice

Active Lookup Gerência de dependências

Gerência Autônoma Gerência por containers

1) O que é um Container? 2) Exemplo: Gerador de Relatórios

3) Complexidade de pesquisa

Passive Lookup

Entendendo IOC (Inversion of Control) Entendendo Dependence Injection (DI)

1 – Gerência de dependências

Uma aplicação é composta de componentes. Cada componente desses precisa ser reutilizável

e ser o mínimo acoplado possível com outras classes que não sejam do componente, para que não se torne dependente destas. Apesar disso, a

maioria dos componentes de uma aplicação precisa do serviço de outros componentes. O Desenvolvedor deve fazê-los interagirem, mas sem comprometer-lhes a reusabilidade e evitar

que fiquem com o código acoplado.

1.1 – Gerência Autônoma

Esse método, apesar de ter a vantagem de ser simples, possui muitas desvantagens. Nele, cada componente é responsável por gerenciar suas dependências, fazendo eles ficarem muito acoplados uns com os outros. Sendo assim, O componente “A” agora é dependente da “implementação” do componente “B”, em vez de ser dependente somente de sua interface. Se qualquer alteração for feita no componente “B”, o código do componente “A” pode se tornar inválido. Como consequência, o componente “A” não pode ser reutilizado.

1 - O Componente “A” precisa do componente “B”.

2 - O Componente “A” importa o componente “B” (se necessário).

3 - O Componente “A” declara uma variável do tipo “B”.

4 - O Componente “A” instancia o componente “B” e o guarda na variável.

5 - O Componente “A” pode agora usar o componente “B”.

1.1 – Gerência Autônoma

Componente “A”

Componente “D”

Componente “C”

Componente “B”

os componentes são muito acoplados, se comportando como um bloco indivisível, onde uma alteração em qualquer classe, leva a necessidade de alterar as classes que dependem dela.

1.2 – Gerência por containers

A Gerência autônoma não satisfaz o desejo da reusabilidade e do desacoplamento, Além de dar uma responsabilidade a mais para todos os componentes: o de gerenciar suas próprias dependências. A abordagem por container procura evitar esses erros através de uma gerência centralizada.

1.2.1 – O que é um container?A Palavra container em si contém muitos significados no universo de TI, mas quando se fala em gerência de dependências, Um container é uma classe que possui referência para todos os componentes da aplicação e possui métodos que os disponibilizam. Com a ajuda dele, os componentes da aplicação não precisam mais instanciar as classes que necessitam, podendo somente, pedir uma referência para o container. Assim, os componentes podem deixar de ficar dependentes da implementação de outro componente, e passar a ser dependente somente das interfaces.

1.2 – Gerência por containers

Container

Componente “C” Componente “D”Componente “B”Componente “A”

Interface “2”Interface “1” Interface “3”

1.2.2 – Exemplo: Gerador de Relatórios

● Suponhamos que vamos desenvolver um sistema cuja função é gerar diferentes tipos de relatórios, ou em HTML ou em PDF. De acordo com o princípio da orientação à objetos de separar interface de implementação, Vamos criar uma interface para gerar relatórios. Vamos assumir que o argumento 'table' é o relatório, um array String.

package com.azul.springtest01;

public interface ReportGenerator{

public void generate(String[][] table);

}

1.2.2 – Exemplo: Gerador de Relatórios

● Agora, criaremos as classes 'HtmlReportGenerator' e 'PdfReportGenerator', para implementar a interface 'ReportGenerator' e gerar relatórios em HTML e em PDF, respectivamente.

package com.azul.springtest01; public class HtmlReportGenerator implements ReportGenerator{

public void generate(String[][] table){ System.out.println(“Gerando relatório em HTML”);

} }

package com.azul.springtest01; public class PdfReportGenerator implements ReportGenerator{

public void generate(String[][] table){ System.out.println(“Gerando relatório em PDF”);

} }

1.2.2 – Exemplo: Gerador de Relatórios

Com as classes implementadoras da interface 'ReportGenerator' prontas, você pode começar a implementar a classe 'ReportService', que age como um provedor para gerar diferentes tipos de relatórios. Note o uso da classe 'Container'.

package com.azul.springtest01; public class ReportService{

private ReportGenerator reportGenerator = (ReportGenerator) Container.instance.getComponent(“reportGenerator”);

public void generateAnnualReport(int year){

String[][] statistics = null; // // coletar estatísticas para o ano (year) … // reportGenerator.generate(statistics);

} }

1.2.2 – Exemplo: Gerador de Relatórios

Implementação da classe 'Container'

package com.azul.springtest01; import java.util.*;

public class Container{ public static Container instance; //Instância global da classe, para facilitar localização.private Map<String, Object> components; //Um mapa para guardar os componentes.

public Container(){ components = new HashMap<String, Object>(); instance = this; components.put(“reportGenerator”, new PdfReportGenerator()); components.put(“reportService”, new ReportService());

} public Object getComponent(String id){

return components.get(id); }

}

1.2.2 – Exemplo: Gerador de Relatórios

HtmlReportGenerator

+ generate(String[][]):void

<<Interface>>ReportGenerator

PdfReportGenerator

+ generate(String[][]):void

Container

+ getComponent(String):void

+ generate(String[][]):voidReportService

+ GenerateAnnualReport(int):void

1.2.3 – Complexidade de pesquisa

Com uma gerência por containers, os componentes dependem uns dos outros através de suas interfaces em vez de suas implementações. Porém, agora eles se tornaram dependentes do container, visto que fazem pesquisa por dependências usando complexos métodos proprietários. Isso impede esses componentes de funcionarem sob a gerência de outro container, que possua uma implementação diferente.

1.2.3 – Complexidade de pesquisa

Uma Solução para esse problema seria implementar o design pattern do Java EE chamado Service Locator, para retirar as dependências dos componentes para o container, impedindo que os componentes fiquem dependentes de código proprietário. Um exemplo de ServiceLocator é a classe abaixo:

package com.azul.springtest01; public class ServiceLocator{

private static Container container = new Container(); //Instancia novo container

public static ReportGenerator getReportGenerator(){ return (ReportGenerator) container.getComponent(“reportGenerator”);

} }

1.2.3 – Complexidade de pesquisa

Assim, a classe ReportService pode usar a Classe ServiceLocator dessa forma:

A Classe ReportService passaria a ser dependente da classe ServiceLocator. Toda vez que o container mudar, basta o ServiceLocator também mudar, e não todos os componentes da aplicação.

package com.azul.springtest01; public class ReportService{

private ReportGenerator reportGenerator = ServiceLocator.getReportGenerator();

public void generateAnnualReport(int year){ String[][] statistics = null; // coletar estatísticas para o ano (year) … reportGenerator.generate(statistics);

} }

1.2.3 – Complexidade de pesquisa

Com a classe ServiceLocator:

I. Todos os métodos de pesquisa são static. Assim sendo, não precisarem de uma instância para serem invocados.

II. Uma Classe pode ser localizada por outra classe, bastando a primeira ser visível para a segunda, e portanto, não precisa de uma instância static de si.

III. A Classe Container não precisa mais de uma instância static de si.

1.2.3 – Complexidade de pesquisa

HtmlReportGenerator

+ generate(String[][]):void

<<Interface>>ReportGenerator

PdfReportGenerator

+ generate(String[][]):void

Container

+ getComponent(String):void

+ generate(String[][]):void

ReportService

+ GenerateAnnualReport(int):void

ServiceLocator

+ getReportGenerator():ReportGenerator

2.1 – Entendendo IoC (Inversion of Control)

Todos os métodos de pesquisa discutidos anteriormente nessa apresentação se baseiam na pesquisa ativa, ou Active Lookup. Esse maneira de pesquisar dependências se baseia em paradigmas herdados da programação procedural e estruturada. No entanto, percebeu-se que o pensamento inverso a esse princípio traz mais reusabilidade e modularidade para a programação orientada a objetos. A esse novo pensamento ou princípio, deu-se o nome de Inversão de Controle ou Inversion of Control (IoC), pois inverte a ordem normal e procedural de se programar até então.

2.2 – Entendendo Dependence Injection (DI)

Injeção de dependência ou Dependence Injection(DI) é um design pattern que implementa o paradigma IoC. Enquanto IoC é um princípio abstrato, DI o realiza. Nesse design pattern, em vez do componente buscar suas próprias dependências através de gerência autônoma ou usando um container e um Service Locator (Active Lookup), ele confia que sua dependência será satisfeita por alguém (Passive Lookup). Para entendermos melhor, veremos agora o exemplo de João, O apertador de parafusos.

2.2 – Entendendo Dependence Injection (DI)

Em uma empresa trabalha João, cujo emprego é apertar parafusos.

Saudações! Eu sou João, O apertador de parafusos.Apertar parafusos é comigo mesmo!

2.2 – Entendendo Dependence Injection (DI)

Certo dia, seu chefe lhe disse:

João, Aperte aquele parafuso.

2.2 – Entendendo Dependence Injection (DI)

Mas joão percebeu que faltava um pequeno detalhe para fazer seu trabalho....

2.2 – Entendendo Dependence Injection (DI)

João precisava de uma chave de fenda para fazer seu trabalho, e foi correndo ao almoxarifado

buscar uma, mas...

A Porta do almoxarifado está fechada...

2.2 – Entendendo Dependence Injection (DI)

Para conseguir a chave, João vai ao encontro do atendente, que possui as chaves da empresa. O

Atendente lhe entrega as chaves.

2.2 – Entendendo Dependence Injection (DI)

Com a chave em mãos, João vai agora para oAlmoxarifado, onde ele poderá finalmente obter

Sua ferramenta de trabalho.

2.2 – Entendendo Dependence Injection (DI)

João abre a porta, E...

2.2 – Entendendo Dependence Injection (DI)

Vê várias caixas... E agora? Em qual das caixas A ferramenta se localiza?

!

2.2 – Entendendo Dependence Injection (DI)

Percebendo que precisava de ajuda, João vai falar com o zelador do almoxarifado, Perguntando a localização do instrumento. O Zelador responde que está na menor caixa da primeira fileira.

?

2.2 – Entendendo Dependence Injection (DI)

Com a informação em mente, João retorna ao almoxarifado e abre a porta.

2.2 – Entendendo Dependence Injection (DI)

No almoxarifado, ele abre a menor caixa da Primeira fileira, e depois de procurar um pouco, Acha a ferramenta desejada.

2.2 – Entendendo Dependence Injection (DI)

Acabou? Ainda não... tudo o que foi feito até Agora era somente para obter o instrumento Para que joão pudesse desempenhar seu papel. Ele agora deve fazer a parte mais importante.

2.2 – Entendendo Dependence Injection (DI)

Com a ferramenta em mãos, João pode Finalmente apertar o parafuso.

2.2 – Entendendo Dependence Injection (DI)

João aperta o parafuso, e...

2.2 – Entendendo Dependence Injection (DI)

Finalmente, O Trabalho foi concluído! João Conseguiu completar sua tarefa, apesar de todos Os imprevistos!

2.2 – Entendendo Dependence Injection (DI)

Mas todo esse trabalho é muito complexo para João sozinho. João, o apertador de parafusos, Agora também é João, o buscador de Ferramentas, João, O porteiro do almoxarifado Etc...

2.2 – Entendendo Dependence Injection (DI)

Perceba que João, O Apertador de parafusos, é Uma classe que resolve todos os seus problemas Sozinha. Isso a deixa muito complexa, e a desvia De seu real propósito: Apertar parafusos. A empresa poderia contratar uma pessoa que fizesse o trabalho de buscar as ferramentas, esperando que alguém lhe peça. Isso faria essa pessoa ser semelhante a um Service Locator. Porém, essa abordagem também não seria interessante, pois, se por acaso, essa pessoa fosse substituída, seria necessário informar todos os funcionários da empresa sobre a substituição.

2.2 – Entendendo Dependence Injection (DI)

Em vez disso, a empresa poderia contratar uma pessoa que, com antecipação, já soubesse o que Cada funcionário precisa, e assim, buscasse as ferramentas e lhes entregasse antes mesmo que eles pedissem. Assim, nenhum funcionário precisaria se preocupar em quem entrega as ferramentas, pois eles saberiam que alguém se comprometeu em entregar-lhes o que precisavam. Essa pessoa se assemelharia, então, a um container de injeção de dependências (DI container).

2.2 – Entendendo Dependence Injection (DI)

Em um container de injeção de dependência, os componentes da aplicação não precisam mais possuir uma referência direta ou indireta ao container. Assim, torna desnecessário o uso de um Service Locator, pois é o container que gerenciará as dependências e é ele que determinará que dependências cada componente precisa.

2.2 – Entendendo Dependence Injection (DI)

Container

Componente “C” Componente “D”Componente “B”Componente “A”

Interface “2”Interface “1” Interface “3”

FIM

top related