Вы находитесь на странице: 1из 8

Construcao de Dependencias entre Objetos

Prof. Eduardo Bezerra


23 de outubro de 2013

Sum
ario
1 Introdu
c
ao

2 Princpio de Holywood

3 Padr
ao Inje
c
ao de Depend
encias

4 Inje
c
ao de Depend
encias aplicado a Reposit
orios e DAOs

5 Conclus
oes

6 Notas Bibliogr
aficas

Padr
oes de Software

Prof. Eduardo Bezerra

Introdu
c
ao

Em um sistema de software orientado a objetos, e comum a tempo de execucao


haver um emaranhado de objetos que colaboram entre si para fornecer as funcionalidades definidas nos requisitos funcionais desse sistema. Essa colaboracao
somente e possvel quando existem refer
encias entre objetos, de tal modo
que um objeto possa enviar mensagens para outro com o proposito de solicitar a realizac
ao de algum servico. Outra forma de pensar nessas referencias
e como depend
encias entre objetos do sistema: um objeto depende de outros para realizar os servicos que estao sob sua atribuicao. Obviamente, para
que possa haver colaborac
ao entre os objetos do sistema, e necessarios que essas
dependencias tenham sido corretamente configuradas. Em uma aplicacao corretamente arquitetada, e comum o uso de frameworks para fornecer servicos mais
gerais. Mesmo nesse caso, dependencias devem ser construdas entre o codigo
implementado pelos desenvolvedores da aplicacao e o codigo previamente existente do framework. Neste Captulo, descrevemos tecnicas para construcao de
dependencias entre objetos. Comecamos por apresentar na Secao 2 o princpio
de Princpio de Holywood, comumente usado na implementacao de frameworks. Na Sec
ao 3, descrevemos o padrao Inje
c
ao de Depend
encias, uma
aplicac
ao particular do Princ
pio de Holywood para permitir a construcao
de dependencias entre objetos dependentes de um servico e objetos que fornecem esse servico. Na Sec
ao 4, descrevemos de que forma o padrao Injec

ao
de Depend
encias pode ser utilizado para configurar um tipo particular de
dependencia, aquela existente entre repositorios e objetos de acesso a dados.
Essa discuss
ao e feita no contexto do framework Spring. Finalmente a Secao 5
apresenta as conclus
oes relativas ao conte
udo apresentado neste Captulo.

Princpio de Holywood

