gerenciamento de dependências

43
Gerenciamento de Dependências por David Paulo Magalhães Araújo

Upload: jambo

Post on 11-Jan-2016

7 views

Category:

Documents


0 download

DESCRIPTION

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

TRANSCRIPT

Page 1: Gerenciamento de dependências

Gerenciamento de Dependências

por David Paulo Magalhães Araújo

Page 2: Gerenciamento de dependências

Aplicativos referidos na apresentação

● JDK 6 ● Spring 2.5 ● Eclipse

Page 3: Gerenciamento de dependências

Fontes

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

Page 4: Gerenciamento de dependências

Í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)

Page 5: Gerenciamento de dependências

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.

Page 6: Gerenciamento de dependências

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

Page 7: Gerenciamento de dependências

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.

Page 8: Gerenciamento de dependências

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.

Page 9: Gerenciamento de dependências

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.

Page 10: Gerenciamento de dependências

1.2 – Gerência por containers

Container

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

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

Page 11: Gerenciamento de dependências

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);

}

Page 12: Gerenciamento de dependências

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”);

} }

Page 13: Gerenciamento de dependências

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);

} }

Page 14: Gerenciamento de dependências

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); }

}

Page 15: Gerenciamento de dependências

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

Page 16: Gerenciamento de dependências

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.

Page 17: Gerenciamento de dependências

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”);

} }

Page 18: Gerenciamento de dependências

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);

} }

Page 19: Gerenciamento de dependências

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.

Page 20: Gerenciamento de dependências

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

Page 21: Gerenciamento de dependências

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.

Page 22: Gerenciamento de dependências

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.

Page 23: Gerenciamento de dependências

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!

Page 24: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

Certo dia, seu chefe lhe disse:

João, Aperte aquele parafuso.

Page 25: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

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

Page 26: Gerenciamento de dependências

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

Page 27: Gerenciamento de dependências

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.

Page 28: Gerenciamento de dependências

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.

Page 29: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

João abre a porta, E...

Page 30: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

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

!

Page 31: Gerenciamento de dependências

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.

?

Page 32: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

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

Page 33: Gerenciamento de dependências

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.

Page 34: Gerenciamento de dependências

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.

Page 35: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

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

Page 36: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

João aperta o parafuso, e...

Page 37: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

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

Page 38: Gerenciamento de dependências

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

Page 39: Gerenciamento de dependências

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.

Page 40: Gerenciamento de dependências

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

Page 41: Gerenciamento de dependências

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.

Page 42: Gerenciamento de dependências

2.2 – Entendendo Dependence Injection (DI)

Container

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

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

Page 43: Gerenciamento de dependências

FIM