speed

Otimizando a performance de aplicativos Cordova/Ionic Framework

Olá pessoal, nessa última semana tive a boa surpresa de ter meu aplicativo Mini Receitas aceito no showcase do Ionic Framework e o melhor é que ele foi considerado pela equipe do Ionic como um dos Top Apps feitos com o framework. Esse bom resultado me fez refletir em como eles escolhem os aplicativos que vão para o Top Apps e a conclusão que eu cheguei é que como eles não conseguem testar a finalidade de todos os aplicativos até por que eles podem estar em idiomar que eles desconhecem, como o português, o que vale mesmo é a performance e o design.

Não sou nenhum especialista em design, mas depois de meia década trabalhando como front-end eu tenho noção do que não fazer, então acho que não passo vergonha como muitos desenvolvedores (principalmente os que vieram do mundo back-end). No entanto, como não sou especialista nesse assunto prefiro falar pra vocês dois cuidados (banco de dados e animações) que tomei para criar um aplicativo híbrido performático.

Banco de dados

A primeira coisa que eu fiz para otimizar a performance do aplicativo foi efetuar o mínimo de operações possíveis no banco de dados pois essas bloqueiam o DOM e iriam travar minha interface. De início segui as dicas do artigo How To Use PouchDB + SQLite For Local Storage In Your Ionic App da Ashteya Biharisingh e embora isso tenha melhorado muito a performance do meu aplicativo eu ainda tinha problemas nas transições de telas. Principalmente nos primeiros acessos às telas, pois o Ionic ainda não tinha colocado-as em cache.

O que acontece é que quando você realiza o primeiro acesso a uma página não cacheada ou uma que possui o cache desabilitado o seu código consulta o banco e isso causa o bloqueio do DOM. Então o objetivo é evitar que ocorra esse bloqueio. E a forma que encontrei de fazer isso foi carregar todo o banco de dados em cache antes mesmo do usuário acessar a tela que irá utilizá-lo.

Para isso eu criei um serviço chamado Loader que possui um método chamado done que me retorna uma promise. Esse método done é quem carrega todos os dados do banco para o cache como descrito pelo artigo da Ashteya.

Logo, o que precisei fazer (usando alguns recursos do ES6) foi:

services/loader.service.js

/**
  * LoaderService
  */
  
(function() {
  'use strict';

  function LoaderService ($q, RecipesService){
    'ngInject';

    this.done = function() {
      return $q.all([
                RecipesService.getAllRecipes()
              ])
              .then((...args) => args)
              .catch((...args) => args)
    }

  }

  module.exports = LoaderService;
}());

index.run.js

/**
  * Run
  */
  
(function() {
  'use strict';

  function runBlock (Loader, $ionicPlatform, $cordovaSplashscreen) {
    'ngInject';

    $ionicPlatform.ready(function(){
      Loader.done()
            .then(function(){
              $cordovaSplashscreen.hide();
            })
    })

  }

  module.exports = runBlock;
}());

index.module.js

/**
  * Definição do módulo
  */
  
import runBlock from './index.run';

import LoaderService from './services/loader.service';
import RecipesService from './services/recipes.service';

angular.module('miniReceitas', ['ionic', 'ngCordova'])
       .run(runBlock)

       .service('RecipesService', RecipesService)
       .service('Loader', LoaderService);

Note que eu também faço o uso do plugin cordova-plugin-splashscreen , faço isso para que o usuário só possa interagir com o aplicativo após todo o banco de dados estar em cache. Dessa forma ele não percebe o bloqueio do DOM pelas consultas ao banco. O único momento o usuário pode vir a notar algum tipo de bloqueio é ao inserir, alterar ou deletar algum registro no banco. No entanto essas operações normalmente são mais leves que uma query de consulta.

Animações

Animações são muito importantes para que aplicativo ofereçam uma boa experiência para o usuário. Quando estamos criando sites nem sempre nos preocupamos com a performance delas já que computadores possuem muito mais poder de processamento, porém nem sempre trabalhamos com mobile-first, o que é um erro em um mundo onde o usuário passa boa parte do seu dia conectado a internet através de dispositivos móveis.

Enfim, para otimizar as animações nós devemos entender como o CSS é renderizado e para isso eu recomendo a leitura do artigo Entendendo os Reflows. Mas em síntese o que precisamos fazer é evitar Repaints e Reflows. E para evitá-los basta projetar seu CSS com propriedades que não disparem esses eventos.

Você pode, por exemplo, utilizar o transform: translateY ao invés do top ou o bottom para uma animação, pois o top e bottom disparam tanto o Repaint quanto o Reflow. Você pode utilizar o CSS TRIGGERS para consultar se a propriedade css que você está utilizando para suas animações dispara algum desses eventos.

(Bônus) DOM

Ainda não terminei a implementação desse terceiro item, por isso ele está presente apenas como bônus. Mas assim como temos que ter cuidado com a árvore de renderização do CSS, nós também temos que ter cuidado com a do HTML. E uma técnica que vem cada vez mais sendo utilizada para otimizar a performance do DOM é o ato de renderizar apenas os nós visíveis. No caso do AngularJS que cada um dos nós pode possuir uma escopo ligado a ele por meio do two-way data binding isso pode otimizar ainda mais a performance pois remove os listeners dos itens que não estão visíveis, já que eles não estão renderizados.

No Ionic uma diretiva que faz uso dessa técnica é a Collection Repeat e estou trabalhando para implementá-la no novo Slider que foi introduzido na versão 1.2 do framework.

Enfim fim

E é isso, além dessas existem outras otimizações que já citei no artigo 4 Dicas para trabalhar com o Ionic Framework e vocês podem encontrar mais algumas dicas na apresentação Top 10 Performance Techniques for PhoneGap and Hybrid Apps do Christophe Coenraets que ainda continua super atual. Sem contar que no fim das contas é tudo Javascript, logo, otimizações a nível da linguagem são sempre bem vindas, nesse sentido recomendo o artigo 10 Javascript Performance Boosting Tips from Nicholas Zakas do Jon Raasch e o artigo do Addy Osmani entitulado Writing Fast, Memory-Efficient JavaScript.