Em arquitetura de sistemas de software, ha um conceito importante denominado Princpio de Holywood, que esta associado `a frase N
ao nos chame,
nos o chamamos (traduc
ao da expressao original Do not call us, we will call
you). A origem dessa frase est
a associada `a atividade dos agentes de atores em
Holywood. Ao serem procurados por atores desconhecidos `a procura de uma
oportunidade para atuar, esses agentes fornecem a resposta padrao para que
esses atores n
ao entrem em contato e que, em vez disso, eles (os agentes) e que
irao entrar em contato no caso de surgir alguma oportunidade.
No contexto de arquitetura de software, o Princpio de Holywood quando
da construc
ao de um elemento de codigo (uma classe ou um componente) que
deve ser integrado ao c
odigo de um framework. Nesse contexto, tipicamente o
desenvolvedor implemente uma ou mais interfaces (fornecidas pelo proprio framework). A tempo de execuc
ao da aplicacao, o framework pode entao invocar
(chamar, call ) o c
odigo definido pelo programador. Repare que o framework invoca c
odigo implementado pelo programador por meio de acoplamento abstrato
e de polimorfismo. Em outras palavras, o framework faz as vezes do agente de
atores, que chama (telefona) os atores no momento em que achar adequado.

Padr
oes de Software

Prof. Eduardo Bezerra

Um nome alternativo(e mais antigo) para o Princ


pio de Holywood e
o Princpio da Invers
ao de Controle (do ingles Inversion of Control - IoC).
Para entender esse nome alternativo, convido o leitor a comparar dois cenarios
possveis de desenvolvimento de uma aplicacao por um programador. No primeiro, o programador invoca funcoes publicadas na API de alguma biblioteca
de software de uso geral (e.g., de autitoria, de acesso a um SGBD, etc). Nesse
caso, o c
odigo de uso geral est
a empacotado em uma biblioteca, e e o codigo
da aplicac
ao que as func
oes dessa API. Agora considere um segundo cenario
em que o programador da aplicacao usa um framework, cujo funcionamento
e baseado no Princpio de Holywood. Nesse segundo cenario, e o codigo do
framework que invoca o c
odigo da aplicacao em alguma momento considerado
adequado pelo pr
oprio framework. Repare a inversao do controle que ocorre
quando comparamos os dois cenarios de desenvolvimento: no cenario em que
um framework e usado, este controla as chamadas ao codigo da aplicacao, enquanto que no outro cen
ario, e a aplicacao quem controla em que momento as
funcoes da API s
ao chamadas.
O Princ
pio de Holywood e entao uma estrategia normalmente usadas por frameworks para permitir que estes possam controlar a invocacao de
codigo definido pelo desenvolvedor da aplicacao. O principiante no estudo desse
princcio (e no estudo de frameworks por consequencia) pode acha-lo bastante
estranho. Isso porque esse princpio permite que um componente de software
generico (normalmente representado pelo codigo de um framework) possa invocar codigo implementado pelo desenvolvedor de uma aplicacao, codigo esse que
possivelmente nem sequer existia quando da implementacao do framework.

Padr
ao Inje
c
ao de Depend
encias

O padr
ao Injec

ao de Depend
encias (do original Dependency
Injection) e uma aplicac
ao particular do princpio de Holywood. O
contexto de uso desse padr
ao e aquele no qual um objeto que depende de
diversos outros deve ser construdo (i.e., instanciado). Dizemos que um objeto
X depende de outro Y quando, para fornecer corretamente seus servicos, X
precisar delegar parte desse servico para Y. Chamamos X de cliente, e Y de
fornecedor do servico. Em geral, um objeto pode depender de varios outros
objetos fornecedores.
Para enteder a aplicac
ao do padrao Injec

ao de Depend
encias, vamos
primeiramente considerar uma situacao em que esse padrao nao e usado. Para
isso, considere a Listagem 1. Diz-se que um elemento A (que pode ser uma
classe ou um componente) possui uma dependencia para outro B se A usa os
servicos fornecidos por B. Uma maneira de definir a dependencia e fazer com
que A instancie B. No trecho de codigo esquematico apresentado, a classe A
(cliente) cria explicitamente uma instancia de B (fornecedor).
Listagem 1: 1o cen
ario: classe A (cliente) cria explicitamente uma instancia de
B (fornecedor).
1

class A {

Padr
oes de Software

Prof. Eduardo Bezerra

B b;
A() {
this.b = new B();
}

2
3
4
5
6

fazerAlgo() {
this.b.fazerAlgo();
}

7
8
9
10

Outra maneira de definir a dependencia entre A e B e atribuir a um terceiro


componente a responsabilidade de instanciar B e passar essa referencia para A
usar. Com o uso do padr
ao Injec

ao de Depend
encias, em vez de o objeto cliente (i.e., dependente) instanciar cada objeto fornecedor de que precisa,
ele simplesmente recebe as referencias para seus fornecedores. A instanciacao
desses objetos fornecedores e realizada por outro componente. Os objetos fornecedores s
ao passados, por exemplo, como parametros do construtor do objeto
dependente, ou como par
ametros de metodos modificadores (setXXX). Veja a
Listagem 2. Nesse trecho de c
odigo, podemos perceber que a instanciacao de
B fica a cargo de outro elemento que nao e A. Vamos chamar esse elemento
de injetor de depend
encias, posto que seu papel e instanciar B e passar a
referencia durante a construc
ao (instanciacao) de A. Repare que na Listagem
2, o elemento B pode ser uma classe concreta, uma classe abstrata ou mesmo
uma interface.
Listagem 2: 2o cen
ario: a instanciacao de B fica a cargo de outro elemento que
nao e A.
1
2

class A {
B b;

A(B b) {
this.b = b;
}

4
5
6
7

public void fazerAlgo() {


this.b.fazerAlgo();
}

8
9
10
11

No 2o cen
ario, houve uma invers
ao do controle de instancia
c
ao das
depend
encias. Em particular, a instanciacao de B passa a ser feita externamente a A. O elemento A e agora mais flexvel ja que nao depende de uma im possvel passar como parametro uma instancia
plementac
ao especfica de B. E
de alguma classe que estende (ou implemente) B.
Pela discuss
ao acima, podemos concluir que Injec

ao de Depend
encias
e padr
ao de projeto que declara o seguinte:
Uma entidade n
ao deve obter entidades externas das quais ela
depende para realizar sua tarefa. Em vez disso, deve esperar
que outra entidade forne
ca essas depend
encias.

Padr
oes de Software

Prof. Eduardo Bezerra

O uso apropriado desse padrao resulta em sistemas fracamente acoplados,


em que seus componentes s
ao intercambiaveis: contanto que os contratos entre
cliente e fornecedor sejas mantidos, o injetor de dependencias pode instanciar
qualquer classe que implemente os servicos esperados pelo cliente e passar (injetar) essa inst
ancia no cliente, sem que seja necessaria qualquer alteracao neste
u
ltimo.
H
a tres alternativas possveis para injetar uma dependencia:
Por meio de um construtor definido no objeto cliente (construction injection)
Por um metodo modificador definido no objeto cliente (setter injection)
Por meio de uma interface a partir da qual o objeto cliente obtem os
servicos (interface injection)

Inje
c
ao de Depend
encias aplicado a Reposit
orios
e DAOs

Uma aplicac
ao do padr
ao Injecao de Dependencia e no contexto da amarracao
entre reposit
orio e objetos de acesso a dados. Nessa Secao, apresentamos um
exemplo dessa amarrac
ao. Considere as classes DisciplinaRepo e DisciplinaDaoJpa do SCA.
Sem o uso do padr
ao injecao de dependencia, teramos possivelmente o
trecho de c
odigo similar ao da Listagem 3 para realizar a amarracao entre
objetos daquelas duas classes. Isso e ilustrado na Listagem 3.
Listagem 3: Amarrac
ao manual entre o cliente (DisciplinaRepo) e o fornecedor (DisciplinaDAOJpa).
1
2
3

public class DisciplinaRepo {


DisciplinaDao dao = new DisciplinaDAOJpa();
...

A injec
ao por metodo modificador pressupoe que o cliente forneca um
metodo p
ublico que possa ser invocado pelo conteiner de IoC para que
este injete a referencia no momento adequado. Na listagem 7, repare a
existencia do metodo setDisciplinaDao. Com uma definicao adequada
realizada no arquivo de configuracao do Spring, toda vez que um objeto
DisciplinaRepositorio e criado na aplicacao, o conteiner automaticamente instancia um objeto cuja classe implemente a interface DisciplinaDao
e invoca o metodo setDisciplinaDao para passar essa referencia ao objeto
DisciplinaRepositorio recem-criado.
Listagem 4: Injec
ao por metodo (setter injection).
1
2

public class DisciplinaRepositorio {


DisciplinaDao dao;

3
4

public void setDisciplinaDao(DisciplinaDao dao) {

Padr
oes de Software

5
6
7

Prof. Eduardo Bezerra

this.dao = dao;
}
...

A injec
ao por construtor pressupoe que o cliente forneca um construtor que
receba como par
ametro um objeto que corresponda `a referencia a ser injetada.
Um exemplo desse tipo de injecao e apresentado na listagem 5, na qual podemos reparar a existencia de um construtor. Mais um vez, com uma definicao
adequada realizada no arquivo de configuracao do Spring, toda vez que um objeto DisciplinaRepositorio e criado na aplicacao, o conteiner automaticamente instancia um objeto cuja classe implemente a interface DisciplinaDao
e passa esse objeto por meio do construtor.
Listagem 5: Injec
ao por construtor (constructor injection).
1
2

