Gerenciamento de Dependências por David Paulo Magalhães Araújo
Aplicativos referidos na apresentação ●
JDK 6
●
Spring 2.5
●
Eclipse
Aplicativos referidos na apresentação ●
JDK 6
●
Spring 2.5
●
Eclipse
ontes
Spring Recipes, A Problem-Solution Approach Approach http:!!!"springsource"org #oogle e Diversos sites da $nternet
!ndice Active %oo&up #er'ncia de depend'ncias #er'ncia Aut(noma #er'ncia por containers )* + ue um .ontainer/ 0* 12emplo: #erador de Relat3rios 4* .omple2idade de pesuisa
Passive %oo&up
1ntendendo $+. 5$nversion o6 .ontrol* 1ntendendo Dependence $njection 5D$*
" # Gerência de dependências 7ma aplica8ão composta de componentes" .ada componente desses precisa ser reutili9vel e ser o m;nimo acoplado poss;vel com outras classes ue não sejam do componente, para ue não se torne dependente destas" Apesar disso, a maioria dos componentes de uma aplica8ão precisa do servi8o de outros componentes" + Desenvolvedor deve 6a9'-los interagirem, mas sem comprometer-lhes a reusabilidade e evitar ue 6iuem com o c3digo acoplado"
"." # Gerência A$t%noma ) - + .omponente =A> precisa do componente =?>" 0 - + .omponente =A> importa o componente =?> 5se necessrio*" 4 - + .omponente =A> declara uma varivel do tipo =?>" @ - + .omponente =A> instancia o componente =?> e o guarda na varivel" - + .omponente =A> pode agora usar o componente =?>"
1sse mtodo, apesar de ter a vantagem de ser simples, possui muitas desvantagens" agora dependente da =implementa8ão> do componente =?>, em ve9 de ser dependente somente de sua inter6ace" Se ualuer altera8ão 6or 6eita no componente =?>, o c3digo do componente =A> pode se tornar invlido" .omo conseu'ncia, o componente =A> não pode ser reutili9ado"
"." # Gerência A$t%noma .omponente =A>
.omponente =?>
.omponente =D>
.omponente =.>
os componentes são muito acoplados, se comportando como um bloco indivis;vel, onde uma altera8ão em ualuer classe, leva a necessidade de alterar as classes ue dependem dela"
".2 # Gerência por containers A #er'ncia aut(noma não satis6a9 o desejo da reusabilidade e do desacoplamento, Alm de dar uma responsabilidade a mais para todos os componentes: o de gerenciar suas pr3prias depend'ncias" A abordagem por container procura evitar esses erros atravs de uma ger'ncia centrali9ada"
".2." # & '$e ( $m container) A Palavra container em si contm muitos signi6icados no universo de B$, mas uando se 6ala em ger'ncia de depend'ncias, 7m container uma classe ue possui re6er'ncia para todos os componentes da aplica8ão e possui mtodos ue os disponibili9am" .om a ajuda dele, os componentes da aplica8ão não precisam mais instanciar as classes ue necessitam, podendo somente, pedir uma re6er'ncia para o container" Assim, os componentes podem dei2ar de 6icar dependentes da implementa8ão de outro componente, e passar a ser dependente somente das inter6aces"
".2 # Gerência por containers $nter6ace =)>
.omponente =A>
$nter6ace =0>
.omponente =?>
.omponente =.>
.ontainer
$nter6ace =4>
.omponente =D>
".2.2 # E*emplo+ Gerador de ,elat-rios ●
Suponhamos ue vamos desenvolver um sistema cuja 6un8ão gerar di6erentes tipos de relat3rios, ou em CBM% ou em PD" De acordo com o princ;pio da orienta8ão E objetos de separar inter6ace de implementa8ão, Famos criar uma inter6ace para gerar relat3rios" Famos assumir ue o argumento GtableG o relat3rio, um arraH String" pacage com"a9ul"springtestI)J p$/lic interface Report#eneratorK p$/lic void generate5StringLL table*J N
".2.2 # E*emplo+ Gerador de ,elat-rios ●
Agora, criaremos as classes GCtmlReport#eneratorG e GPd6Report#eneratorG, para implementar a inter6ace GReport#eneratorG e gerar relat3rios em CBM% e em PD, respectivamente" pacage com"a9ul"springtestI)J p$/lic class CtmlReport#enerator implements Report#eneratorK p$/lic void generate5StringLL table*K
SHstem"out"println5=#erando relat3rio em CBM%>*J N N
pacage com"a9ul"springtestI)J p$/lic class Pd6Report#enerator implements Report#eneratorK p$/lic void generate5StringLL table*K
SHstem"out"println5=#erando relat3rio em PD>*J N
".2.2 # E*emplo+ Gerador de ,elat-rios .om as classes implementadoras da inter6ace GReport#eneratorG prontas, voc' pode come8ar a implementar a classe GReportServiceG, ue age como um provedor para gerar di6erentes tipos de relat3rios" *J
p$/lic void generateAnnualReport5int Hear*K StringLL statistics O n$llJ coletar estat;sticas para o ano 5Hear* report#enerator"generate5statistics*J N N
".2.2 # E*emplo+ Gerador de ,elat-rios $mplementa8ão da classe G.ontainerG pacage com"a9ul"springtestI)J import java"util"QJ p$/lic class .ontainerK p$/lic static .ontainer instanceJ $nstncia global da classe, para 6acilitar locali9a8ão" private MapString, +bjectT componentsJ 7m mapa para guardar os componentes" p$/lic .ontainer5*K components O ne0 CashMapString, +bjectT5*J instance O t1isJ components"put5=report#enerator>, ne0 Pd6Report#enerator5**J components"put5=reportService>, ne0 ReportService5**J N
p$/lic +bject get.omponent5String id*K ret$rn components"get5id*J N N
".2.2 # E*emplo+ Gerador de ,elat-rios tml,eportGenerator ,eportService
U generate5StringLL*:void
U #enerateAnnualReport5int*:void
$nter6aceTT ReportGenerator
4ontainer U get.omponent5String*:void
U
generate5StringLL*:void
3df,eportGenerator U generate5StringLL*:void
".2. # 4omple*idade de pes'$isa .om uma ger'ncia por containers, os componentes dependem uns dos outros atravs de suas inter6aces em ve9 de suas implementa8Ves" Porm, agora eles se tornaram dependentes do container, visto ue 6a9em pesuisa por depend'ncias usando comple2os mtodos proprietrios" $sso impede esses componentes de 6uncionarem sob a ger'ncia de outro container, ue possua uma implementa8ão di6erente"
".2. # 4omple*idade de pes'$isa 7ma Solu8ão para esse problema seria implementar o design pattern do Wava 11 chamado Service Locator, para retirar as depend'ncias dos componentes para o container, impedindo ue os componentes 6iuem dependentes de c3digo proprietrio" 7m e2emplo de Service%ocator a classe abai2o: pacage com"a9ul"springtestI)J p$/lic class Service%ocatorK private static .ontainer container O ne0 .ontainer5*J $nstancia novo container p$/lic static Report#enerator getReport#enerator5*K ret$rn 5Report#enerator* container"get.omponent5=report#enerator>*J N N
".2. # 4omple*idade de pes'$isa Assim, a classe ReportService pode usar a .lasse Service%ocator dessa 6orma: pacage com"a9ul"springtestI)J p$/lic class ReportServiceK private Report#enerator report#enerator O Service%ocator"getReport#enerator5*J p$/lic void generateAnnualReport5int Hear*K StringLL statistics O n$llJ coletar estat;sticas para o ano 5Hear* report#enerator"generate5statistics*J N N
A .lasse ReportService passaria a ser dependente da classe Service%ocator" Boda ve9 ue o container mudar, basta o Service%ocator tambm mudar, e não todos os componentes da aplica8ão"
".2. # 4omple*idade de pes'$isa 4om a classe Serviceocator+ $" Bodos os mtodos de pesuisa são static" Assim sendo, não precisarem de uma instncia para serem invocados" $$" 7ma .lasse pode ser locali9ada por outra classe, bastando a primeira ser vis;vel para a segunda, e portanto, não precisa de uma instncia static de si" $$$" A .lasse .ontainer não precisa mais de uma instncia static de si"
".2. # 4omple*idade de pes'$isa Serviceocator
tml,eportGenerator
U getReport#enerator5*:Report#enerator
U generate5StringLL*:void
$nter6aceTT ReportGenerator
,eportService U #enerateAnnualReport5int*:void
U
generate5StringLL*:void
4ontainer
3df,eportGenerator
U get.omponent5String*:void
U generate5StringLL*:void
2." # Entendendo 7o4 87nversion of 4ontrol9 Bodos os mtodos de pesuisa discutidos anteriormente nessa apresenta8ão se baseiam na pesuisa ativa, ou Active %oo&up" 1sse maneira de pesuisar depend'ncias se baseia em paradigmas herdados da programa8ão procedural e estruturada"
2.2 # Entendendo Dependence 7n:ection 8D79 $nje8ão de depend'ncia ou Dependence $njection5D$* um design pattern ue implementa o paradigma $o." 1nuanto $o. um princ;pio abstrato, D$ o reali9a"
2.2 # Entendendo Dependence 7n:ection 8D79 1m uma empresa trabalha Woão, cujo emprego apertar para6usos" Sauda8VesX 1u sou Woão, + apertador de para6usos" Apertar para6usos comigo mesmoX
2.2 # Entendendo Dependence 7n:ection 8D79 .erto dia, seu che6e lhe disse:
Woão, Aperte auele para6uso"
2.2 # Entendendo Dependence 7n:ection 8D79 Mas joão percebeu ue 6altava um peueno detalhe para 6a9er seu trabalho""""
2.2 # Entendendo Dependence 7n:ection 8D79 Woão precisava de uma chave de 6enda para 6a9er seu trabalho, e 6oi correndo ao almo2ari6ado buscar uma, mas""" A Porta do almo2ari6ado est 6echada"""
2.2 # Entendendo Dependence 7n:ection 8D79 Para conseguir a chave, Woão vai ao encontro do atendente, ue possui as chaves da empresa" + Atendente lhe entrega as chaves"
2.2 # Entendendo Dependence 7n:ection 8D79 .om a chave em mãos, Woão vai agora para o Almo2ari6ado, onde ele poder 6inalmente obter Sua 6erramenta de trabalho"
2.2 # Entendendo Dependence 7n:ection 8D79 Woão abre a porta, 1"""
2.2 # Entendendo Dependence 7n:ection 8D79 F' vrias cai2as""" 1 agora/ 1m ual das cai2as A 6erramenta se locali9a/
X
2.2 # Entendendo Dependence 7n:ection 8D79 Percebendo ue precisava de ajuda, Woão vai 6alar com o 9elador do almo2ari6ado, Perguntando a locali9a8ão do instrumento" + Yelador responde ue est na menor cai2a da primeira 6ileira"
/
2.2 # Entendendo Dependence 7n:ection 8D79 .om a in6orma8ão em mente, Woão retorna ao almo2ari6ado e abre a porta"
2.2 # Entendendo Dependence 7n:ection 8D79
2.2 # Entendendo Dependence 7n:ection 8D79 Acabou/ Ainda não""" tudo o ue 6oi 6eito at Agora era somente para obter o instrumento Para ue joão pudesse desempenhar seu papel" 1le agora deve 6a9er a parte mais importante"
2.2 # Entendendo Dependence 7n:ection 8D79 .om a 6erramenta em mãos, Woão pode inalmente apertar o para6uso"
2.2 # Entendendo Dependence 7n:ection 8D79 Woão aperta o para6uso, e"""
2.2 # Entendendo Dependence 7n:ection 8D79 inalmente, + Brabalho 6oi conclu;doX Woão .onseguiu completar sua tare6a, apesar de todos +s imprevistosX
2.2 # Entendendo Dependence 7n:ection 8D79 Mas todo esse trabalho muito comple2o para Woão so9inho" Woão, o apertador de para6usos, Agora tambm Woão, o buscador de erramentas, Woão, + porteiro do almo2ari6ado 1tc"""
2.2 # Entendendo Dependence 7n:ection 8D79 Perceba ue Woão, + Apertador de para6usos, 7ma classe ue resolve todos os seus problemas So9inha" $sso a dei2a muito comple2a, e a desvia De seu real prop3sito: Apertar para6usos" A empresa poderia contratar uma pessoa ue 6i9esse o trabalho de buscar as 6erramentas, esperando ue algum lhe pe8a" $sso 6aria essa pessoa ser semelhante a um Service %ocator" Porm, essa abordagem tambm não seria interessante, pois, se por acaso, essa pessoa 6osse substitu;da, seria necessrio in6ormar todos os 6uncionrios da empresa sobre a substitui8ão"
2.2 # Entendendo Dependence 7n:ection 8D79 1m ve9 disso, a empresa poderia contratar uma pessoa ue, com antecipa8ão, j soubesse o ue .ada 6uncionrio precisa, e assim, buscasse as 6erramentas e lhes entregasse antes mesmo ue eles pedissem" Assim, nenhum 6uncionrio precisaria se preocupar em uem entrega as 6erramentas, pois eles saberiam ue algum se comprometeu em entregar-lhes o ue precisavam" 1ssa pessoa se assemelharia, então, a um container de inje8ão de depend'ncias 5D$ container*"
2.2 # Entendendo Dependence 7n:ection 8D79 1m um container de inje8ão de depend'ncia, os componentes da aplica8ão não precisam mais possuir uma re6er'ncia direta ou indireta ao container" Assim, torna desnecessrio o uso de um Service %ocator, pois o container ue gerenciar as depend'ncias e ele ue determinar ue depend'ncias cada componente precisa"
2.2 # Entendendo Dependence 7n:ection 8D79 $nter6ace =)>
.omponente =A>
$nter6ace =0>
.omponente =?>
.omponente =.>
.ontainer
$nter6ace =4>
.omponente =D>