Padrões Arquiteturais para o Acesso a Banco de Dados

44
Padrões Arquiteturais para o Acesso a Banco de Dados Instituto de Matemática e Estatística Universidade de São Paulo Kelly Rosa Braghetto [email protected] Departamento de Ciência da Computação

Transcript of Padrões Arquiteturais para o Acesso a Banco de Dados

Padrões Arquiteturais para o Acesso a Banco de Dados

Instituto de Matemática e EstatísticaUniversidade de São Paulo

Kelly Rosa [email protected]

Departamento de Ciência da Computação

2

Primórdios das Arquiteturasem Camadas

● Anos 90 – primeiros sistemas “em camadas”– Apenas 2 camadas: cliente – servidor– Cliente = interface com o usuário – Servidor = BD relacional

● Ferramentas para o desenvolvimento dos clientes: Visual Basic, PowerBuilder, Delphi– Facilitavam a construção de aplicações de manipulação

intensiva de dados– Permitiam que controles fossem arrastados para uma área

de desenho da interface e que depois fossem conectados a elementos do BD

3

Problema da Arquitetura Cliente-Servidor

● Onde embutir a lógica do domínio?

– Regras de negócio, validações, cálculos, etc.● Geralmente, ficavam no código do cliente

– Lógica era embutida nas telas da interface– Precisava ser replicada em diferentes telas →

manutenção difícil

4

Problema da Arquitetura Cliente-Servidor

● Alternativa: embutir lógica do negócio no servidor → no BD, por meio de stored procedures

● Essa estratégia não é muito bem aceita devido as características das linguagens para stored procedures

– São mais pobres que linguagens de programação convencionais

– Não são padronizadas; são específicas para um SGBD e impedem que o BD possa ser “portado” a um baixo custo

5

Solução: Arquitetura em 3 Camadas

● Contexto de criação: disseminação das linguagens de programação orientadas a objetos e o crescimento da Web

● Componentes da arquitetura em 3 camadas:

– Camada de apresentação: para as interfaces com o usuário

– Camada de domínio: para a lógica do negócio

– Camada de dados: comunicação com os bancos de dados

6

Camada de Apresentação

● Trata da interação entre o usuário e o software

● Principais responsabilidades:

– Mostrar informações– Interpretar comandos do usuário e disparar as ações

correspondentes nas outras duas camadas ● A interação com os usuários pode ser por meio de diferentes tipos

de interface:

– Linha de comando, interface gráfica, interface HTML

– Uma mesma aplicação pode ter mais de uma interface com usuário

● As requisições vêm na forma de cliques de mouses, teclas digitadas, requisições HTTP

7

Camada de Domínio

● Faz o trabalho que é específico para o domínio de aplicação sendo tratado:

– cálculos baseados em dados de entrada ou dados armazenados

– validação de dados que vêm da camada de apresentação

– escolha da lógica e de fontes de dados em função dos comandos recebidos via camada de apresentação

– processamento e formatação dos dados recebidos da camada de fontes de dados antes de repassá-los à camada de apresentação

8

Camada de Dados

● Um dos principais papéis da camada de dados é estabelecer a comunicação entre o sistema e os BDs

● Existem diferentes padrões arquiteturais no que se refere à forma como a lógica do domínio “conversa” com os BDs

– Padrões: são soluções comuns para problemas recorrentes

● A escolha de uma arquitetura para a comunicação com o BD é uma etapa crítica no projeto de um sistema, já que é algo muito complicado de se refatorar depois

9

Padrões Arquiteturais para a Camada de Dados

● Recomendado: separar código em SQL do código da lógica do negócio, colocando-os em classes diferentes

– Vantagem dessa separação: código SQL concentrado em um só lugar evita replicação, facilita a manutenção, etc.

● Organização das classes pode se basear na estrutura do BD

– Ex.: uma classe por tabela → gateway para a tabela

10

Gateway

● É um objeto que encapsula o acesso a um recurso ou sistema externo

11

Tipos de Gateways para Acesso ao BD

● Gateway de linha de dados (row data gateway) – um objeto que atua como um gateway para uma única tupla em uma fonte de dados

