Fastlane

Este texto foi atualizado e doado ao projeto Code Design World.
Leia a versão mais atualizada.

Fast Lane Reader

Fast Lane Reader(Leitor Via-Rápida), ou apenas , Fastlane, é um padrão de projeto que visa diminuir a criação de objetos durante a leitura de uma coleção de objetos diminuindo o caminho entre o consultor da lista e o repositorio dos dados reais. [1].

O problema

Você precisa iterar uma lista de objetos mas a lista é muito grande.
Em uma aplicação multicamada os dados do objeto são lidos do banco e colocados em instancias do objeto , que é depois colocado num objeto de coleção (um List, por exemplo). Criar todos esses objetos e colocar numa coleção java seria demasiado honeroso quer em termos de memória, quer em termos de processamento.

A solução

A solução é simples de entender, mas não necessáriamente de implementar. Em vez de criarmos todos os objetos de uma vez, colocar na coleção e descartar a fonte de dados ( normalmente um java.sql.ResultSet) podemos encapsular a fonte de dados com a interface que queremos e construir o objeto de dados apenas quando necessário e um por vez.

A solução tipica é ter um objeto do tipo Iterator, ou semelhante, em que temos um método para saber
se ainda existem mais elementos e um métodos para obter o elemento seguinte ( o próprio java.sql.ResultSet segue este padrão).
Um objeto Factory está encarregue de pegar os dados brutos da fonte e os transformar em objetos, contudo,
este objeto não será guardado em lugar algum, diminuindo a quantidade de memória alocada durante a iteração.

A seguir a estrutura de um objeto Fastlane que implementa a interface de um Iterator e lê um java.sql.ResultSet.


01
02
03 public ResultSetFastlaneIterator<T> implements Iterator<T> {
04
05 ResultSet rs;
06 Factory<T> factory;
07 public ResultSetFastlaneIterator ( ResultSet rs , Factory<T> factory ){
08 this .rs = rs;
09 this .factory = factory;
10 }
11
12 public boolean hasNext (){
13 return rs.next () ;
14 }
15
16 public <T> next (){
17 return factory.newObject ( rs ) ;
18 }
19
20 public boolean remove (){
21 throw new UnsupportedOperationException ( “Remove is not supported” ) ;
22 }
23
24 public void finalize (){
25 rs.close () ;
26 }
27 }



Código 1:

Utilizamos o objeto factory para construir o objeto a partir do registro atual no ResultSet.
Isso poderia ser feito diretamente no código do método next(). Assim é mais legivel já que o nosso objtivo aqui não é explicar a criação do objeto.

Um detalhes importante é que apenas no livramos da fonte de dados quando o objeto de FastLane não for mais utilizado.
Para isso implementamos um codigo especial no método finalize(). Na realidade a chamada a close() lança uma exceção verifica.
Essa exceção tem que ser tratada de forma que não impeça o objeto de FastLane de ser removido da memoria.

Comparemos os códigos utilizando Fastlane e sem utilizar o padrão. Este código seria escrito num objeto que implemente o padrão DAO, por exemplo. (O tratamento de exções foi removido para simplificação)

01
02
03 // sem fastlane
04 public Iterator<T> getIteratorForQuery (){
05
06 // obtém resultados do banco
07 ResultSet rs = executeQuery () ;
08 Factory<T> factory = new Factory<T> () ;
09
10 List<T> list = new LinkedList<T> () ;
11
12 while ( rs.next ()){
13 list.add ( factory.newObject ( rs )) ;
14 }
15
16 // descarta resultSet
17 rs.close () ;
18
19 return list.iterator () ;
20 }
21
22 // com fastlane
23 public Iterator<T> getIteratorForQuery (){
24
25 // obtém resultados do banco
26 ResultSet rs = executeQuery () ;
27
28 Factory<T> factory = new Factory<T> () ;
29
30 return new ResultSetFastlaneIterator ( rs,factory ) ;
31
32 }

Código 2:

