sexta-feira, 24 de abril de 2015

Dez considerações sobre performance no ambiente mobile

É muito comum que desenvolvedores de sistemas extremamente competentes se aventurem pelo mundo dos apps para dispositivos móveis com alta taxa de frustração. Geralmente o motivo é que não adequam corretamente as suas criações ao contexto móvel.

Desenvolver aplicativos para celulares pressupõe o conhecimento de algumas questões bastante peculiares.

Este artigo visa explicitá-las, de forma a orientar desenvolvedores sobre pontos fundamentais do contexto mobile, que influenciarão na qualidade da experiência do usuário final.

1.  A Rede

A primeira observação diz respeito à rede móvel. Nem sempre o aplicativo terá acesso à rede para realizar uma comunicação. Isso deve ser a premissa número 1 ao desenvolver aplicativos. Os fatores podem ser os mais diversos: Falha das operadoras, zonas de sombra, condições climáticas desfavoráveis, sabotagem, interferências, interrupção do serviço devido ao limite do plano de dados, ausência de plano de dados, enfim, vários motivos podem deixar um aplicativo sem comunicação com a Internet. Isso deve ser tomado como uma realidade e o desenvolvedor deve preparar o aplicativo para responder corretamente. Um app que exija autenticação, por exemplo, pode usar uma técnica de guardar o estado, de forma a não precisar mais da rede uma vez autenticado o usuário.

2.  Integração

Um sistema desenvolvido para ambiente móvel geralmente é composto por duas partes distintas, conhecidas formalmente como "front-end" e "back-end". A primeira é o aplicativo propriamente dito, que é executado no aparelho celular do usuário. A segunda é uma API, um programa que existe hospedado em um servidor remoto, à espera de requisições. O trabalho é dividido entre essas duas partes, cabendo ao desenvolvedor determinar o que é papel do front-end e o que é papel do back-end. Geralmente o aplicativo tem o objetivo de expor as informações de forma que possam ser visualizadas fácil e rapidamente pelo usuário (por exemplo, em um mapa). E a API é onde ocorre o processamento mais pesado e as buscas nos bancos de dados. As duas partes devem conversar da maneira mais otimizada possível, trafegando o mínimo de dados pela rede. Também, de acordo com o que vimos no item 1, é preciso fornecer uma alternativa à rede, garantindo as funcionalidades do aplicativo na sua ausência.

3.  Escassez de recursos

Embora a cada dia os celulares tenham mais memória e poder de processamento, é muito comum que eles estejam sempre entupidos de aplicativos, videos, músicas, etc. Em outras palavras, o desperdício de recursos aumenta exponencialmente junto com o poder tecnológico dos aparelhos. Como se não bastasse, o Android tem uma questão séria em relação à distinção da memória interna do aparelho e da memória externa (o cartão SD). Na grande maioria das vezes os aplicativos e seus bancos de dados locais são armazenados nessa memória interna (na pasta "/data/data"), que geralmente é menor e quando cheia, torna o celular lento e causa travamentos. Portanto, os recursos são escassos. Isso exige que o desenvolvedor otimize o máximo que puder, reutilize código, mantenha arquivos de imagens o menor possível, use o menos possível da rede, libere memória sempre que puder. No Android, é tarefa do desenvolvedor, por exemplo, retirar as activities (telas) da memória, (com finish())quando não são mais utilizadas. Antes de publicar um APP na loja, é imprescindível passar um pente fino no código-fonte e nas pastas do projeto, a fim de verificar o que pode ser excluído, diminuído ou otimizado.

4.  Assincronia

A maioria dos acessos de um aplicativo à rede deve ser assíncrona. Senão, o usuário permaneceria esperando o app terminar uma consulta antes de mostrar o resultado. Neste ínterim, o aplicativo ficaria travado. Se o usuário estivesse olhando para um mapa, por exemplo, e fosse feito um acesso síncrono, a navegação pelo mapa ficaria interrompida até que a requisição tivesse sido respondida. Imagine, também, rotinas que atuem em background, sem que o usuário saiba. Todas devem ser assíncronas. Não fosse assim, travariam o aplicativo até o término da operação. É claro que cada caso é um caso. Há rotinas onde a sincronia é necessária, como por exemplo uma autenticação de usuário, que depende do resultado para prosseguir, ou a obtenção de dados que serão utilizados à frente. Mas é possível criar acessos assíncronos de forma que os resultados obtidos via rede vão sendo mostrados pouco à pouco, à medida que são recebidos, e não apenas ao final do processo. Isso melhora substancialmente a experiência do usuário.