Ultimamente tenho estudado mais questões relacionadas a engajamento do usuário, promoção de aplicativos e melhoria de ranking nas lojas de aplicativos e achei conveniente fazer um post sobre performance enquanto essas informações ainda estão frescas em minha memória. Espero que esse post possa ajudá-los e caso você utilize alguma outra técnica para otimizar a performance dos seus aplicativos deixe seu comentário abaixo para que possamos disctuir e criar aplicativos cada vez melhores.

ionic

4 Dicas para trabalhar com o Ionic Framework

1 – AngularJS

Originalmente essa não era a primeira dica, mas no decorrer da escrita notei que provavelmente era a dica mais importante. O Ionic é um framework escrito sobre o AngularJS, logo, boa parte das dicas com relação ao AngularJS cabem no Ionic (como a últim dica).

De fato o AngularJS não é o framework SPA mais performático do mercado, ele tem problemas estruturais que remetem ao início de seu desenvolvimento e impactam na performance do mesmo e é um dos motivos da total reescrita do framework para sua segunda versão. Com o passar dos meses (e versões) a equipe do AngularJS conseguiu mitigar vários dos problemas de performance e para que você consiga extrair o máximo do Ionic Framework eu recomendo fortemente que você conheça o AngularJS, seus pontos fortes, problemas, peculiaridades, arquitetura, etc.

E para otimizar a performance de seus apps sugiro que leia a série de artigos Micro tunnings with Angular apps (Parte 1 & Parte 2) do GDE Will Mendes.

2 – Native Scrolling

Uma das grandes sacadas da equipe do Ionic para a versão 1.0 "uranium-unicorn" (eu gosto desse nome), foi a implementação do Native Scrolling, que nada mais é que o scroll padrão dos dispositivos. Mas por que isso é bom? Isso é bom por que no começo do desenvolvimento do framework a equipe optou por desenvolver o scroll em javascript para poder oferecer algumas funcionalidades que não seriam possíveis no contexto daquela época dos dispositivos móveis, como Pull To Refresh, Infinite Scrolling, List Reordering, e Collection Repeat. E, convenhamos, grande parte do sucesso do framework é por causa dessas funcionalidades e de sua facilidade de utilização.

Então os dispositivos móveis evoluíram tanto o hardware quanto o software e após o Android 4.1 (Jelly Bean) e o iOS8 essas funcionalidades se tornaram possíveis graças às atualizações do navegador nativo do Android e da WKWebView no iOS8, pois ambas as plataformas passaram a ter suporte aos eventos de scroll nativo e foi aí que a equipe do Ionic resolveu implementar o Native Scrolling, pois com ele a CPU e a GPU do dispositivo móvel, que não é tão potente quanto a de um PC, não precisará mais processar o JS Scrolling, podendo então se preocupar com o que realmente importa: sua aplicação. O que deixará seu aplicativo mais rápido e resultará numa experiência mais fluída para o usuário.

O Native Scrolling funciona da mesma forma que o atributo overflow-scroll="true" na diretiva <ion-content> e para utilizá-lo basta desabilitar o jsScrolling no ionicConfig:

angular.module('ionicApp', ['ionic']).config(function($ionicConfigProvider) {
  if(!ionic.Platform.isIOS())$ionicConfigProvider.scrolling.jsScrolling(false);
})

A diferença de performance ao utilizar o Native Scrolling é notável e se torna ainda mais perceptível em dispositivos Android. No entanto essa funcionalidade ainda não está 100%. Ela não funciona muito bem com o Keyboard e o Collection Repeat. Portanto não é receomendo que você utilize o Colection Repeat ou um input em uma tela que possua o Native Scrolling ativado.

ps.: O código acima ignora a plataforma iOS pois os eventos de scroll nativos só foram implementados na WKWebView do iOS8 e o Ionic oferece suporte ao iOS7 também, logo, o scroll nativo não funcionará como deveria em todas as versões do iOS. É recomendado o uso do scroll nativo em dipositivos iOS caso o suporte de seu aplicativo seja a partir do iOS8.

3 – Debug remoto e autoreload

Durante o desenvolvimento de uma aplicação é sempre bom possuir boas ferramentas de debug para não desenvolvermos às cegas. E no caso de Aplicativos Híbridos nós podemos contar com o apoio do browser nessa tarefa.

Basta rodar o comando ionic run android -l -c -s. Para maiores informações sobre esse comando acesse o artigo Live Reload All the Things.

4 – Estrutura de diretórios e arquivos

Uma boa estrutura de diretórios e arquivos para seu aplicativo é essencial e, de fato, a estrutura dos templates (blank, sidemenu e tabs) do Ionic não é a melhor, pois conforme sua aplicação vai crescendo fica mais complicado gerenciar todos os seus controllers em um único arquivo e quando você divide esse arquivo em um para cada controller fica complicado gerenciar quais arquivos estão relacionados.

Pensando nisso a comunidade do AngularJS criou uma recomendação, chamada Best Practice Recommendations for Angular App Structure, para facilitar no desenvolvimento de Aplicações AngularJS, segundo ela o melhor é organizar seus diretórios e arquivos por funcionalidades e páginas, um exemplo simples seria algo como:

sampleapp/
    app.css
    app.js
    app-controller.js
    app-controller_test.js
    components/
        bar/                        "bar" describes what the service does
            bar.js
            bar-service.js
            bar-service_test.js
        foo/                        "foo" describes what the directive does
            foo.js
            foo-directive.js
            foo-directive_test.js
index.html

Acredito que essas 4 dicas são essenciais para melhorar a performance e a qualidade de aplicativos criados com o Ionic. Em breve voltarei com mais dicas referentes a acesso às APIs do dispositivo, PouchDB, Sincronização com webservice REST, etc.