– Existe uma instância por tupla– Essa abordagem combina bem com

orientação a objetos (cada tupla pode corresponder a um objeto)

12

Tipos de Gateways para Acesso ao BD

● Gateway de tabela de dados (table data gateway) – um objeto que atua como gateway para uma relação (tabela ou visão) do BD

– Uma única instância (do tipo conjunto de registros) manipula todas as tuplas da relação

– Bastante usado para devolver recordsets – uma estrutura de dados genérica para tabelas e linhas (que imita a estrutura tabular dos BDs relacionais). Ela existe em diversas linguagens de programação e costuma ser usada em diferentes partes de uma aplicação

13

Gateway de Linha de Dados

● Um gateway de linha de dados é um objeto com uma estrutura semelhante à tupla armazenada no BD, mas que pode ser acessada por meio dos mecanismos regulares de uma linguagem de programação

● Todos os detalhes do acesso a fonte de dados ficam escondidos atrás dessa interface

https://martinfowler.com/eaaCatalog/rowDataGateway.html

14

Gateway de Tabela de Dados

● Um gateway de tabela de dados armazena todo o SQL para acessar uma única relação: seleção, inserção, atualização e remoção

– Outros códigos chamam seus métodos para todas as interações com o banco de dados

https://martinfowler.com/eaaCatalog/tableDataGateway.html

15

Um Parênteses sobre Objetos...

Em linguagens de programação OO:● Objeto é uma instância de uma classe

– Objetos têm estados (= valores para seus atributos)– Objetos têm comportamentos (= métodos)

● Modelo de objetos é uma coleção de todas as definições de classes de uma aplicação

● As classes podem representar:– Elementos de interface do usuário– Recursos do sistema– Eventos da aplicação– Abstrações dos conceitos de negócio

16

Objetos de Negócio

● Exemplos de objetos que abstraem conceitos de negócio:– Num sistema de processamento de pedidos:

● Cliente, Pedido e Produto

– Numa aplicação financeira● Cliente, Conta, Crédito, Débito

● Esses objetos modelam o domínio do negócio onde a aplicação específica irá operar → são chamados de Modelo de Domínio

17

Padrão Modelo de Domínio

● Um objeto do modelo de domínio incorpora tanto dados quanto comportamento

● Um modelo de domínio cria uma rede de objetos interconectados, onde cada objeto representa alguma entidade significativa

– Que pode ser tão grande quanto uma corporação ou tão pequeno quanto uma linha em um formulário de pedido

https://martinfowler.com/eaaCatalog/domainModel.html

18

Persistência de Objetos

● Os objetos do modelo de domínio representam os principais estados e comportamentos da aplicação

● Geralmente, esses objetos:

– São compartilhados por vários usuários simultaneamente – São armazenados e recuperados entre as execuções da

aplicação● Persistência de objetos – capacidade desses objetos de

“sobreviverem” além do tempo de execução da aplicação

● Objetos podem ser persistidos em diferentes tipos de fontes de dados (data sources)

– A persistência não é exclusividade dos objetos de domínio (mas é um requisito mais frequente para eles)

19

Mapeamento de Objetos para Bancos de Dados

● Para persistência dos objetos em BDs, é preciso fazer um mapeamento– Mapeamento objeto-relacional (ORM – Object-Relational Mapping)– Mapeamento objeto-documento (ODM – Object-Document Mapping)– Mapeameto objeto-[outros tipos de BDs NoSQL]

● Na implementação do mapeamento, são usados padrões arquiteturais para camada de dados, como os gateways

● Existem ferramentas para o mapeamento automático– Geração automática da estrutura do BD a partir das classes de modelo de

domínio– Geração automática das classes a partir da estrutura do BD– Definição manual de mapeamentos entre BDs e classes já existentes

● Feita por meio de anotações em classes ou arquivos de configuração

20

Padrões de Mapeamentopara Modelo de Domínio

● Em aplicações que usam modelo de domínio, outras opções de mapeamento podem ser mais apropriadas