O código é apenas um inicialização do objeto. Não ha iteração nem fabricação de nenhum objeto.
O primeiro código cria e mantém 1+N objetos onde N é o numero de registros retornados na pesquisa.Na execução do iterador ele não cria mais nenhum objeto. Portanto, a cada iteração existem na memoria 1+N objetos.
O segundo métodos cria e mantém 3 objetos e durante a execução da iteração cria mais 1 objeto.
Portanto, a cada iteração existem na memoria 4 objetos. Não é preciso muito para entender que existe uma vantagem em utilizar FastLane Reader quando N é grande. E grande, neste caso é ser maior que 3.

Utilização

Em aplicações web é muito comun oferecer listagens para consulta pelo utilizador. Estas consultas
são baseadas em objetos já que as tags JSP são normalmente baseadas em coleções. Contudo podemos “enganar” a camada que gera o HTML utilizando um objeto Fastlane que comunica directamente com o banco.

Limitações

O padrão FastLane Reader pretender acelerar a leitura de um conjunto de registros
de forma eficiente. A forma de fazer isso é ignorar a separação de camadas e acessar internamente à camada de dados de uma qualquer outra camada superior. O utilizador do objeto que implementa o padrão não tem conhecimento de que os dados estão vindo directamente da camada mais inferior.

Para que este processo de comunicação “trans-camada” funcione, a camada onde o objeto é utilizado e a camada onde os dados são lidos têm que existir no mesmo nodo ( no caso, na mesma JVM). Caso contrário teremos que incluir logicas de Proxy remoto e com isso colocando barreiras na comunicação entre as camadas.A via não é mais livre, e portanto, não é mais rápida.

O padrão FastLane viola a separação de camadas explicitamente para fornecer uma otimização de eficiência.
A utilização deste padrão implica num trade-off consciente: a violação de um principio básico em prol de um aumento de eficiencia.
Contudo, é preciso tomar cuidado porque a violação de separação de camadas pode ter efeitos secundários à partida desconhecidos.

Padrões Relacionados

FastLane Reader pode ser entendido como uma especialização de Proxy em que o objeto constantemente comunica com um objeto em outra camada. Por outro lado, esse objeto não tem a mesma estrutura que o objeto Fastlane por isso podemos entendê-lo como a especialização de Adapter. Por outro lado, ainda, podemos considerar que o trabalho de Fastlane não é completo sem o uso de outros objetos, como um Factory ou próprio objeto que contêm os dados originais. Isso nos poderia levar a considerá-lo um Façade.

No frigir dos ovos o FastLane não é nenhum destes. Ele pega um pouco de cada. Talvez por isso, ele mereça seu próprio nome.

Um outro padrão relacionado ao FastLane Reader é o Flyweight. O objeto criado
pelo FastLane Reader pode ser uma versão simplificada do objeto real. Desta forma, não só diminuímos o numero de objetos em memoria mas para cada um deles diminuímos o numero de atributos em memoria.

Referências

[1] Core J2EE Patterns – Fast Lane ReaderSun Developer Network

Core J2EE Patterns – Fast Lane Reader
URL: http://java.sun.com/blueprints/patterns/FastLaneReader.html

Licença


Creative Commons License
Sérgio TabordaEste trabalho é licenciado sob a


Licença Creative Commons Atribuição-Uso Não-Comercial-Não a obras derivadas 3.0 Genérica
.

2 opiniões sobre “Fastlane”

  1. ótimo post Sérgio. só fiquei com uma duvida que não foi relacionada ao FastLane Reader e sim a linha:

    Factory factory = new Factory () ;

    e

    list.add ( factory.newObject ( rs )) ;

    essa factory vc usa introspecção?

    achei bem produtivo.

    1. A estratégia que a factory usa pode ser muito diversa. Sim pode usar reflection, mas pode fazer na mão tb, mapeando cada campo do objeto com o campo do resultSet. Essa parte fica para definir conforme o sistema. Exactamente por isso que eu encapsulei num objeto factory, porque não interessa muito como o objeto é criado. Interessa que dado um rs, um objeto é criado para a linha corrente.

Deixe um comentário