herança

Entendendo herança no JavaScript

O javascript é uma linguagem orientada a objeto porém diferente da maioria das linguagens orientada a objeto em que a herança é baseada em classes no javascript é baseado em prototypes. Você pode construir uma "emulação" de classes com JavaScript através de funções.
JavaScript não tem classe apenas objetos, isto é, você instacia novos objetos a partir de outros obejtos.

prototype faz referência a todas as propriedades e métodos herdados do objeto pai, incluindo seu prototype.

Ele pode ser pensado como uma lista ligada referenciando o elemento anterior na lista.Um dos principais aspectos da herança de prototype é que se você alterar uma propriedade herdada ou método de um objeto, 
essas mudanças vai refletir nos seus filhos mesmo depois de terem sido criados. Isso porque os filhos remetem as propriedades e métodos do pai.

Outro aspecto importante é que você pode mudar o prototype de qualquer um dos objetos globais. Porém é perigoso, e considerado uma má prática pois objetos globais são definidos por um padrão, por isso fazer que se eles comportarem de outra forma pode ser perigoso e perder seus beneficios.

Vamos há um simples exemplo:

 

ECMAScript 5 introduziu o novo método: Object.create(). Invocando este método podemos criar novos objetos.O prototype destes novos objetos é o primeiro argumento do método:

Este método utiliza um objeto como parâmetro e retorna um novo objeto, e elimina a necessidade de acessar diretamente a propriedade prototype.

var pai = { 
	a: 10,
	b: 50,
	//Object.prototype = {a:10, b:50}
	//pai ---> Object.prototype ---> null
	metodo: function(message) {
		console.log('Eu sou o '+ message);		
	},
};

var filho = Object.create(pai); 
//filho ---> pai ---> Object.prototype ---> null
var neto = Object.create(filho);
//neto ---> filho ---> pai ---> Object.prototype ---> null
console.log(neto.a);   	//vai imprimir 10
pai.a = 20;		//Atribui 20
console.log(neto.a);   	//vai imprimir 20
console.log(filho.a);  	//vai imprimir 20
filho.metodo('filho');  //"Eu sou o pai".
neto.metodo('neto');    //"Eu sou o neto"

 

Para familiarizarmos melhor, vamos fazer uma analogia:

 

var pai = { //Objeto
	a: 10,
	b: 50
};

var filho = Object.create(pai); //criando um objeto e herdando tudo do Objeto pai

 

Seria o mesmo que em Java da seguinte forma:

Class pai { //Classe
    a: 10,
    b: 50
}
Class filho extends pai { //Herdando tudo da classe pai.

}

 

Enquanto a propriedade prototype é usada pela linguagem para construir a cadeia prototype, ainda é possível atribuir qualquer valor a ela. No entanto, os primitivos serão simplemesmente ignorados quando atribuídos como prototype.

 

function Foo() {}
Foo.prototype = 1; // sem efeito
Foo.prototype      //1
Foo.prototype.1    //lança um erro.

 

Este é um exemplo trivial, mas vamos falar de performance.O tempo de pesquisa de propriedades em que estão no alto da cadeia de prototype pode ter um impacto negativo no desempenho, e isso pode ser significativo no seu código em que o desempenho é algo critico. Além disso, tentar acessar propriedades inexistentes irá sempre percorrer a cadeia prototype inteira.

Uma característica inconveniente que é frequentemente usada é estender Object.prototype ou um dos outros contruídos em prototype.
Essa técnica é chamada monkey patching e quebra o encapsulamento. Enquanto é usada por frameworks populares como o Prototype, ainda não há uma boa razão para sobrecarregar tipos internos (built-in types) com funcionalidades adicionais não padrão.
A única boa razão para estender um prototype interno é para transportar as funcionalidades para novos motores JavaScript; por exemplo, Array.forEach.


Agora vamos há um exemplo em que adicionamos propriedades ao objeto pai e disponibilizando aos filhos.

 

var pai = { 
	a: 10,
	b: 50
};

var filho = Object.create(pai);
var neto = Object.create(filho);

console.log(neto.a);   //vai imprimir 10
pai.c = 'Olá';	       //Adiciona a propriedade c e atribui o valor "Olá"
console.log(neto.c);   //vai imprimir 'Olá'
console.log(filho.c);  //vai imprimir 'Olá'

 

Como visto os filhos herdam as propriedades do pai mesmo já tendo sido criados antes das modificações.

 

Como a definição de ojeto global : Object.create() só foi definida apartir do ECMAScript 5, temos uma maneira de contornar a situação para navegadores que não suportam:

 

if (typeof Object.create !== 'function') {
	Object.create = function (o) {
		function F() {}
		F.prototype = o;
		return new F();
	};
}


Concluindo, é essencial entender o modelo de herança baseado em prototype antes de escrever códigos complexos que fazem uso dela. Além disso, esteja ciente do tamanho das cadeias prototype no seu código e quebre elas, se necessário, para evitar possíveis problemas de desempenho ou seja prudende e use Closures ao invés de prototypes. Outro ponto, os prototypes nativos nunca devem ser estendidos a menos que seja por uma questão de compatibilidade com novas funcionalidades JavaScript.

javascript-design-patterns-cover

Module Pattern e privacidade com JavaScript

Pois bem, imagine você trabalhando com uma grande aplicação JavaScript e muitos
desenvolvedores. E você precisa encontrar uma maneira de encapsular seçoes de códigos 
para que eles tenham um namespace privado sem que haja conflitos com o código 
existente.

Como você faria isso? Ora! com Módulos (Module Pattern)

Module pattern usa "funcões imediatas" para criar uma Closure para todo
seu código encapsulado. Você pode ter membros privados e até mesmo publicar APIs publicas

Vamos a um exemplo básico:

var Modulo = (function() {
	var _variavelPrivada = "Esta é privada";
	var _outraVariavelPrivada = "Eu também sou privada";
	public = {}; //Este objeto será retornado.

	function _metodoPrivado() {
		console.log("Este método é privado");		
	};

	public.acessarMetodoPrivado = function(){
		_metodoPrivado();
	};

	public.propriedadePublica = "Esta é uma propriedade publica";
	public.metodoPublico = function() {
		console.log("Este é um método publico");		
	};
	return public;	
})()

console.log(Modulo._variavelPrivada);       //imprime "undefined".
Modulo._metodoPrivado;                      //Lança um erro ao executar.
console.log(Modulo.propriedadePublica);     //imprime "Esta é uma propriedade publica"
Modulo.metodoPublico(); 		    //imprime "Este é um método publico"

 

 

Acessando Métodos privados

E o JavaScript é impressionante pois nos permite invocar métodos privados
através de nossos métodos publicos, observe:

Modulo.acessarMetodoPrivado();	     //imprime "Este método é privado"

O padrão Module Pattern é um excelente exemplo de usar Closure para
gerenciar escopo. Dentro do Módulo existe um âmbito privado que é protegido
de modificação.

Isso não é  tudo, você pode ainda extender o Modulo facilmente através 
de outra "funcão imediata". Tudo que você tem a fazer é passar o Modulo 
original como um novo argumento para a "funcão imediata". Vejamos:

 

var Modulo2 = (function(Modulo){
	//Acesso ao módulo
	Modulo.metodoPublico();
	return Modulo;
})(Modulo)

 

Conforme o código acima, o Modulo2 tem todas propriedades e métodos publicos do Modulo e pode assim acessá-los.

 

var Modulo2 = (function(Modulo){
	//Outro método
	Modulo.novoMetodo = function() {
		console.log("Novo método");	
	};
	return Modulo;
})(Modulo || {})


console.log(Modulo);  //Imprime Object {propriedadePublica: "Esta é uma propriedade publica", metodoPublico: function, novoMetodo: function}

 

Vemos que o método foi adicionado ao módulo inicial(Modulo).

 

Contudo o Padrão de Projeto Module é altamente flexivel por fazer 
grande uso de caracteristicas dinâmicas do JavaScript. É também usado nas bibiotecas
JavaScript modernas, por exemplo JQuery.

Por fim é isso amigos, essa é mais uma boa prática de JavaScript
Mais conhecimentos avançados e padrões de projetos estão por vir aqui neste blog fiquem ligados.

I know jQuery

Muito além do jQuery

Por incrível que pareça eu comecei esse artigo no dia 8 de Agosto de 2013 e ele ficou perdido no limbo do meu Google Drive desde então, faltavam alguns exemplos e uma conclusão. Então, eis que o encontrei ao procurar um outro artigo que estava perdido por lá.

Resolvi finalizar e estou postando com mais de 1 ano de atraso mesmo.


Bom galera já tinha um tempo que eu queria falar sobre esse assunto, mas ainda faltava um incentivo para soltar a boiada. E então eis que aconteceu, dispararam o gatilho. E aconteceu em um grupo de desenvolvimento do facebook, o jQuery Brasil. Um iniciante perguntou quais os requisitos necessários de JavaScript para aprender jQuery e um membro respondeu que não era preciso saber JavaScript para aprender. E na hora eu fiquei indignado, mas pensando bem eu acho que ele está certo, muita gente sabe jQuery e não sabe JavaScript. Mas se o jQuery é uma biblioteca JavaScript, logo, quem sabe jQuery sabe JavaScript, certo?

Em teoria era isso que deveria acontecer, mas as bibliotecas e os frameworks existem para criar uma camada de abstração maior e simplificar o trabalho, então em grande parte das vezes as pessoas não aprendem a linguagem e sim a ferramenta, que pode ser uma biblioteca, um framework, uma sdk, etc.

Então esse artigo é dedicado para o pessoal que sabe jQuery e que provavelmente não sofreu para aprender a trabalhar com o DOM (Document Object Model) ou fazer uma requisição ajax usando o XMLHttpRequest.

Primeiramente eu gostaria de lembrá-los que para tudo que o jQuery faz existe algo equivalente em JavaScript, até por que jQuery é JavaScript (sim, vou falar isso várias vezes). Mas eu não vou começar pelo básico, até por que o básico você encontra facilmente no google. Eu recomendo o ótimo artigo do Tárcio Zemel entitulado “Equivalentes nativos de JavaScript para funções jQuery“, onde o autor mostra algumas dessas equivalências.

Quando usar jQuery?

Uma das inspirações para esse artigo foi o artigo I know jQuery. Now what? do Remy Sharp, onde ele levanta alguns pontos sobre quando não usar jQuery e demonstra algumas soluções de problemas sem a utilização de jQuery. Este artigo é mais simples que o do Remy Sharp por isso recomendo a leitura dele, no entanto, é igualmente opinativo.

Bom, esse artigo já está ficando grande e chato e eu nem comecei a parte técnica ainda, então chega de enrolação.

Quando a complexibilidade supera a facilidade

Quando uma grande parte do seu público alvo não utiliza navegadores de última geração fica complicado trabalhar com JavaScript puro já que algumas funções do JavaScript podem não ser compatíveis por terem sido implementadas depois. O pessoal da BBC, no artigo Cutting the mustard, divide os navegadores em dois grandes grupos (Navegadores HTML5 e Navegadores HTML4) para poder exibir uma interface mais rica ao usuário dependendo dos recursos suportados pelo navegador do mesmo.

Por padrão o IE8 não suporta o método addEventListener que é um método que fica “escutando” um evento e é executado quando o evento do objeto é acionado. Está presente em todos os navegadores lançados desde 2007, menos no IE8. E isso, teoricamente, implica que se o navegador do cliente suportar esse recurso então esse navegador possui um melhor suporte aos padrões que o IE8.