– Dependendo do modelo de domínio e da estrutura da fonte de dados, os gateways podem ter complexidade demais ou de menos

● Exemplos de padrões de mapeamento usados com modelo de domínio:

– Active Record

– Data Mapper

21

Active Record

● Em aplicações com modelo de domínio simples:

– Estrutura do modelo de domínio se assemelha bastante à estrutura do BD, com uma classe do domínio por tabela do BD

– Objetos do domínio possuem lógica de negócio de complexidade moderada

● Nesse contexto, é viável que cada objeto do domínio se ocupe pelo carregamento e pelo salvamento de dados no BD → esse padrão de arquitetura é chamado de Registro Ativo (Active Record)

22

Active Record

● Um objeto que encapsula uma tupla de uma relação do BD, encapsula o acesso ao BD e adiciona lógica de domínio aos dados

● Um objeto carrega tanto dados quanto comportamento

● A maior parte dos dados é persistente e precisa ser armazenada em um BD

https://martinfowler.com/eaaCatalog/activeRecord.html

23

O Padrão Active Record “na Prática”

● Ruby On Rails (Ruby)

● Django (Python)

● Eloquent/Laravel (PHP)

● ActiveJDBC (Java)

● DBIx::Class (Perl)

● …

24

Mas o Active Record Não É Suficiente Quando...

● A lógica de domínio é mais complicada → modelo de domínio complexo

● Não há um mapeamento 1-para-1 entre as classes do modelo e as tabelas do BD

● Existe a necessidade de se testar a lógica de negócio sem que o acesso ao BD seja feito o tempo todo

→ Nesses casos, nem mesmo a indireção do padrão Gateway é suficiente para lidar com a complexidade

● Alternativa: padrão Data Mapper

25

Data Mapper

● É uma camada de mapeadores que transferem dados entre objetos de domínio e um BD, mantendo-os independentes entre si

● Essa é a arquitetura de mapeamento mais complicada, mas que garante isolamento entre as duas camadas

– Tanto o modelo de domínio quanto o de BD podem variar sem que um afete o outro

https://martinfowler.com/eaaCatalog/dataMapper.html

26

O Padrão Data Mapper “na Prática”

● MyBatis, para Java

● SQLAlchemy, para Python

● Ruby Object Mapper (ROM), para Ruby

● Doctrine, para PHP

● ...

27

Padrão Data Acess Object (DAO)

● Data Acess Object (DAO) – objeto de acesso aos dados● Muito usado em aplicações Java

– Origem: “Core J2EE Patterns”● “O DAO abstrai e encapsula todos os acessos a uma fonte de

dados. Ele gerencia a conexão com a fonte de dados para obter e armazenar dados”

● Provê uma interface abstrata para algum tipo de mecanismo de persistência– SGBDRs, SGBOO, XML, etc.– Provê operações sobre os dados sem expor detalhes de

implementação da fonte de dados● Equivale ao padrão Data Mapper!

28

DAO – Diagrama de Classes (UML)

● BusinessObject – objeto “cliente”, que requisita o acesso aos dados

● DataAcessObject – abstrai a implementação do acesso aos dados para o BusinessObject

● DataSource – representa a implementação de uma fonte de dados

● TransferObject – usado para “carregar” dados (obtidos da fonte de dados) para o BusinessObject

https://www.oracle.com/java/technologies/dataaccessobject.html

29

DAO – Diagrama de Sequência (UML)

https://www.oracle.com/java/technologies/dataaccessobject.html

30

Fábrica de DAOsDiagrama de Classes (UML)

● Quando o tipo de BD usado na persistência não muda de um business object para outro, pode-se usar o padrão de projeto Factory Method (construtor virtual) para criar os diferentes DAOs de que a aplicação precisa, como mostrado no diagrama ao lado

https://en.wikipedia.org/wiki/Factory_method_pattern

https://www.oracle.com/java/technologies/dataaccessobject.html

31

Fábrica Abstrata de DAOs

● Quando o tipo de BD usado na persistência pode mudar de uma implementação para outra, pode-se usar o padrão de projeto Abstract Factory, como mostrado no diagrama do próximo slide

