Programação Orientada a Objetos - Pós Graduação - Aula 7 - Inversão de Controle
1. Programação Orientada a Objetos
Inversão de
Controle
Pós Graduação em Análise e Desenvolvimento de Sistemas
Aplicados à Gestão Empresarial
INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA
TRIÂNGULO MINEIRO – Campus Uberlândia Centro
Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
2. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Separação de
responsabilidades
• Ao pensar no design de uma aplicação, deve-se
pensar no grupo de objetos que trabalham em
conjunto para uma determinada finalidade;
• Ao desenhar pequenas classes que, juntas,
realizam uma tarefa maior, o programador
ganha em simplicidade e modularidade;
• Sistemas fáceis de manter são os que contém
classes que possuem apenas uma
responsabilidade bem definida, já que a
alteração do comportamento é isolada.
3. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Baixo acoplamento e alta
coesão
• O desejável é que mudanças em uma parte do
sistema não impliquem em mudanças em outras
partes;
• A necessidade de atualizar diversos pontos do
código em alterar uma funcionalidade indica
que estes pontos estão ligados ou acoplados de
maneira indesejada;
• Acoplamento é o quanto dois elementos estão
amarrados entre si e quanto as alterações no
comportamento de um afetam o de outro.
4. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Baixo acoplamento e alta
coesão
• Minimizar o acoplamento implica em facilitar a
troca dos componentes, além de ser peça
fundamental para a manutenção do código,
formando um arquitetura de maior qualidade;
• Baixo acoplamento é diferente de Nenhum
acoplamento;
• Deseja-se que a ligação entre dois componentes
seja a menor e mais simples possível;
5. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Baixo acoplamento e alta
coesão
• A razão da existência de todo componente é
exercer algum tipo de função ou
responsabilidade dentro do sistema, por isso
este deve ter alta coesão;
• Alta coesão quer dizer que suas
responsabilidades sejam relacionadas e façam
sentido juntas, que não haja responsabilidades
desconexas dentro de um mesmo componente;
• SRP – uma única razão para mudança.
6. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Baixo acoplamento e alta
coesão
• Um método que verifica permissões de um
usuário logado e monta um relatório possui
mais de uma responsabilidade e requer
refatoração;
• Separar indica criar dois métodos distintos, e até
duas classes distintas, pois duas
responsabilidades estão vinculadas: autenticação
e execução.
7. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Mesmo com o baixo acoplamento, sempre
existirá uma ligação entre duas classes que
precisam trabalhar em conjunto.
8. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• No exemplo anterior, Dao existe para que se
encapsule os detalhes de acesso a dados,
contudo precisa de recursos para realizar seu
trabalho, como conexão com o banco.
9. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• É inviável repetir o código de conexão, e outros
detalhes como externalização de configurações,
pool de conexões, etc.. É óbvio que ProjetoDao
tem responsabilidades demais.
10. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• No último exemplo, não seria possível salvar
dois projetos com a mesma conexão, nem
executar dois métodos Dao em uma única
transação.
• Essa é uma má prática conhecida como sessão
por operação, ou transação por operação;
• Esse exemplo soa
familiar?
11. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Neste exemplo, o Dao acabaria com uma grande
quantidade de métodos, a maioria formado por
uma combinação de outros, ou seja, o Dao
trabalha demais.
12. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• O problema deste exemplo é se o método inicia()
for esquecido de ser invocado, ou seja, o
objetoDao não é um bom cidadão, já que pode
ser instanciado sem que todas as suas
dependências sejam resolvidas.
13. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• E agora?
14. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• O método fecha() quebra o encapsulamento do Dao, já
que se a implementação for trocada por outros tipos de
arquivos, não existiria conexão a ser fechada;
• Deve-se evitar espalhar responsabilidade de gerenciar o
recurso que está sendo manipulado;
• Não existe erro de compilação por não chamar o método
fecha();
• Delegar fechamento de conexão para outras classes é
ruim porque o fechamento é relativamente complexo,
pois deve-se controlar transações e exceções;
• Ainda não é possível salvar um Projeto, atualizar um
Usuário e remover uma História, já que cada Dao abre
sua conexão.
15. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• A solução é tirar do Dao a responsabilidade de abrir e
fechar conexões;
• Sua única responsabilidade será tratar das operações de
manipulação do banco, mas não irá gerenciar conexões.
16. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Receber a conexão em vez de criá-la é um princípio de
injeção de dependências;
• Inverte-se quem está no controle de gerenciar a
dependência;
• O programador faz com que os objetos já recebam suas
dependências inicializados e prontos para uso;
17. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Inversão de Controle vs
Injeção de Dependências
• Injeção de Dependências é um caso específico de
Inversão de Controle;
• Em uma aplicação visual, ao invés de verificar o estado
de um botão de tempos em tempos, uma classe pode
registrar um listener, que será notificado quando o
evento ocorrer, onde o código do tratamento do evento
passa a ser invocado pelo botão, em vez de invocar
métodos para descobrir seu estado.
18. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Diante disso, quem irá gerenciar a conexão?
• Na injeção de dependências, existe um dependente (o
Dao), uma dependência (a conexão), e quem amarra
tudo isso é um provedor (provider).
19. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Inverter o controle e declarar as
dependências para ser injetadas por
alguém é considerado uma boa prática de
design;
• As dependências podem ser injetadas via
construtor, métodos setter, ou diretamente
nos atributos via reflection;
• O mais recomendado é via construtor.
20. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Injeção diretamente no atributo:
• Injeção via setter:
21. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Em CrudDao, foi implementada uma
estratégia manual de injeção de
dependências.
22. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Em ClienteControl, não existe inversão de
controle, pois esta classe sabe onde buscar
suas dependências, pelo ServiceLocator.
23. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Injeção de Dependências
• Contudo, muitos têm utilizado
frameworks que fazem a injeção
automaticamente, como Spring, Google
Guice, Pico Container, e a especificação
CDI do Java EE 6, com o framework Weld
como implementação de referência;
• Na disciplina “Desenvolvimento de
Sistemas”, será usado o CDI com o
framework Weld.
24. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Será aplicada uma inversão de controle
manual no projeto utilizado nas aulas
anteriores;
• Observa-se no código abaixo que está
sendo implementado a má prática
chamada transação
por operação.
25. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Caso o sistema necessite salvar dois
clientes ou dois pedidos em uma mesma
transação, ou ainda assim salvar um
cliente e um pedido na mesma transação,
não será possível;
• Para exemplificar este cenário, será criada
uma classe Log, que será salva juntamente
com Cliente e Pedido.
26. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
27. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Deseja-se que a classe CrudDaoImpl deixe de ter
a responsabilidade de gerenciar as conexões;
• Esta classe simplesmente irá usar as conexões
para efetuar suas operações;
• Contudo, as conexões deverão ser estado nas
classes PedidoDao,ClienteDao e LogDao, pois
estas classes podem efetuar outras operações
com o banco de dados, como uma consulta
complexa via Sql. CrudDaoImpl somente faz
operações de CRUD.
28. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Adiciona-se o método getEntityManager() em
Crudavel
29. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Inverte-se o controle do Dao, exigindo que as
classes recebam a EntityManager ao serem
instanciadas.
30. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• O mesmo é feito com LogDao. Os métodos
getConsultaSql() e getParametrosMapa()
receberão implementação quando for criado algo
para consultar o log.
31. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Observa-se que CrudDaoImpl apenas usa o
EntityManager, não gerencia mais a conexão
32. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Obviamente as classes do pacote service
começam a gerar erros, pois o Dao está exigindo
a EntityManager para efetuar seu trabalho;
• O gerenciamento das conexões não pode ser
feito pelas classes de service, pois estas classes
somente servem para expor o model para
clientes remotos. Deverá ser criada outra
chamada chamada repository.
33. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Será criada uma exception para identificar erros
de sistema.
34. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Será criada uma exception para identificar erros
de sistema.
35. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• O repositório de Cliente pode ser feito dessa
forma:
36. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
37. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Ao executar o sistema, naturalmente um erro
será gerado porque a tabela TB_LOG não existe,
contudo como foi feito um rollback, o cliente
também não foi inserido.
38. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Refactoring com IoC na
camada Dao do Ecommerce
• Ao editar o arquivo persistence.xml para
permitir dropar e criar tabelas, a tabela TB_LOG
irá existir, logo o insert será feito em ambas as
tabelas.
39. Prof Carlos Eduardo Dantas – carloseduardodantas@iftm.edu.br
Referências
• SILVEIRA, Paulo, Guilherme. LOPES, Sérgio.
MOREIRA, Guilherme, SEPPAT, Nico. KUNG,
Fábio. Introdução à Arquitetura e Design de
Software. Editora Campus, 2012;
• ANICHE, Maurício. Orientação a objetos e
SOLID para Ninjas. Casa do Código, 2015;
• GUERRA, Eduardo. Design Patterns com Java.
Casa do Código, 2014;
• “LARMAN, Craig – Utilizando UML e Padrões
3ª Edição. Bookman, 2007”.