Turbinando o client-side com




Tiago Romero Garcia

Quem sou?

Tiago Romero Garcia

Gerente Técnico na Avenue Code
Líder Técnico de Front-End
Desenvolvedor Full-Stack

@tiagooo_romero
tgarcia.com.br
github.com/tiagorg

Meu trabalho

  • Metodologias ágeis
  • Nearshoring
  • English as official language
  • Ambiente inovador
  • Viagens internacionais


www.avenuecode.com.br
Be part of the BEST!

Há muito tempo atrás, em uma galáxia muito,
muito distante....

É tempo de guerra dos navegadores. Desenvolvedores rebeldes, atacando de uma base escondida, tiveram sua primeira vitória contra o temível Império da Microsoft.

Durante a batalha, espiões rebeldes conseguiram roubar os planos da arma definitiva do Império, o INTERNET EXPLORER 6, um navegador armado com poder suficiente para destruir uma conexão de Internet por completo.

Perseguido pelos agentes sinistros do Império, nossos heróis correm contra o tempo para diminuir o tempo de resposta e melhorar a navegação web para salvar os usuários e restaurar a liberdade na galáxia....

Agenda

  • Javascript e o Hiperespaço
  • Arquitetura web
    • Client-side x Server-side
    • REST
    • JSON
    • MVC
    • Aplicações no client-side x Frameworks web

Agenda

  • Backbone.js
    • Model
    • Collection
    • View
    • Router
    • Templates dinâmicos

Javascript e o Hiperespaço

  • Hiperespaço: uma dimensão acima
  • Somente enxergamos até a dimensão máxima atual
  • Considere 3 dimensões para um navegador:
    • Renderização gráfica: HTML/CSS
    • Elementos: DOM
    • Comportamento: JS
  • A quarta dimensão é seu hiperespaço. Como seria?

Arquitetura web

  • Partes da aplicação:
    • Front-end: interage com o usuário
    • Back-end: contém lógica de negócio e acesso aos dados/serviços
  • Lados da aplicação:
    • Client-side: roda no navegador/dispositivo do usuário
    • Server-side: roda em um servidor

NÃO SÃO A MESMA COISA!

Client-side x Server-side

  • Aplicações web isoladas no client-side:
    • Somente front-end. Ex: "Calculadora IMC"
    • Front-end e back-end. Ex: "Controle de tarefas" salvando no local storage do navegador

Client-side x Server-side

  • Client-side integrado com server-side:
    • Front-end no client-side, back-end no server-side. Resposta HTTP trafegando HTML. Ex: "Controle de tarefas" em framework web (Struts, JSF, Rails ou ASP.NET MVC)
    • Front-end e back-end no client-side, back-end no server-side. Resposta HTTP trafegando dados. WTF???

REST

  • REpresentational State Transfer
  • Estilo arquitetural stateless para sistemas distribuídos, baseado no protocolo HTTP:
    • Métodos HTTP são verbos (ações)
    • URIs são substantivos (recursos)
    • Códigos de status HTTP são resposta das ações, como 200 (ok), 404 (not found), 500 (internal server error)

REST

  • Ações REST abordadas hoje:
    • HTTP POST: criar recurso. Ex:  POST /users cria um usuário (passando seus dados no corpo da requisição)
    • HTTP GET: ler recurso. Ex:  GET /users/1 recupera o usuário com id = 1
    • HTTP PUT: alterar recurso. Ex:  PUT /users/1 altera o usuário com id = 1 (passando seus dados no corpo)
    • HTTP DELETE: remover recurso. Ex:  DELETE /users/1 remove o usuário com id = 1

JSON

  • JavaScript Object Notation
  • Formato universal de transmissão de dados JavaScript
  • Tamanho reduzido, formato simplificado, fácil de interpretar -> boa alternativa ao XML

{
  "name": "R2-D2",
  "owners": ["Anakin", "Leia", "Luke"],
  "attributes": {
    "height": 0.96,
    "mass": 32
  }
}
					

MVC

  • Model-View-Controller
  • Padrão de projeto arquitetural que encoraja uma melhor organização da aplicação através da separação de interesses:
    • Model: dados de negócio
    • View: interface com o usuário
    • Controller: lógica de conexão e entrada de dados