Logo, se o seu público alvo utiliza esse navegador você deve utilizar jQuery. O que não quer dizer que todos os projetos que não utilizem jQuery ou outras bibliotecas não irão funcionar no IE8 e sim que você deve começar o projeto de forma simples e sem gambiarras.

Quando é necessário agilidade

Isso é uma das principais causas pelo qual os desenvolvedores utilizam bibliotecas e frameworks, agilizar o desenvolvimento. E o jQuery faz isso muito bem. Então não precisamos ficar reinventando a roda.

Como sobreviver sem jQuery?

Desenvolver sem o jQuery pode soar para alguns como reinventar a roda. Mas existem algumas alternativas para se escrever a aplicação sem ele e sem perder tempo.

document.ready

O document.ready, ou simplesmente $(function), é utilizado para executar o JavaScript após o navegador ter compilado o DOM. Fazemos isso pois o JavaScript bloqueia a renderização, mas como estamos falando de alternativas que tal colocar o seu código JavaScript antes da tag ? Dessa forma o DOM já estará compilado.

Caso essa simples ação ainda não resolva o seu problema, o que eu duvido muito, você ainda poderá utilizar o DOMContentLoaded. O DOMContentLoaded é suportado pela maioria dos navegadores.

document.addEventListener("DOMContentLoaded", function(event) {
  //do work
});

querySelectorAll

Anos atrás, quando o jQuery surgiu, ele trouxe uma revolução ao modo de utilizar JavaScript pelo simples fato dele ter simplificado, de forma significativa, a tarefa de selecionar os elementos com os quais queremos trabalhar. Porém o JavaScript evoluiu e hoje nós temos uma maneira igualmente fácil e nativa. É o querySelectorAll que é usado da seguinte forma:

var matches=document.querySelectorAll("div.nota, div.alerta");

Classes

Frequentemente costumamos trabalhar com classes no JavaScript, tanto para selecionar um elemento, quanto para fazer gets e sets do atributoclass em elementos. Normalmente acabamos usando o jQuery. Mas que tal usar as propriedades className e classList?

Formulários

Antigamente para fazer a validação de formulários no navegador nós sempre utilizávamos JavaScript, não existia outra opção. Porém o HTML também evoluiu e atualmente é possível fazer validação de formulários utilizando apenas atributos nos elementos HTML. É possível validar emails com o input do tipo email, definir campos obrigatórios com o atributo required e fazer validações com expressões regulares com o atributo pattern, nos permitindo assim, validar telefones, CPFs, CNPJs, etc.

Animações

O CSS também evoluiu e hoje podemos fazer animações com ele através da propriedade animate, como visto nesse artigo da MDN, e até mesmo utilizar aceleração hardware utilizando o translate3d da propriedade transform como visto nesse artigo do Paul Irish. 
Eu, particularmente, uso bastante essas duas características do CSS3 para deixar as animações nos dispositivos móveis mais fluídas.

Conclusão

Hoje é possível ser produtivo sem utilizar jQuery que embora seja muito prático muitas vezes não é necessário, pois muitas vezes carregamos uma biblioteca inteira para utilizar apenas alguns métodos que já possuem APIs nativas disponíves no JavaScript ou alternativas melhores, mais simples e mais performáticas no HTML e no CSS.

Então sempre que o jQuery não for necessário, evite-o ;)

genymotion2

Emulando aplicativos Ionic/Cordova no Genymotion

Fala pessoal, beleza? Esse é um post rápido pra dar uma dica de algo que descobri hoje. Bom, todo mundo sabe, e não é de hoje, que o emulador android presente no Android Studio é uma porcaria maravilha. E é por isso que grande parte dos desenvolvedores android utilizam o Genymotion como alternativa.

O Genymotion é um emulador rápido e essa palavra “rápido” define ele. Enfim, se você ainda não o conhece e/ou não o utiliza cadastre-se no site www.genymotion.com, faça o download e seja feliz. A utilização dele é muito fácil. É só criar um novo “Virtual Device” e rodar.

E para rodar aplicativos feitos com o Cordova ou Ionic dentro do Genymotion basta rodar seu Virtual Device e executar o código:

ionic run android

Mas por que “run” e não “emulate”?

Isso ocorre pois o Genymotion não notifica o Android/ADB que ele é um emulador. Ele se “apresenta” como sendo um dispositivo e é por isso que nós temos que executar o comando do Cordova para rodar o aplicativo em um dispositivo real, pois assim ele encontrará o Genymotion.

Debugando

Como vocês já sabem, pois leram na documentação, o Ionic Framework é um framework feito para rodar em dispositivos recentes (Android 4+ e iOS 6+) não adiantará criar um virtual device do Galaxy S2 com Android 2.3.6. Particularmente, eu recomendo que criem o virtual device de qualquer dispositivo com Android Kit Kat, pois no Kit Kat o navegador padrão é o Chrome e não mais o Android Browser, logo, a WebView do dispositivo também roda o Chrome.

Faço essa recomendação pois no Chrome é possível debugar sites abertos no navegador remotamente. E isso também serve para aplicativos que usam a WebView. Para inspecionar o dispositivo basta você ir em Menu > Ferramentas > Dispositivos ou abrir uma nova aba no Chrome e digitar:

chrome://inspect

Então ele irá carregar uma página como a seguinte e então é só clicar em “inspect” para começar a trabalhar.

Aba de dispositivos

Ao clicar em “inspect” o Chrome irá abrir o Developer Tools e você terá todos os recursos dele para se divertir.

Inspetor Remoto

Qualquer dúvida quanto a inspeção de dispositivos remotos utilizando o Google Chrome é só acessar esse tutorial.

Captura de Tela 2014-09-23 às 11.38.51

Erro ‘The command “android” failed’ no Ionic Framework