● Este padrão permite a criação de famílias de objetos relacionados por meio de uma única interface e sem que a classe concreta seja especificada

https://en.wikipedia.org/wiki/Abstract_factory_pattern● Nesta estratégia, usa-se um objeto da fábrica DAO abstrata para construir vários

tipos de fábricas DAO concretas, cada fábrica apoiando um tipo diferente de implementação de persistência (ex., em BD relacional, em XML, em BD orientado a objetos)

● Com uma fábrica DAO concreta para um determinado tipo de implementação de persistência, produz-se os DAOs desse tipo de implementação

● Um DAOs pode estender e implementar uma classe de base genérica, que descreve os requisitos do business object a que ele corresponde. Um DAO concreto cuida da conexão com o BD e da manipulação de dados para o seu business object.

32

Fábrica de DAOsDiagrama de Classes (UML)

https://www.oracle.com/java/technologies/dataaccessobject.html

fábrica DAO abstrata

fábrica DAO concretapara um dado tipo de BD

DAO concreto de um dado tipo de business object, para um dado tipo de BD

DAO abstrato para um dado tipo de business object

33

Fábrica de DAO – Diagrama de Sequência

https://www.oracle.com/java/technologies/dataaccessobject.html

34

Exemplo de uma Implementação Simples do DAO em Java

● Ver arquivos do Exemplo 2, disponibilizado com o material da aula– Adaptado do exemplo de DAO dado em:

http://www.caelum.com.br/apostila-java-web/bancos-de-dados-e-jdbc/ ● No exemplo, há apenas uma classe no Modelo de Domínio – a classe

Contato –, que possui como atributos nome, e-mail, endereço e data de nascimento. Os objetos de Contato são persistidos em uma tabela de um BD relacional

– O próximo slide mostra a classe Contato e a tabela correspondente– A implementação do DAO para Contato está dentro do diretório

chamado “BD” no código fonte disponibilizado– Além da classe ContatoDAO, o diretório contém a classe

FabricaDeConexao, que implementa o padrão Fábrica para a criação de conexões com o BD. Ele será mostrado a seguir.

35

Exemplo: Implementando os Padrões em Java

create table contatos (

id serial,

nome VARCHAR(255),

email VARCHAR(255),

endereco VARCHAR(255),

dataNascimento DATE,

primary key (id)

);

