Posts Tagged ‘web’

Por uma web melhor: evite manter estado

7 de setembro de 2010

Todo dia centenas de aplicações são lançadas ou atualizadas na internet e fazem uso do protocolo http, que influencia diretamente o retorno do nossos produtos. Por exemplo, adotar web services via ftphoje em dia não parece tão viável quanto era anos atrás.

Mas mesmo com um protocolo ubíquo como o http, muitas vezes deixamos de lado conhece-lo a fundo e perdemos um grande número de potenciais clientes.

Um caso comum que pode ser melhorado é a utilização indiscriminada de estado de cliente para responder uma requisição.

Nesse cenário, já na primeira requisição o servidor marca o cliente com um cookie de tempo determinado de expiração, por exemplo 15 minutos, e esse cookie é essencial para todas as requisições futuras. Assim que o cookie expira, o usuário é obrigado a voltar para a pagina inicial.

Por exemplo, no site da Tam, inicie uma busca e aguarde sua sessão expirar. Tente executar um refresh: o site o redireciona para a página inicial de escolha de língua, uma página que você não passou anteriormente.

Tam e a escolhe de país

Site com escolha de país. Opção para lembrar, mas será esquecida junto com o cookie.

Ao escolher um país note que devido a utilizar cookies (ou url-rewriting), o sistema não consegue realmente lembrar após o tempo passar, apesar de marcarmos o checkbox.

Além do usuário se assustar com uma tela que não existia antes, ele não retorna para onde estava, mas sim para a página inicial, perdendo o trabalho executado até então.

Se o usuário encontrou uma viagem interessante e tenta compartilhar o mesmo para Se enviar o link para um colega para que veja o preco da passagem, ele nao sera capaz de acessa-lo. Como o http pode nos ajudar? Trabalhando com a busca como um recurso (de REST), URIs amigáveis, verbo GET e sem manter o estado teríamos uma URI que resolveria quase todos os problemas acima mencionados:

http://site.com.br/viagem/cgu/seo/20110101/201101012

Podemos medir o número de clientes potenciais que podemos perder diariamente por mantermos sessão em momentos desnessários colocando um contador na página de perda de sessão.

Analise em seu site quantas pessoas entram nessa página diariamente e tem seu fluxo de pensamento quebrado devido a essa abordagem.

Na abordagem da URI baseada em recursos existe somente um ponto que não foi abordado: como saber o país do cliente? Existe uma solução padrão do http para isso: utilize o header Accept-language.

Seria possível reescrever as URIs com a língua o que apresenta desvantagem somente para o caso de compartilhar a URI com amigos que não entendem a lingua atual.

Timeout

Quando uma sessão se faz necessária e o tempo é curto, mantenha um contador indicando o mesmo para seu usuário, como no site do Banco do Brasil. Perder o fluxo de trabalho atual é sempre uma experiência negativa portanto dê a chance de seu usuário executar um refresh para continuar trabalhando.

Solução do BB: mostrar o tempo até expiração.

Caso o usuário esteja preenchendo um formulário e não queira executar um refresh, mostre um alert do javascript confirmando se o usuário deseja se manter logado, executando uma requisição ajax para prolongar o tempo, como alguns sistemas de submissão de palestra online costumam fazer.

Recentement Subbu Allamaraju comentou sobre a questão de sessão não fazer parte de HTTP e quão vital isso é para a web escalar.

Entender o cookie e o valor da sessão significa algo além do que está na URI: conhecimento fora do padrão HTTP, chamado out-of-band knowledge. Sites que se baseiam nesse tipo de trabalho, implicam em pior SEO, além de dificuldades de acesso no dia a dia por seus usuários. Por uma web melhor, não dependa de estado do seu cliente.

Anúncios

Filtros REST em Rails e Java

18 de março de 2010

Para aqueles que gostariam de ver somente o conteúdo relativo as notícias de gerenciamento ágil, assinem o feed da categoria agile.

Para quem gostaria de assinar o feed completo, utilize o feed principal.

Muitas aplicações web possuem páginas de relatórios com campos para filtragem. O exemplo mais famoso é o caso onde o usuário pode configurar a data inicial e final para filtragem de dados.

FIltragem de dados

Mas o que acontece quando o usuário clica em qualquer link desse relatório, ou de relatórios consecutivos que aparecem após o mesmo? A data se perde. Em situações genéricas, o filtro se perde.

Vou exemplificar três maneiras de implementar tal funcionalidade.

Armazenar na sessão

É muito comum ver aplicações onde na primeira tela somos responsáveis por escolher, por exemplo, com qual unidade, centro de custo ou contrato desejamos trabalhar e, a partir de então, com tal valor armazenado na sessão no lado do servidor, temos acesso a URIs como http://www.projeto.com.br/clientes que retornaria a lista de clientes de uma unidade.

O que acontece se desejo trabalhar com clientes de duas unidades ao mesmo tempo, em abas distintas? Tenho que mudar de unidade a cada clique que executo com clientes de unidades diferentes.

Além disso, caches públicos como proxies entre o servidor e o cliente não terão o mesmo ganho de desempenho com URIs identificadoras de recursos reais.

O load-balancing também se torna custoso pois a sessão fica presa a uma máquina ou deve ser replicada em determinados momentos.

Tudo isso acontece pois sua aplicação é stateful, quebrando uma das regras da arquitetura REST.

O escopo flash é uma solução que cai nessa categoria.

Parâmetros do request

Outra solução é quando as características do filtro são passadas por parâmetros em uma URI do acessada através de GET.

parametros get

Nesse caso, podemos sobrescrever o método utilizado para definição de links para sempre adicionar os parâmetros de filtagem (url-rewriting):


  # remembers the starting and end date on all links
  def url_for(options = {})
    options[:start_date] = params[:start_date]
    options[:end_date] = params[:end_date]
    super(options)
  end

  public String urlFor(Class resource, String method) {
     return "/" + resource.getName() + "&start_date=" + params("start_date") + ...;
  }

Note que em ambos os casos é possível criar um componente que decide se o parâmetro de filtragem deve ou não ser adicionado.

Com um único método (monkey patch no Rails ou definição de tag no Java) somos capazes de resolver o problema em todos os links de um sistema.

Note que com essa abordagem, não existem os problemas de sessão apresentados anteriormente.

Armazenar um cookie no client

Aqui, como na solução baseada em sessões, existe o problema do trabalho em unidades distintas em diversas abas.

Uma vez que o cookie registrou informações relativas ao estado do cliente no processo definido no servidor, as próximas requisições irão levar em consideração tal informação, em todas as abas.

Novamente perdemos escalabilidade e, se usado em conjunto com sessões, temos um fator a mais negativo no load balancing.

REST

A segunda solução é a única que se aproxima mais de uma arquitetura REST: o servidor não mantém estado e a URI identifica um recurso, onde, por exemplo, open search pode ser utilizado para o sistema de filtragem.

O segredo está em deixar o cliente através de recursos identificados por URIs, ser guiado pelo servidor, e nenhum dos dois armazenem informações relativas ao estado atual de um processo. Os recursos e seus links ditam o processo (HATEOAS).

Note que de todas as soluções, ela foi a mais simples de trabalhar e com mais vantagens.

Além disso, não foram usados cookies que quebram a transparência para layers intermediários.

Fuja de cookies e de sessões, viva uma vida mais rest.