MVC em JavaScript

  • Evita códigos “macarrônicos” (difíceis de ler e manter por não apresentarem estrutura)
  • Manutenção geral facilitada, mudanças localizadas
  • Agora é possível fazer testes unitários objetivos
  • Modularidade permite dividir melhor as tarefas entre desenvolvedores

MVC É O NOSSO HIPERESPAÇO!!

Aplicações no client-side x Frameworks web

  • Frameworks web:
    • Ciclo de vida de cada ação é gerenciado e roteado no server-side
    • Template no server-side gera conteúdo HTML
    • Resposta HTTP trafega HTML
    • Cada ação gera uma recarregamento de página
    • Ações são síncronas

Aplicações no client-side x Frameworks web

  • Aplicações no client-side:
    • Ciclo de vida de cada ação é gerenciado e roteado no client-side
    • Resposta HTTP trafega dados (JSON, XML, etc...)
    • Template no client-side gera conteúdo HTML
    • Cada ação não gera uma recarregamento de página
    • Ações podem ser assíncronas

Backbone.js

  • Biblioteca JavaScript que fornece estrutura para aplicações client-side, baseado em APIs REST com JSON
  • Criada em 2010, hoje é usada em grandes sites como Airbnb, BitTorrent, Digg, Foursquare, Hulu, LinkedIn mobile, Pinterest, Trello, Walmart, Wordpress
  • Dependente de Underscore.js e jQuery

Backbone.js

  • SPA (Single-Page Application): estilo arquitetural que carrega uma única página para a aplicação
  • Elementos: Model, Collection, View e Router

O BACKBONE.JS NÃO É UM FRAMEWORK MVC CLÁSSICO...

...MAS É DA FAMÍLIA MV*, COM OS MESMOS OBJETIVOS!!

Model

  • Armazena e manipula dados
  • Comunica com API REST
  • Suporta parsing, conversão, validação e processamento de lógica de negócio

var CardModel = Backbone.Model.extend({
  urlRoot : '/api/cards'
});
							
  • urlRoot especifica a URL base para as chamadas REST

Model

  • Métodos REST:
    • fetch(options): recupera uma entidade por HTTP GET
    • save(attributes, options): cria uma entidade por HTTP POST (se objeto não possuir id) ou altera uma entidade por HTTP PUT (se objeto possuir id)
    • destroy(options): remove uma entidade por HTTP DELETE

Model

  • Parâmetros:
    • attributes: objeto contendo os dados a serem salvos
    • options: objeto contendo configurações como:
      • url: URL de conexão com o server-side, ignorando urlRoot
      • success: Função callback para resposta de sucesso
      • error: Função callback para resposta de erro ou timeout

Model


var model = new CardModel({
  id: 1
});

// GET /api/cards/1
model.fetch({
  success: function(model, response, options) {
    console.log('Sucesso no fetch! Model = ' + model.toJSON());
  },
  error: function(model, response, options) {
    console.log('Erro ou timeout no fetch.');
  }
});
							

Model

  • Outros métodos:
    • get(attribute): Obtém o valor de um dado do Model. Ex: card.get('title');
    • set(attribute, value): Define um valor para um dado do Model. Ex: card.set('title', 'Projeto X');
    • toJSON: Retorna uma cópia dos dados do Model em JSON. Ex: card.toJSON();

Collection

  • Lista ordenada de Models
  • Instancia Models a partir de um array de JSON
  • Implementa métodos de arrays do Underscore.js

var CardCollection = Backbone.Collection.extend({
  model : CardModel,
  url : '/api/cards'
});
							
  • model especifica o Model manipulado
  • url especifica a URL base para as chamadas REST

Collection

  • Collections complementam a API REST dos Models com este método:
    • fetch(options): recupera um array de entidades por HTTP GET, popula cada entidade destas como um Model e a insere na Collection

Collection


var cardCollection = new CardCollection();

// GET /api/cards
cardCollection.fetch({
  success: function(collection, response, options) {
    console.log('Sucesso no fetch! Collection = ' + collection.toJSON());
  },
  error: function(collection, response, options) {
    console.log('Erro ou timeout no fetch.');
  }
});
							

Collection

  • Outros métodos:
    • get(id): Obtém um Model a partir de seu id. Ex: collection.get(12);
    • at(index): Obtém um Model a partir de sua posição na Collection. Ex: collection.at(1);
    • add(model): Adiciona um Model na Collection. Ex: collection.add({'title', 'Projeto X'});
    • remove(id): Remove um Model da Collection. Ex: collection.remove(12);