public class Contato {

private Long id;

private String nome;

private String email;

private String endereco;

private Calendar dataNascimento;

// métodos get e set para id, nome, email, ...

public String getNome() {

return this.nome; }

public void setNome(String novo) {

this.nome = novo; }

public String getEmail() {

return this.email; }

public void setEmail(String novo) {

this.email = novo; }

...

● Classes do domínio → implementadas como classes em Java que possuem um construtor sem argumentos e métodos get e set para o acesso aos atributos

● Exemplo para entidade Contato:

36

Um Padrão para Controlar as Conexões com o BD: Fábrica de Conexões

● Uma fábrica de conexões se ocupa da criação de conexões com o BD– Sempre que solicitada, ela devolve uma conexão com o BD– Todas as conexões usadas na aplicação devem ser criadas por meio dela

● Vantagens de uma fábrica de conexões:– Oculta os detalhes da criação da conexão (localização do BD,

informações de autenticação, configurações de conexão, etc.)● Facilita a manutenção, por centralizar esses detalhes em um só lugar

do código da aplicação– Pode fazer pooling de conexões (para diminuir o volume de operações de

criação e fechamento de conexões – essas operações consomem tempo)● Ao invés de devolver uma conexão nova a cada nova requisição, a

fábrica pode devolver uma conexão que já estava aberta, mas que não estava mais em uso

● A fábrica gerencia o pool de conexões abertas

37

Um Padrão para Controlar as Conexões com o BD: Fábrica de Conexões

● Exemplo em Java + JDBC:public class FabricaDeConexao {

public Connection obterConexao() {

try {

return DriverManager.getConnection(

"jdbc:postgresql://meuservidor.br:23001/bd_teste",

"usuario","senha");

} catch (SQLException e) {

throw new RuntimeException(e);

}

}

}

● Sempre que uma nova conexão for necessária:Connection con = new FabricaDeConexao().obterConexao();

38

Fechando uma Conexão

public static void main(String[] args) throws SQLException {

Connection con = null;

try {

con = new FabricaDeConexao().obterConexao();

// faz algumas operações sobre a conexão

// que podem gerar exceções (SQLException)

catch(SQLException e) {

System.out.println(e);

} finally {

con.close(); // A conexão será fechada mesmo

} // em caso de exceção no bloco “try”

}

39

Fechando uma Conexão

● É possível se beneficiar da estrutura try-with-resource

http://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html

● Nesse tipo de “try”, é possível declarar e inicializar objetos que implementam java.lang.AutoCloseable– Ao término do “try”, o close do objeto será invocado

automaticamente● Exemplo:

try (Connection con = new FabricaDeConexao().obterConexao()){

// faz um monte de operações sobre a conexão

// que podem gerar exceções

catch(SQLException e) {

System.out.println(e);

}

40

Exemplo de Implementação do Data Mapper em Java

● Um exemplo de implementação do Data Mapper foi disponibilizado com o material da aula (arquivos do Exemplo 3)

– Baseado nos exemplos contidos no livro “Patterns of Enterprise Architecture”

– Adaptado do código em:

https://github.com/asakichy/PofEAA

● Nesse exemplo, há apenas uma classe de domínio – a Person –, que tem como atributos firstName, lastName e numberOfDependents

● Além do Data Mapper, o código do Exemplo 3 exemplifica a implementação do padrão Identity Map

https://martinfowler.com/eaaCatalog/identityMap.html

41

● Principais

– Row Data Gateway

– Table Data Gateway

– Data Mapper

– Active Record

● Auxiliares

– Unit of Work

– Identity Map

– Lazy Load

Lista (Incompleta) dos Padrões Arquiteturais para Camada de Dados

● Mapeamento de relacionamentos

– Identity Field

– Foreign Key Mapping

– Association Table Mapping

http://martinfowler.com/eaaCatalog/

42

“Lição de Casa” - I

● Ler (no site ou no livro do Martin Fowler) sobre os padrões:– Unit of Work – “Maintains a list of objects affected by a business

transaction and coordinates the writing out of changes and the resolution of concurrency problems.”

https://martinfowler.com/eaaCatalog/unitOfWork.html

– Identity Map – “Ensures that each object gets loaded only once by keeping every loaded object in a map.”

https://martinfowler.com/eaaCatalog/identityMap.html

– Lazy Load – “An object that doesn't contain all of the data you need but knows how to get it.”

https://martinfowler.com/eaaCatalog/lazyLoad.html

43

“Lição de Casa” - II

● Ler (no site ou no livro do Martin Fowler) sobre os padrões:

– Identity Field – “Saves a database ID field in an object to maintain identity between an in-memory object and a database row.”

https://martinfowler.com/eaaCatalog/identityField.html

– Foreign Key Map – “Maps an association between objects to a foreign key reference between tables.”

https://martinfowler.com/eaaCatalog/foreignKeyMapping.html

– Association Table Mapping – “Saves an association as a table with foreign keys to the tables that are linked by the association.”

https://martinfowler.com/eaaCatalog/associationTableMapping.html

44

Referências Bibliográficas

● Livro: “Patterns of Enterprise Application Architecture” (2012), de Martin Fowler,

– Capítulo 3 – “Data Source Architectural Patterns” está disponível online:

http://www.informit.com/articles/article.aspx?p=1398618

– Resumo dos padrões:

http://martinfowler.com/eaaCatalog/

● “Core J2EE Patterns - Data Access Object”

http://www.oracle.com/technetwork/java/dataaccessobject-138824.html

● Apostila da Caelum – “Banco de Dados e JDBC”

http://www.caelum.com.br/apostila-java-web/bancos-de-dados-e-jdbc/

● Slides do prof. João Eduardo Ferreira sobre persistência:

http://www.ime.usp.br/~jef/persistencia.pdf