5.  Gravação local

Um dos maiores segredos de sucesso de aplicativos famosos é justamente a gravação local de dados. É uma técnica que permite oferecer ao usuário uma experiência de fluidez incrível no uso do app. Toda operação de gravação tem resposta imediata, causando uma percepção de que o aplicativo é incrivelmente rápido. Isso é feito com algo extremamente simples: a gravação dos dados num banco local SQLite, que reside no próprio celular. Esses dados serão sincronizados mais tarde, via rede (geralmente no método onPause() do aplicativo). Essa técnica permite até mesmo criar aplicativos que não precisam de rede. Imagine um aplicativo de avaliação de restaurantes onde você possa ver e avaliar os estabelecimentos, mesmo sem sinal de Internet presente. Isso é possível se o aplicativo guarda tudo num banco de dados local. Depois, quando o app perceber em algum momento que retornou o sinal de Internet, então ele faz o upload para o servidor, daquilo que ainda não tenha sido sincronizado.


6. Antecipação

Antecipação é outra técnica muito interessante que muda completamente a experiência de fluidez do usuário e aproveita melhor o tempo de "inatividade". Imagine que você criou um app que permite que o usuário tire fotos e depois as publique na Internet. Logo depois que o cidadão tira uma foto, o app exibe uma caixa de diálogo perguntando: "Você deseja publicar a foto neste momento?". A técnica de antecipação consiste em, antes de jogar na tela a pergunta ao usuário, já iniciar um processo assíncrono de upload da foto, ou seja, o app já estará enviando a foto para o servidor enquanto o usuário vê a mensagem e pensa se quer publicá-la ou não. Se o usuário levar 3 segundos para pensar, pode ser suficiente para que a foto seja transferida. A decisão do usuário, então, confirmará (ou não) a publicação da foto.

7. Cache

Eis uma técnica que pode ser vista sob vários aspectos. Mas, é inquestionável que o uso de cache é o que torna possível o que fazemos hoje com nossos aparelhos celulares. Para aqueles que não sabem, o cache é uma forma de armazenar dados que permite sua recuperação de maneira muito rápida, praticamente instantânea, se comparado aos métodos tradicionais. Explicando muito superficialmente, os dados que buscamos quando efetuamos uma requisição, via de regra estão gravados em discos, que são dispositivos físicos, cujo acesso depende de deslocamentos de braços mecânicos sobre superfícies magnéticas. Essas buscas geralmente ocorrem na casa dos segundos, o que, embora pareça pouco no contexto humano, no contexto das máquinas é uma eternidade. Então, foi inventado o cache, que nada mais é do que a reprodução de parte dos dados em memória eletrônica. Dessa forma, o tempo para obter as respostas cai para a casa dos milissegundos, permitindo a experiência que temos hoje em nossos smartphones. Acontece que a maneira de aplicação de um cache é também bastante subjetiva. Mas o conceito e a intenção permanecem os mesmos. Uma das formas de implementar cache é na API remota, que é consumida pelo app. Cria-se uma tarefa agendada que extrai a informação de um banco de dados de tempos em tempos e a armazena em memória real. Esta memória (o cache) é, então, exposta via webService. Isso garante um acesso praticamente imediato do app aos dados remotos, pois a consulta ao banco de dados remoto foi antecipada pela API. Outra maneira de implementar cache é no próprio aplicativo. Por exemplo: Na primeira vez que o aplicativo é acionado, é feita uma consulta à API que traz todos os itens disponíveis numa determinada tabela do banco de dados remoto (por exemplo: uma lista de restaurantes). Esses itens são, então, armazenados em um banco de dados local, dentro do aparelho celular, o que constitui um cache local de dados). Esse tipo de cache vai permitir que, mesmo sem acesso à Internet, o aplicativo possa mostrar ao usuário os restaurantes para que sejam avaliados. Cache é essencial.