public class DisciplinaRepositorio {


DisciplinaDao dao;

3
4
5
6
7

public DisciplinaRepositorio(DisciplinaDao dao) {


this.dao = dao;
}
...

Em ambos os exemplos apresentados na Listagem 7 e na Listagem 5, note


que DisciplinaDAO e uma interface, que pode ser implementada por mais
de uma classe. Dessa forma, o cliente (DisciplinaRepositorio) nao tem
conhecimento da verdadeira classe do fornecedor, e isso e bom se pensarmos
pela perpectiva do princpio do acoplamento.
Listagem 6: Trecho do arquivo de contexto do framework Spring para configurac
ao de DI sem anotac
oes.
1
2
3
4

<?xml version="1.0" encoding="UTF-8"?>


<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans
-2.5.xsd">

5
6
7

8
9

<!-- DAOS -->


<bean id="disciplinaDao" class="br.cefetrj.sca.infra.
DisciplinaDaoJpa" />
<bean id="turmaDao" class="br.cefetrj.sca.infra.TurmaDaoJpa" />
<bean id="professorDao" class="br.cefetrj.sca.infra.
ProfessorDaoJpa" />

10
11
12

13
14
15
16
17

<!-- REPOSIT
ORIOS -->
<bean id="disciplinaRepositorio" class="br.cefetrj.sca.dominio.
DisciplinaRepositorio">
<property name="dao">
<ref local="disciplinaDao" />
</property>
</bean>
<bean id="turmaRepositorio" class="br.cefetrj.sca.dominio.
TurmaRepositorio">

Padr
oes de Software

Prof. Eduardo Bezerra

<property name="dao">
<ref local="turmaDao" />
</property>
</bean>
<bean id="professorRepositorio" class="br.cefetrj.sca.dominio.
ProfessorRepositorio">
<property name="dao">
<ref local="professorDao" />
</property>
</bean>

18
19
20
21
22

23
24
25
26
27
28

</beans>

Uma forma alternativa e mais adequada de configurar a injecao de dependencias no Spring e por meio do uso de anotacoes. A anotacao relevante a
usar nesse caso e denominada Autowired. Veja a Listagem 7, que apresenta
um exemplo de uso dessa anotac
ao. Nesse exemplo, um repositorio deve ser injetado na classe de servico FornecerGradeService. Para isso, o atributo correspondente a esse reposit
orio e anotado com Autowired. Nessa alternativa, o
conteiner de IoC instanciar o repositorio e iniciar o atributo professorRepo.
Listagem 7: Exemplo de uso da anotacao @Autowired
1

public class FornecerGradeService {

@Autowired
private ProfessorRepo professorRepo;

3
4
5

public Professor validarProfessor(String matriculaProfessor) {


return professorRepo.obterProfessor(matriculaProfessor);
}

6
7
8
9

Na alternativa de injec
ao com uso da anotacao Autowired, as definicoes
no arquivo de configurac
ao s
ao mais simples. A Listagem 8 apresenta um trecho
de um arquivo de configurac
ao que usa essa alternativa. Compare com o trecho
do arquivo apresentado na Listagem 6.
Listagem 8: Trecho do arquivo de contexto do framework Spring para configurac
ao de DI com anotac
oes.
1
2

3
4
5
6

<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:
context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context
-3.0.xsd">

7
8

<context:annotation-config />

9
10

<bean id="FornecerGradeServiceBean" class="br.cefetrj.sca.


service.FornecerGradeService" />

Padr
oes de Software

11

12

Prof. Eduardo Bezerra

<bean id="ProfessorRepoBean" class="br.cefetrj.sca.dominio.


ProfessorRepo" />
<bean id="ProfessorDaoBean" class="br.cefetrj.sca.infra.
ProfessorDaoJpa" />

13
14

</beans>

Conclus
oes

o de Depend
Com o uso do padr
ao Injec
a
encias, uma referencia a um
objeto fornecedor pode ser passada para um objeto cliente. As duas
motivac
oes principais para usar esse mecanismo sao:
Aumentar a reusabilidade dos componentes.
Aumentar a testabilidade dos componentes
Uma vantagem do uso do padrao Injec

ao de Depend
encias e que ele
permite desacoplar componentes de uma solucao. Entrentato, esse padrao nao
e para ser usada em todas as situacoes de desenvolvimento. Isso porque seu
uso aumenta a complexidade da implementacao resultante, devido a indirecoes
adicionais. Avalie cuidadosamente a efetiva necessidade de adicionar flexibilidade ao projeto de software. Se essa flexibilidade for realmente necessaria, isso
conta a favor do uso da aplicac
ao do padrao Injec

ao de Depend
encia.

Notas Bibliogr
aficas

Ha diversos arcaboucos para IoC. Tres deles sao o Spring IoC (www.
springsource.org/), o Pico Container (http://picocontainer.
org/) e o Castle (http://www.castleproject.org/).
Martin Fowler ajudou a popularizar o conceito de Injecao de Dependencias
por meio do artigo intitulado Inversion of Control Containers and
the Dependency Injection pattern. Esse artigo pode ser encontrado na Internet no endereco http://martinfowler.com/articles/
injection.html.

Вам также может понравиться