Collection

  • Outros métodos:
    • toJSON: Retorna uma cópia dos dados da Collection em JSON. Ex: collection.toJSON();
    • where(attributes): Retorna apenas os elementos da Collection que corresponderem ao critério especificado. Ex: collection.where({'type', 'PROJECT'});
    • pluck(attribute): Retorna um array com o valor de um determinado atributo extraído de cada elemento da Collection. Ex: collection.pluck('title');

View

  • Gerencia a lógica de apresentação e os eventos
  • Renderiza um template HTML que pode ser adicionado à DOM, consumindo dados de Models/Collections
  • O template HTML pode ser gerado dinamicamente.

View

  • Elementos principais a serem implementados:
    • events: objeto mapeador de eventos, da forma:
      'seletor CSS': função / 'nome_de_função'
    • render(): método que concentra toda a lógica da View, realizando três etapas:
      • Obtenção do template HTML
      • Renderização do template HTML, consumindo um Model ou Collection
      • Inserção do resultado da renderização no elemento el

View

  • Outros elementos da View:
    • el: elemento HTML renderizado por esta View. Pode ser acessado via $el como um objeto jQuery
    • id: O atributo id de el
    • className: O atributo class de el
    • tagName: A tag HTML a ser utilizada por el
    • remove(): Remove a View da DOM e remove listeners de eventos associados

View


var CardView = Backbone.View.extend({
  events: {
    'click button.close': function(e) {
      e.preventDefault();
      this.remove();
    }
  },
  render: function() {
    var result = '

' + this.model.toJSON().title + '

' + ''), this.$el.html(result); } });

View

  • Parâmetros da View:
    • el: pode ser passado um elemento HTML existente para receber conteúdo renderizado pela View
    • model: O Model a ser consumido por render()
    • collection: A Collection a ser consumida por render()

View


var cardModel = new CardModel({ id: 1 });

cardModel.fetch({
  success: function(model, response, options) {
    var	cardView = new CardView({
      model: cardModel
    );
    cardView.render();
    $('#contents').append(cardView.el);
  },
  error: function(model, response, options) {
    console.log('Erro ou timeout no fetch.');
  }
});
							

Router

  • Permite a livre manipulação e roteamento de URLs
  • Controla o histórico de navegação
  • Evita requisições diretas ao server-side
  • Elemento principal:
    • routes: objeto mapeador de rotas, da forma:
      'seletor CSS': função / 'nome_de_função'

Router

  • Outros elementos:
    • route(path, name): método que também insere uma rota, mas pode utilizar expressões regulares. Ex: router.route(/^card/(\d+)$/, 'viewCard');
    • navigate(path, options): método que navega para uma URL. Para também executar a rota, utilize options como {trigger: true}. Ex: router.navigate('/card/32',{trigger: true});

Router


var AppRouter = Backbone.Router.extend({
  routes : {
    '' : 'viewAll',
    'card/:id' : 'viewCard',
    '*path' : 'viewAll'
  },

  viewAll: function() { ... },

  viewCard: function(id) { ... }
});
							

Router

  • É necessário chamar a função Backbone.history.start() para iniciar o monitoramento das rotas pelos Routers
  • Passe {pushState: true} para usar o pushState do HTML5. Senão, o roteamento usará # no final da URL

var appRouter = new AppRouter();

Backbone.history.start({
  pushState : true
});
							

Templates dinâmicos

  • O template HTML pode ser gerado por qualquer biblioteca como Underscore.js, Mustache, Handlebars.js, dust.js, etc...
  • Mesma idéia do PHP, JSP, ERB, ASP - porém no client-side
  • Mais mantenível que strings concatenadas

Templates dinâmicos

  • Handlebars.js: alternativa performática, flexível e fácil de aprender e manipular

{{#if children}}
  
    {{#each children}}
  • {{title}}: {{description}}
  • {{/each}}
{{else}}

Não há itens!

{{/if}}

Conclusão

  • Aplicações no client-side buscam reproduzir a experiência do desktop na web
  • Aplicações no client-side conseguem reduzir drasticamente a espera do usuário por um feedback
  • Assim, aumentam-se as chances de sua permanência no sistema
  • O Backbone.js é uma alternativa madura MV* para estruturar aplicações no client-side

Saiba mais

Dúvidas?