Esse post é uma pequena retificação ao post anterior. E, primeiramente, eu gostaria de agradecer ao Márcio Vinícius por ter me atentado a esses pequenos detalhes que eu deixei passar. Enfim, o nosso problema aqui é que eu esqueci de mencionar que para desenvolver para o Android no Mac OS você precisará do Android SDK. Caso contrário, ao rodar o comando ionic platform add android será retornado um erro como na imagem a seguir:

ionic platform add android error

Como podemos notar pela mensagem de erro retornada, o comando `android” falhou, pois não temos o Android SDK instalado, logo, para instalar e configurar corretamente siga os seguintes passos:

  1. Baixe o Android SDK no link abaixo.

    http://developer.android.com/sdk/index.html

  2. Execute o arquivo sdk/tools/android.

  3. Faça o download da plataforma para o qual você irá desenvolver. Como no exemplo abaixo onde eu faço o donwload da SDK do Android 4.4.2 (API19).
    Android Tools

  4. Abra o terminal e execute o seguinte comando no terminal:

    open ~/.bash_profile

  5. Edite o arquivo com adicionando a linha abaixo, onde DIRETÓRIO_DO_SDK representa o caminho para o SDK.

    export PATH=$PATH:/DIRETÓRIO_DO_SDK/platform-tools/:/DIRETÓRIO_DO_SDK/tools/


    Exemplo:

    export PATH=$PATH:/Users/marciovinicius/Documents/Componentes\ de\ Desenvolvimento/adt-bundle-mac-x86_64-20140702/sdk/platform-tools/:/Users/marciovinicius/Documents/Componentes\ de\ Desenvolvimento/adt-bundle-mac-x86_64-20140702/sdk/tools/

  6. Após salvar o arquivo, rode o seguinte comando no terminal:

    source ~/.bash_profile

  7. Agora, ao executar no terminal o comando ionic platform add android pode ser que você não tenha o ant instalado, então aparecerá o seguinte erro:

    ERROR : executing command 'ant'

    Para solucioná-lo da forma fácil, basta instalar o homebrew e depois o ant rodando os seguintes comandos no terminal:

    ruby -e "$(curl -fsSL https://raw.github.com/Homebrew/homebrew/go/install)"
    brew install ant

E é isso, agora tudo funcionará como deveria. Até mais.

ps.: Ainda não verifiquei no Windows e no Linux, mas provavelmente você precisará efetuar procedimento parecido. Voltarei em breve com a solução para esses sistemas operacionais.

Ionic Framework

Aplicativos mobile com o AngularJS e Ionic

Introdução

Os desenvolvedores web vem a cada dia mais se tornando desenvolvedores mobile. Isso vem acontecendo graças ao surgimento de tecnologias de desenvolvimento de aplicativos mobile hí­bridos, onde o desenvolvedor consegue utilizar as mesmas tecnologias já conhecidas por ele na web para criar aplicativos que rodem em múltiplas plataformas. Não necessitando aprender as linguagens nativas das plataformas mobile.

Atualmente existem várias tecnologias para desenvolvimento mobile onde o aplicativo é portado para diversas plataformas, como o Titanium, o PhoneGap, o Xamarin, o Delphi XE7, etc.

O Ionic Framework é uma dessas tecnologias e vem ganhando destaque nos últimos meses. O Ionic é um framework front-end open source que utiliza o poder do HTML5 e do AngularJS para entregar uma experiência de usuário fluí­da e um rápido desenvolvimento.

Os aplicativos Ionic são baseados no Cordova, logo, os utilitários do Cordova podem ser usados para build, deploy e testes dos aplicativos.

Por que o Ionic?

"Mas por que usar o Ionic se eu posso utilizar o Onsen UI ou o fazer tudo do zero em cima do Cordova?". Existem algumas caracteríticas do Ionic que vão ajudar a responder essa questão:

  1. O Ionic trabalha muito bem com o AngularJS. Os componentes de interface do Ionic são diretivas do AngularJS. Além disso o Ionic utiliza o UI-Router para gerenciar as rotas e estados das views. Ao utilizar o Ionic você pode manter múltiplos históricos de navegação dentro de seu aplicativo, permitindo que você crie aplicativos com navegação não linear.
  2. Todo o CSS é gerado a partir do SASS e foi projetado para ser sobrescrito, tornando-o mais fácil para desenvolvedores personalizarem seus aplicativos. O CSS do Ionic é independente da camada de JavaScript, permitindo uma maior liberdade no desenvolvimento. Ele utiliza um sistema de grids baseado no Flexbox do CSS3, onde é possível criar layouts com qualquer quantidade de colunas e, inclusive, alinhar o conteúdo verticalmente dentro das colunas.
  3. Ele utiliza o Gulp para automatização de tarefas, como compilar o código SASS em CSS.
  4. O framework é obcecado por performance, com uma interface rápida e consistente. Ele utiliza recursos de aceleração de hardware e busca manipular minimamente o DOM.
  5. Não possui depedência do jQuery, embora você possa adicioná-lo caso queira.
  6. Por ser um framework front-end, é possí­vel utilizar os navegadores para o desenvolvimento. Fazendo bom uso das ferramentas de debug presentes nos navegadores é possí­vel desenvolver boa parte dos aplicativos (tudo o que não façaa uso das APIs nativas dos dispositivos móveis).
  7. Comunidade forte e ativa. Como o AngularJS é, atualmente, o framework javascript mais popular entre os desenvolvedores front-end, grande parte desses desenvolvedores optam por utilizar o Ionic e isso acaba fortalecendo cada dia mais a sua comunidade.

Instalação

Para utilizar o Ionic é necessário que você tenha o Node.js instalado.

Após instalar o Node.js é necessário instalar o Cordova e o Ionic através da seguinte linha de comando:

npm install -g cordova ionic

Assim que a instalação estiver completa você pode iniciar um novo projeto utilizando um template. Os templates disponí­veis são: blank, tabs e sidemenu. O primeiro é um template vazio, com o mí­nimo necessário para se ter um aplicativo Ionic, o segundo é um template que possui abas de navegação e o terceiro possui um menu lateral.

Para inicar um projeto utilizando um desses templates é só executar um dos comandos a seguir:

ionic start myApp blank
ionic start myApp tabs
ionic start myApp sidemenu

Onde myApp é o nome do aplicativo que você irá criar, ou seja, você pode substituí­-lo por qualquer outro nome. Poderia ser tableless ou tablelessApp por exemplo.

ionic start tablelessApp sidemenu

Após iniciar o aplicativo você deve adicionar as plataformas para o qual ele será publicado. Lembre-se que para desenvolver para iOS você precisa estar desenvolvendo em um Mac OS.

cd tablelessApp
ionic platform add ios
ionic platform add android

Agora você já pode fazer o build de seu aplicativo e executar ele no emulador da plataforma desejada.

ionic build ios
ionic emulate ios

É assim que seu aplicativo deve estar parecendo agora:

Ionic Side Menu - Home

Conclusão

Neste artigo nós vimos por que utilizar o Ionic Framework e como começar o desenvolvimento com o mesmo. Para que o artigo não fique muito extenso termino o mesmo por aqui, mas voltarei, em breve, com um tutorial onde explicarei como criar um aplicativo utilizando o Ionic.

Entretanto, fique a vontade para explorar as possibilidades do framework através dos links abaixo.

Site: http://ionicframework.com
Tutoriais: http://learn.ionicframework.com
Fórum: http://forum.ionicframework.com
GitHub: http://github.com/driftyco/ionic

Javascript vai resolver tudo mesmo?

Fala galera, meu nome é Diogo. E como proposto pelo Jean, vou falar um pouco mais sobre mim neste primeiro post.

Fui graduando de Engenharia de Software na UFG, porém tranquei o curso em busca de me “autodidatizar” (discussão que quero trazer pra outro post). Desde então tenho estudado vários assuntos, até que me descobri apaixonado pelo Frontend.

Sou desenvolvedor Frontend na Meta Tecnologia. Fã de conhecimento holístico. E curto muito ler quando não estou programando. Além de ter idéias horríveis todos os dias.


A “nova era” do desenvolvimento web

Bom, eu já tinha um post semi-pronto sobre Web Storage. Porém, um podcast¹ que eu escutei hoje (13/08) me inspirou a escrever esse post. E me fez pensar bastante sobre o seguinte assunto: “Estamos mesmo usando Javascript da forma certa?”

Desde 2006-07 com a popularização de bibliotecas como jQuery e YUI, até hoje em dia com a evolução destas para os frameworks MV* (model-view-whatever) como Angular, Ember, Backbone, ExtJS, fora o uso de JS no servidor. Muitas das atividades, antes designadas ao backend, foram transferidas para o frontend. Por vários motivos, tais como: facilidade de desenvolvimento, performance, menor consumo de banda, entre outras.

No podcast, Nicholas C. Zakas (@slicknet) comenta sobre esse crescimento da “cultura do javascript” e levanta 2 pontos importantes:

  1. JS é a melhor solução para o meu problema?

  2. Qual o peso de usar uma ou várias bibliotecas javascript? E o que fazer para diminuí-lo?
     

Entender o problema é a melhor solução

 

No primeiro ponto abordado, é discutida a real necessidade do uso de bibliotecas/frameworks JS nas aplicações. O entrevistado fala da “jqueryzação” do desenvolvedor, citando a frase: “Bom, eu tenho esse problema. Como eu vou usar jQuery pra resolvê-lo?”. Ele critica o modo com muitos desenvolvedores não estendem os limites impostos pelas bibliotecas usadas, como criar plugins, forks, etc.

Outro argumento utilizado é o de que já existem tecnologias que fazem as mesmas coisas, no backend, por exemplo. E que podemos usar de Progressive Enhancement (melhoria progressiva) com Javascript para melhorar a experiência do usuário.

Eu divirjo um pouco dessa opinião. Pois penso que essa cultura de estender as bibliotecas tem crescido bastante. Muito pelo fato de que o GitHub (a.k.a: presença open-source) dos desenvolvedores tem se tornado uma espécie de currículo na visão de muitas empresas.

Porém, concordo com o fato de que JS deve ter uma abordagem de Progressive enhancement². O fato de se ter uma stack toda em Javascript é bastante atraente e resolve boa parte dos problemas. Mas nem todos eles exigem uma baita interface rica, ou uma ótima performance. Ou seja, conforme a necessidade surgir, a solução deve ser implementada.
 

Optei por Javascript, e agora?

 

Um dos principais problemas que surgem quando usamos javascript, principalmente no browser, é o excesso de alternativas.

Por exemplo, hoje eu preciso de uma lib para navegar na DOM, amanhã de widgets, depois de promises, autocomplete, etc. Além do meu próprio código, que faz o projeto realmente funcionar. Chegará um dia em que eu terei arquivos demais, consequentemente mais tempo de carregamento.

Para melhorar esse problema de carregamento, o Nicholas fala sobre os quatro tempos de carregamento no browser (os quais você pode se aprofundar mais nos slides³ da palestra que ele deu sobre o assunto).

Dentre eles, o que mais me chamou a atenção é o quarto: “On demand”. Neste tipo de abordagem, nós devemos pensar em como o cliente usará a aplicação.

Um bom exemplo citado no podcast, é de uma página de produto da Amazon.

 

amazon

 

  • Qual deve ser o primeiro passo do usuário logo após ter aberto a página? (assumindo que ele veio de uma pesquisa)

  1. Prioritariamente o botão “Add to Cart”, pois, se o usuário gostar do produto, essa será a primeira ação a ser tomada.

  2. Se o usuário não quiser o produto, provavelmente ele vai querer fazer outra pesquisa. Então, por exemplo, o autocomplete da pesquisa, não precisa estar carregado junto com a página. Podemos atrasar um pouco seu carregamento.

  3. O botão “Sell on Amazon”, por ser menos usado, pode ter sua funcionalidade carregada quando o mouse estiver a uma certa distância dele, por exemplo.

Só neste pequeno exemplo, nós economizamos o carregamento de 2 scripts. A partir daí, nós podemos viajar e pensar melhor em outras formas de trazer o mínimo viável de arquivos para o funcionamento da página. Tudo isso com base no comportamento do usuário. Achei isso muito foda e pretendo usar nos meus próximos projetos.
 

Conclusão

Apesar de causar xiismo e polêmica em muitos casos. Acho muito válidas as discussões sobre o uso ou não das tecnologias. Pois muita gente defende muito tecnologias em si, e não a solução para o problema.

Pra quem tiver um bom nível de inglês eu recomendo que escute o podcast, pois há outras discussões que eu não citei aqui. E espero que vocês tragam suas opiniões nos comentários, para que a gente possa discutir melhor sobre o assunto.

 

Referências

¹ Hanselminutes #383: Enough With The JavaScript Already! with Nicholas Zakas?
² Progressive enhancement is still important
³ Enough with the Javascript already!

 

Senha

Balanceando segurança e experiência do usuário

Oi, eu sou o Jean e antes de começar esse primeiro post do blog eu me sinto no dever de fazer uma breve apresentaçao.
 

Bom, eu sou graduando de Sistemas de Informação na UFG e trabalho no LabTIME/UFG e na Monodois Comunicação, além de ter vários projetos pessoais que, assim como muitos dos projetos por aí, estão demoram a sair do papel.

 

E a ideia de criar um blog partiu de uma conversa minha com o Márcio Sena, que também trabalha comigo no LabTIME/UFG e irá se apresentar por aqui futuramente, e a idéia basicamente é compartilhar nosso conhecimento e nos ajudar a buscar mais conhecimento.

 

A partir daí eu convidei mais dois colaboradores, o Diogo César e o Clóves Cardoso, que se também se apresentarão futuramente, e a partir daí decidimos auxiliar a disseminar as tecnologias frontend e um pouco de UX para a comunidade.

 

E é isso, espero que gostem.

 


Ajudando a atrapalhar o usuário

 

Eu não sou o único a sofrer quando digito uma senha e o único feedback recebido são um monte de bolinhas. Muitos usuários sofrem do mesmo mal e é normal, afinal nem sempre temos a certeza de termos digitado a senha corretamente. E o problema tende a piorar nos famosos "Digite sua senha novamente".

 

De modo geral o ato de mascarar as senhas é uma convenção de segurança definida anos atrás e que foi criada para evitar que "bisbilhoteiros" roubassem as senhas dos usuários mais descuidados. E embora seja uma boa prática de segurança pode comprometer a experiência do usuário, principalmente nos dispositivos móveis, onde a digitação é comprometida pela falta de espaço entre os caracteres do teclado.

 

Quando mascaramos as senhas nós criamos, basicamente, dois problemas:

 

  • Os usuários cometem mais erros, pois eles não conseguem ver o que estão digitando e, por isso, se tornam menos confiantes. Tornando-se mais propensos a desistirem da ação.

  • A incerteza que o usuário sente com relação ao que foi digitado faz com que o usuário busque formas alternativas de "burlar" o sistema, como empregar senhas excessivamente simples e/ou copiar senhas de arquivos em seus computadores. Ambas as condutas levam a uma perda real de segurança.

 

No entanto, deixar as senhas sem máscaras podem oferecer um risco real aos usuários, pois sempre há a possibilidade deles estarem sendo espionados por um "bisbilhoteiro". Principalmente nos formulários de login, pois essa é uma ação que se repete várias vezes, ao contrário dos formulários de cadastro. No caso dos formulários de cadastro mascarar as senhas podem criar mais problemas ao usuário do que realmente valem a pena. A segurança proporcionada pelas máscaras nesse caso muitas vezes é inútil, já que normalmente as pessoas não se cadastram em sites com outras pessoas bisbilhotando.


 

Solução

 

Uma solução plausível é o desmascaramento de senhas que pode ser realizado quando o campo do formulário estiver em foco ou quando um checkbox estiver marcado por exemplo. Isso fica a critério do desenvolvedor.

 

Cases

 

Recentemente o Windows 8 foi lançado e junto com ele o Internet Explorer 10 e ambos possuem um recurso de desmascaramento de senhas quando se mantém pressionado um signo (botão), como podem ver abaixo.

Alguns aplicativos para dispositivos móveis já implementaram o mesmo recurso. É o caso do Polar e do LinkedIn como se pode ver nas imagens abaixo.




 

Extra: hideShowPassword Plugin

 

O pessoal do Cloud Four concorda comigo e como não conseguiram encontrar nenhum plugin javascript que realizasse o desmascaramento de forma otimizada para dispositivos touchscreen então eles criaram um.

 

hideShowPassoword no Github

Demo

O hideShowPassword necessita do jQuery ou do Zepto.js e funciona de forma muito fácil e tudo o que você precisa fazer é alterar a visibilidade do campo de senha através dos métodos:
 

$('#password').showPassword();     // Exibir

$('#password').hidePassword();     // Esconder

$('#password').togglePassword();     // Alternar

 


Conclusão

 

Seguir as convenções de design é geralmente o aconselhável, mas quando essas convenções começam a dificultar a vida dos usuários então elas precisam ser repensadas. A segurança deve ser equilibrada com a experiência do usuário. E ao meu ver mascarar as senhas é uma convenção errada e eu sou a favor de desmascarar as senhas temporariamente a fim de otimizar a experiência do usuário, tendo em vista que isso não prejudica consideravelmente a segurança.


Referências

Stop Password Masking
Better Password Masking For Sign-Up Forms
Hide/Show Passwords: The Missing Plugin