8. Compatibilidade

Sempre que você tiver aquela vontade irresistível de usar aquele novo recurso fantástico disponível apenas na versão recém-lançada do sistema operacional Android, pense duas vezes. Qual o seu público-alvo? A quantas pessoas deseja que seu aplicativo atenda? Num país como o nosso, embora as estatísticas mostrem que já existem mais celulares do que pessoas, é pouco provável que a maior parte deles sejam aparelhos modernos. Então, compensa utilizar um recurso que vai restringir o uso do seu app apenas aos dispositivos mais novos? Particularmente acho que não. Essa é uma discussão importante, pois durante o desenvolvimento de aplicativos Android, é preciso especificar para qual versão você está programando, o que vai provocar uma limitação no número de aparelhos que suportam o seu app.  O resultado é que, se uma pessoa com um celular mais antigo pesquisar o seu app na Google Play Store, se ele não for compatível com o aparelho dela, o app nem ao menos aparece na pesquisa. Eu tenho como filosofia criar apps que funcionem na maior parte possível de aparelhos Android. No uso de mapas, por exemplo, é preciso baixar o "Google Play Services for Froyo", biblioteca que (embora considerada deprecated) é compatível com qualquer modelo de aparelho Android. Aplicativos com mapas produzidos com esta biblioteca funcionarão no mais básico Android (essa biblioteca está incluída em nosso ambiente de desenvolvimento disponível aqui no blog). No momento que se publica o APK na loja, o desenvolvedor recebe um relatório informando o número de dispositivos compatíveis. Recomendo levar este quesito com seriedade. É muito frustrante não poder usar um app por ser incompatível com nosso modelo de celular. Seu usuário também pensará desta forma.


9. Agilidade

Chamamos os aparelhos celulares de "dispositivos móveis" não é à toa. As pessoas usam seus smartphones na rua, à caminho do trabalho, ou no supermercado, enfim, é preciso entender o contexto em que acontece o uso do aplicativo. O usuário está com pressa, fora de casa, no meio do caminho para algum lugar, as condições de iluminação podem variar (o usuário pode estar na praia, com sol à pino, ou dentro de um vagão do metrô mal iluminado). Portanto, para um app ser considerado adequado, as respostas precisam ser rápidas. Mantenha o foco em responder ao usuário imediatamente.


10. Simplicidade

Alguns desenvolvedores sustentam uma regra de que no contexto mobile, o número de cliques (toques na tela) não deve passar de três, desde a primeira interação do usuário até a obtenção daquilo que ele procura. De fato, existe uma infinidade de aplicativos altamente complexos que não fazem sucesso porque não é o que o usuário quer. Num aplicativo de ônibus, por exemplo, talvez o usuário não queira traçar rotas especificando origem e destino dos veículos que tem ar-condicionado e rodas de liga leve e teto solar, mas, simplesmente, querem saber onde o ônibus está. Portanto, tenha isso em mente. Mantenha as coisas básicas o máximo que puder. Pense nos aplicativos mais famosos (que têm bilhões de downloads na loja) e confira como são, de fato, simples.



Embora alguns dos itens expostos acima possam parecer não ter relação com performance, no meu entender há vários tipos de "performance". O conceito está sim, sempre ligado a desempenho, o que não significa apenas que o aplicativo é rápido, mas sim que toda uma experiência do usuário tem uma prazerosa fluidez.

Há também alguns aspectos importantes no desenvolvimento de aplicativos que consiste em ter um bom embasamento teórico-filosófico, o que funciona como os alicerces da própria ideia do aplicativo, o que dá sentido a ele.

Este será o tema de nosso próximo post. Não perca!

Um comentário:

  1. Considerações muito importantes. Sendo um pouco mais rigoroso e baseado nas normas de qualidade, sugiro mudar de compatibilidade para portabilidade.

    ResponderExcluir