BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Aplicações móveis com HTML5 e JavaScript: um exemplo completo com frameworks e arquitetura MVC

Aplicações móveis com HTML5 e JavaScript: um exemplo completo com frameworks e arquitetura MVC

Pode-se criar uma interface rica para aplicações de forma nativa ou utilizando HTML5 e JavaScript. Aplicações nativas podem oferecer uma experiência mais rica para os usuários, mas podem levar mais tempo e ser mais caras de desenvolver para vários sistemas operacionais. As tecnologias HTML5 e JavaScript abrirão a porta para as interfaces independentes de dispositivo. Isso significa que as interfaces com o usuário podem ser criadas utilizando bibliotecas de componentes JavaScript que renderizam componentes visuais utilizando elementos do HTML5. O HTML5 traz novas funcionalidades que suportam a mobilidade e o desenvolvimento de interfaces ricas.

Este artigo apresenta frameworks e estruturas usadas para implementar o lado cliente das aplicações móveis com base em JavaScript e HTML5. A interface com o usuário e os elementos de navegação são todos componentes renderizados no navegador, enquanto os servidores de aplicações têm somente o papel de fornecer acesso aos dados JSON para a interface com o usuário. Como a intenção aqui é fornecer uma arquitetura de referência, o exemplo implementa apenas algumas funcionalidades básicas.

Considerações sobre o desenvolvimento móvel

Muitas abordagens para desenvolver aplicações para navegadores desktop podem ser utilizadas nas aplicações baseadas em navegadores móveis. No entanto, as aplicações móveis apresentam desafios não existentes nos navegadores para desktop.

Considere por exemplo as resoluções de tela. As dimensões bem menores das telas exigem um design de interfaces diferente para otimizar a interação do usuário com a aplicação. O HTML5, juntamente com uma biblioteca de componentes de interface gráfica móvel como o jQuery Mobile, fornece um modo independente de dispositivo para criar interfaces móveis com JavaScript. Veja a seguir uma lista criada com o jQuery Mobile:

Essa interface com usuário é renderizada utilizando o identificador de papéis (role identifier) do HTML5, além de CSS. Abaixo está um trecho do código usado para implementar a lista. Note o atributo data-role, utilizado pelo jQuery Mobile para renderizar um componente visual amigável a dispositivos móveis.

<div id="stockListContainer" data-role='content'>
           <ul data-role="listview" id='tcStockList' data-inset="true" data-filter="true"></ul>
</div>

A conectividade é outra questão fundamental. Embora as redes 3G e wi-fi sejam hoje comuns, a conectividade não pode ser considerada como sempre disponível. Felizmente, o HTML5 tem funcionalidades de cache, permitindo que recursos do site possam ser armazenados localmente e controlados de modo desconectado. O caching é habilitado adicionando-se o seguinte elemento HTML em nível de raiz:

<!DOCTYPE HTML>
        <html manifest="cache.manifest">
                  <body>
                  ...
                  </body>
        </html>

Os arquivos de manifesto são arquivos textuais que definem quais recursos serão armazenados, além de diretivas que controlam os recursos que podem "pular" o cache, ou o que mostrar quando o recurso não está disponível. Atualizações e notificações de cache também podem ser controlados quando o arquivo muda, ou através de uma API JavaScript. A seguir, é apresentado um exemplo de arquivo manifest:

CACHE MANIFEST
# 2012-27-18:v1

# Explicitly cached resources.
CACHE:
index.html
css/stylesheet.css
Images/logo.png
scripts/main.js

# White Listed Resources, requires connectivity, will bypass cache
NETWORK:
http://api.twitter.com


# offline.html will be displayed, if *.HTML are not available.
FALLBACK:
*.html /static.html

Além disso, o HTML5 fornece um mecanismo que armazena os dados do lado do servidor localmente para operações desconectadas, e também para ganho de desempenho. Um mecanismo de armazenamento local de 5 MB baseado em chave/valor está disponível para armazenar strings ou objetos JSON transformados em strings. O exemplo a seguir mostra como um Backbone.Collection de objetos Stock podem ser armazenados e recuperados localmente como uma string do JSON.

var d = JSON.stringify(data);
localStorage.setItem('STOCKS', d);

var d = localStorage.getItem('STOCKS');
data = JSON.parse(d);

As aplicações também podem ser construídas para notificar o usuário da "falta de conectividade" e intermediar as requisições de acesso aos dados que serão enfileiradas em um repositório local de chave/valor, que é padronizado nos navegadores que suportam o HTML5. Quando a conexão é restaurada, os objetos que foram armazenados localmente são enviados para o servidor.

O uso de largura de banda é outra preocupação. Minimizar as requisições ao servidor e o tamanho da carga podem ser suportados usando a AJAX; há dependência do servidor somente para acesso aos dados usando JSON. O JSON é muito mais eficiente e sucinto que XML ou protocolos baseados em SOAP.

Arquitetura de aplicações HTML5

O JavaScript nunca foi pretendido como linguagem uso geral para criação de aplicações. Seu objetivo original era aprimorar a experiência dos usuários nos navegadores, permitindo que HTML dinâmico fosse renderizado e alterado sem se ter que acessar um servidor remoto; isso oferecia melhora de desempenho perceptível e real. Os dispositivos móveis não têm todo o poder de processamento ou o acesso a largura de banda dos navegadores desktop, então as interfaces de usuário ricas precisam minimizar as idas e vindas ao servidor implementando o que for possível com elementos JavaScript e HTML5 no lado cliente.

Isso é bem diferente do que é feito em aplicações web do lado servidor (JSP/ASP/PHP), em que elementos dinâmicos de HTML são renderizados no servidor. Na nova topologia, os elementos do lado do servidor suportam a autenticação e requisições de acesso a dados, e a interação com o usuário e muita lógica de aplicação fica no navegador do cliente. Isso pode ser visto na figura a seguir:

Além disso, por usarmos uma linguagem dinâmica e fracamente tipada, (que permite closures e a habilidade de tratar blocos de código como tipos de dados), ganhamos muita flexibilidade na programação. Mas, isso pode levar a um código difícil de manter. Assim, precisamos ser rigorosos ao criar aplicações baseadas em JavaScript. A lista a seguir apresenta técnicas gerais que precisam ser postas em prática:

  • Navegação
  • Acesso a dados remotos
  • Autenticação e Autorização
  • Desacoplamento da visão do modelo da aplicação (padrão MVC)
  • Modularização / Empacotamento
  • Gerenciamento de dependências
  • Registro em logs/ Rastreamento
  • Tratamento de exceções

No mundo do Java, há frameworks que auxiliam a criação de arquiteturas em camadas. Do mesmo modo, há frameworks disponíveis no mundo do JavaScript para auxiliar o uso de uma arquitetura em camadas. Para aumento de facilidade de manutenção e estabilidade, os seguintes frameworks são usados para ajudar a forçar uma arquitetura modular dividida em camadas e orientada a objetos:

Backbone.js

O Backbone fornece uma maneira orientada a objetos para separar e aplicar o padrão Model View Controller (MVC) nas aplicações JavaScript. As interfaces com o usuário em HTML5 são separadas do controle e das implementações dos objetos do modelo. Além disso, é fornecido um mecanismo de navegação padrão entre as funcionalidades da interface.

Require.js

O Require.js é um framework para carregamento de arquivos e módulos JavaScript, o qual permite que as dependências de código JavaScript sejam carregadas e validadas conforme solicitados por um módulo ou função JavaScript. O framework também informa para o desenvolvedor erros de dependências, quando um módulo ou biblioteca JavaScript não pôde ser carregado.

Underscore.js

O Underscore.js é uma biblioteca que disponibiliza métodos utilitários para permitir que mecanismos de programação funcional sejam aplicados às coleções de objetos. Também oferece a funcionalidade de templates HTML.

JQuery

Biblioteca utilizada para acessar e manipular elementos DOM do HTML.

jQuery Mobile

Biblioteca de componentes de interface com o usuário em HTML5, que oferece um conjunto de controles renderizados em HTML5 e mecanismos para o tratamento de eventos e da aparência da aplicação.

khsSherpa

Trata-se de um framework de servidor de aplicações, em Java, que oferece acesso remoto a objetos Java por meio de requisições HTTP. Oferece suporte a autenticação baseada em tokens, por meio do empacotamento automático de tipos Java para objetos JSON; opcionalmente habilita o suporte entre domínios diferentes com JSONP.

Estrutura de pastas para JavaScript

O JavaScript não fornece uma maneira padronizada de organizar os elementos de programação, que são apenas arquivos de texto com extensão .js. Outras linguagens fornecem mecanismos para organização, como os pacotes de Java ou Namespaces de C#. Tentar definir todas as funções e objetos JavaScript em um grande arquivo único dificultará a manutenção, especialmente quando grande parte de aplicação é definida no JavaScript. Portanto, as pastas de arquivos do sistema podem ser criadas na pasta raiz, para particionar os fontes por áreas de responsabilidade.

As pastas irão conter elementos os JavaScript do MVC da aplicação. A imagem anterior apresenta um exemplo de estrutura de pastas. Suponha que essas pastas estejam localizadas dentro da pasta raiz do servidor web ou servidor de aplicações.

Suporte a modularidade

O JavaScript não tem mecanismos internos para particionar os elementos de código fonte, diferentemente de outras linguagens como o Java, novamente, com seus packages e o C# com seus Namespaces. No entanto, as aplicações JS podem importar e incluir diretivas para trazer dependências. Isso permite a modularização dos códigos das aplicações e frameworks, aprimorando a manutenção e o reuso.

O framework Require.js fornece um mecanismo eficiente para particionar e tratar os arquivos JavaScript como módulos; tem também habilidade de definir, importar e acessar dependências.

O Require.js usa o framework Asynchronous Module Definition (AMD) para realizar a definição e carregamento de dependências. A função "require" do AMD para carregar os módulos tem sua sintaxe apresentada a seguir:

define([modules], factory function);

Cada módulo é um arquivo JavaScript individual que define um objeto JavaScript. Quando invocado, os módulos são carregados e uma instância de objeto é criada e passada para uma função de fábrica (factory) para uso do desenvolvedor. O exemplo a seguir mostra um módulo JavaScript usando a função define() do Require.js, para carregar a dependência utilitária:

define(["util"], function (util) {
          return {
          date: function(){
                      var date = new Date();
          return util.format(date);
            }
      };
});

O Require também tem funcionalidades de otimização com o objetivo de minimizar o carregamento de arquivo e aumentar o desempenho.

Backbone MVC

O Backbone MVC permite a implementação do popular padrão de projeto MVC usando JavaScript. Tipicamente, as aplicações web implementam esse padrão com o objetivo de usar as tecnologias de geração de HTML dinâmico no lado do servidor, como o JSP ou algum mecanismo de templates de HTML. O Backbone MVC fornece componentes ou abstrações para processar as entradas do usuário e aplicar os modelos de objetos da aplicações ao mecanismo de HTML dinâmico. O framework fornece uma maneira para usar esses mecanismos com JavaScript, em vez de gerar tags HTML no servidor.

Templates HTML

A camada de visão (view) do Backbone é simplemente um arquivo HTML estático com a aplicação dos papéis do HTML5. O Backbone fornece um mecanismo de templates, então esses atributos de modelos podem ser aplicados no HTML quando a camada de visão for renderizada por uma visão/controle. A aplicação de exemplo define uma lista na tela com o JQuery Mobile, que é definido com os papéis de atributos do HTML5. A tela HTML5 stock-list.html é mostrada a seguir:

<div id="stockListContainer" data-role='content'>
          <ul data-role="listview" id='tcStockList' data-inset="true" data-filter="true"></ul>
</div>

As ações na lista são definidos no stock-list-item.html. Aplicando o mecanismo de templates do Backbone para apresentar os detalhes do objeto de modelo de ação (stock). O HTML com os elementos de templates é mostrado a seguir:

<a href='#<%=ticker%>'>
          <h4><%= ticker %></h4>
          <p><%= name %></p>
          <p>Price: <%= price %></p>
</a>

Note que as expressões de templates são similares às páginas JSP e ASP, nas quais <%= %> são usados para marcar locais a serem atualizados com valores de atributos de um objeto JSON. Os templates HTML são localizados na pasta template.

Visão/Controlador

Uma visão (view) HTML é renderizada navegando até uma implementação de controlador (controller) do Backbone. Os controles ligam os objetos JavaScript a uma tela HTML e informam para o framework renderizar a camada de visão com a definição e tratamento dos eventos. Na terminologia do Backbone, as visões são controles e a criação das visões no Backbone são feitas estendendo o objeto Backbone.View do framework.

A seguir é apresentado um exemplo parcial para o controlador de visão stockListPage.js, no qual primeiro carregamos os arquivos JavaScript necessários usando o framework require.js. Este último invoca a função JavaScript define([modules,...], controller()) e retorna uma função do controlador de visão do Backbone. Note que essa função estende o objeto Backbone.View.

Um aspecto interessante do framework Require é a função Define, responsável por carregar as dependências dos módulos necessários através da implementação do controlador de visão. Observe que os módulos de modelo e do template HTML são também fornecidos pelo objeto do módulo de visão/controlador:

define([
                'jquery',
                'backbone',
                'underscore',
                'model/stockListCollection',
                'view/stockListView',
                'text!template/stock-list.html'],
                function($, Backbone, _, StockListCollection, StockListView, stockListTemplate) {var list = {};
                            return Backbone.View.extend({
                                      id : 'stock-list-page',

Quando uma instância da visão/controlador é criada: a função initialize é invocada. Ela fornece uma maneira para definir eventos e inicializar o modelo de controlador, que pode ser um objeto individual ou uma coleção de objetos.

Note no exemplo que na função initialize da visão/controlador de stockListPage.js, é criado um objeto StockListCollection. As coleções são também oferecidas pelo Backbone, através de objetos que fornecem uma maneira de gerenciar "coleções" de modelos de objetos JavaScript para a camada de visão. Quando esse controlador é invocado, o método initialize() é executado. Quando uma instância é criada, são utilizados os seletores jQuery para aplicar os tratamentos de eventos do Backbone aos botões. A seguir temos o trecho de código da função initialize():

var list = {};
return Backbone.View.extend({
          id : 'stock-list-page',
          initialize : function() {
                    this.list = new StockListCollection();

                    $("#about").on("click", function(e){
                              navigate(e);
                              e.preventDefault();
          e.stopPropagation();
                   & amp;nbsp;          return false;
                    });


                    $("#add").on("click", function(e){
                              navigate(e);
                              e.preventDefault();
          e.stopPropagation();

                  &nb sp;           return false;
                    });


          },

Os eventos são associados ao método da visão/controlador, através da associação do evento do formulário e um seletor jQuery com um nome de método. O exemplo a seguir apresenta o evento e métodos de tratamento para a aplicação de exemplo e adiciona botões para a lista de ações da página. Os comandos de navegação são discutidos na próxima seção.

events: {
 "click #about" : "about",
 "click #add" : "add",
},
about : function(e) {

window.stock.routers.workspaceRouter.navigate("#about",true);
          return false;
},

add : function(e) {
                    window.stock.routers.workspaceRouter.navigate("#add",true);
          return false;
},

Um template de visão/controlador em HTML é renderizado e apresentado quando o método render() é enviado para uma instância. A função render de stockListPage.js é apresentada a seguir. O template é compilado e então mostra um template HTML que é aplicado para os controladores do atributo el. O atributo this.el é a localização do controlador no DOM no qual o HTML será inserido. A seguir, note que outra visão/controlador é instanciada e renderizada. O StockListView controla a renderização da lista de ações com o jQuery Mobile.

          render : function(eventName) {
                    var compiled_template = _.template(stockListTemplate);
                    var $el = $(this.el);
                    $el.html(compiled_template());
                    this.listView = new StockListView({
                              el : $('ul', this.el),
                              collection : this.list
                    });
                    this.listView.render();
                    return this;
                    },
          });
});

Navegação

A navegação entre os controladores de visão é outro mecanismo fornecido pelo Backbone. O Backbone se refere a isso como "roteamento" e assim fornece um objeto Backbone. O objeto de roteamento que pode ser estendido para definir rotas de navegação. Um exemplo de roteamento é apresentado a seguir:

define(['jquery', 'backbone', 'jquerymobile' ], function($, Backbone) {
         var transition = $.mobile.defaultPageTransition;
         var WorkspaceRouter = Backbone.Router.extend({
                   // bookmarkMode : false,
                   id : 'workspaceRouter',
                   routes : {
                             "index" : "stockList",
                             "stockDetail" : "stockDetail"
                   },
                   initialize : function() {
                             $('.back').on('click', function(event) {
                                       window.history.back();
                                       return false;
                             });
                             this.firstPage = true;
                   },
                   defaultRoute: function() {
                             console.log('default route');
                             this.runScript("script","stockList");
         },
         stockDetail: function() {
                   require(['view/stockDetailView'], function (ThisView) {
                                       var page = new ThisView();
                                       $(page.el).attr({
                                                 'data-role' : 'page',
                                                 'data-add-back-btn' : "false"
                                       });
                                       page.render();
                                       $(page.el).prependTo($('body'));
                                       $.mobile.changePage($(page.el), {
                                                 transition : 'slide'
                                       });
                   });
         },

         stockList : function() {
                             require(['view/stockListPage'], function (ThisView) {
                                       var page = new ThisView();

                                       $(page.el).attr({
                                                 'data-role' : 'page',
                                                 'data-add-back-btn' : "false"
                                       });

                                       page.render();
                                       $(page.el).prependTo($('body'));
                                       $.mobile.changePage($(page.el), {
                                                 transition : 'flip'
                                       });
                           });
                   },
         });
         return new WorkspaceRouter();
});

A função Define do framework Require é usado para fornecer instâncias do jQuery, Backbone e jQuery Mobile para sobrescrever as funções/métodos de roteamento. Quando a instância do Router é criada, as rotas são inicializadas com um ID e nome da função a se executar quando a rota é navegada. No exemplo anterior, há duas rotas: #index e #stockDetail.

O objeto de roteamento pode ser invocado pela navegação para uma visão/controle com a seguinte expressão:

<aRouter>.navigate("#index");

Uma função de roteamento cria uma instância do Backbone.View e chama a função de renderização. O trecho de código a seguir é um exemplo que estende a função BackBone.Router para renderizar a lista de ações com o jQuery Mobile. Note no código a seguir que o Require cria uma instância da visão/stockListPage com a visão/controle do Backbone, e em seguida usa o jQuery para fazer decorações dos atributos da página e renderizá-los.

// Router navigation funtion
stockList : function() {
                    require(['view/stockListPage'], function (ThisView) {
                              var page = new ThisView();
                              $(page.el).attr({
                                        'data-role' : 'page',
                                        'data-add-back-btn' : "false"
                              });
                              page.render();

                              $(page.el).prependTo($('body' ));

                              $.mobile.changePage($(page.el), {
                                        transition : 'flip'
                              });
          });
        },

Coleção/Modelo

O Backbone fornece um objeto Collection, que gerencia listas de objetos Backbone.Model. Os objetos de visão/controle têm atributos que referenciam uma lista ou um simples objeto JavaScript. O objeto Backbone.Collection para os objetos do modelo StockListItem é apresentado pela visão/controle a seguir:

define(['jquery', 'backbone', 'underscore', 'model/stockItemModel'],
function($, Backbone, _, StockListItem) {
         return Backbone.Collection.extend({
                   model : StockListItem,
                   url : 'http://localhost:8080/khs-sherpa-jquery/sherpa?endpoint=StockService&action=quotes&callback=?',
                   initialize : function() {
                             $.mobile.showPageLoadingMsg();
                             console.log('findScripts url:' + this.url);
                             var data = this.localGet();
                             if (data == null) {
                                       this.loadStocks();
                             } else {
                                       console.log('dados locais presentes..');
                                       this.reset(data);
                             }
                   },
                   loadStocks : function() {
                             var self = this;
                             $.getJSON(this.url, {
                                       }).success(function(data, textStatus, xhr) {
                                                 console.log('o script obteve a lista json com sucesso');

                                                 console.log(JSON.stringify(data.scripts));
                                                 self.reset(data);
                                                 self.localSave(data);
                                       }).error(function(data, textStatus, xhr) {
                                                 console.log('error');
                                                 console.log("data - " + JSON.stringify(data));
                                                 console.log("textStatus - " + textStatus);
                                                 console.log("xhr - " + JSON.stringify(xhr));
                                       }).complete(function() {
                                                 console.log('concluída a requisição json');
                                                 $.mobile.hidePageLoadingMsg();
                                       });
                   },
                   localSave : function(data) {
                             var d = JSON.stringify(data);
                             localStorage.setItem('STOCKS', d);
                   },
                   localGet : function() {
                             var d = localStorage.getItem('STOCKS');
                             data = JSON.parse(d);
                             return data;
                   }
         });
});

Quando o objeto Collection é inicializado (na aplicação de exemplo, isso acontece quando a visão/controle cria uma instância), o atributo URL especificado é chamado usando o mecanismo AJAX do jQuery para invocar o endpoint JSONP do lado servidor. O endpoint retorna objetos do JSON, que são automaticamente mapeados para o modelo stockListItem. A definição do Backbone.Model para o StockItemModel é apresentada a seguir:

define(['jquery',
                         'backbone',
                         'underscore'],
                         function($, Backbone, _) {
                                        return Backbone.Model.extend({
                                                  initialize : function() {

                                                  }

                                        });
});

Para os leitores familiarizados com as linguagens fortemente tipadas, a habilidade do JavaScript de transformar strings no formato JSON em objetos de modelo JavaScript parece mágica.

Os objetos Backbone.Model têm vários métodos para ajudar a salvar e sincronizar com um servidor. Do mesmo modo, os objetos Backbone.Collection têm métodos para sincronizar e salvar em um servidor também, e efetuar tipos de operações da programação funcional. Verifique mais funcionalidades no site do Backbone.

Armazenamento local

Outros métodos adicionados no exemplo do StockListCollection estendem Backbone.Collection, fornecendo a habilidade de salvar e restaurar objetos usando o mecanismo de armazenamento local do HTML5. Isso é definido nos métodos localSave() e localGet() dentro da coleção. Como a coleção de objetos Stock são obtidos no servidor, a aplicação HTML5 pode atuar sem conectividade.

Esse exemplo utiliza o mecanismo de sessão local baseado em chave/valor. O HTML5 também fornece um mecanismo de armazenamento relacional local chamado webSQL. No entanto, o trabalho para essa especificação está parado e ela não é completamente suportada. Então contar com esse recurso pode ser arriscado. Já o armazenamento de sessões baseado em chave/valor é bem suportado. Para mais informações, verifique a especificação do webSQL.

Inicialização e Bootstrap de aplicações

O index.html padrão inicia tudo. Este é o ponto em que são carregados os estilos definidos com a seguinte tag:

<script data-main="main.js src="libs/require/require.js"/>

Esse trecho invoca a função main.js que configura e carrega o suporte das bibliotecas JavaScript. O framework Require fornece um bom mecanismo para acessar uma biblioteca JavaScript, através de um nome simples e uma URL base com o caminho da localização. Como a pasta lib está fora do diretório raiz, nenhum caminho base de URL é exigido. Veja um exemplo:

require.config({
                    paths : {
                              'backbone' : 'libs/AMDbackbone-0.5.3',
                              'underscore' : 'libs/underscore-1.2.2',
                              'text' : 'libs/require/text',
                              'jquery' : 'libs/jquery-1.7.2',
                              'jquerymobile' : 'libs/jquery.mobile-1.1.0-rc.2'
                    },
                    baseUrl : ''
          });

Essa função de inicialização também usa a função require para configurar as propriedades do jQuery Mobile e carregar o script do App.js que navega para a rota #index, apresentando a stock-list-item.html.

O script App.js apresentado a seguir inicializa uma instância de roteamento da área de trabalho, inicializa o backbone e então navega para a página #index:

define(['backbone', 'router/workspaceRouter'], function(Backbone, WorkspaceRouter) {

          "use strict";

          $(function(){
                    window.tc = {
                              routers : {
                                        workspaceRouter : WorkspaceRouter
                              },
                              views : {},
                              models : {},
                              ticker: null
                    };

                    var started = Backbone.history.start({pushState:false, root:'/HTML5BackboneJQMRequireJS/'});
                    window.tc.routers.workspaceRouter.navigate("#index", {trigger:true});
          });
});

Endpoints JSON no lado servidor

Um servidor de aplicações configurado para usar o framework JSON khsSherpa fornece URLs para endpoints, com métodos para criar, ler, atualizar e remover para objetos Lists e Stock. O framework converte os parâmetros das requisições HTML para métodos de Endpoint Java chamando e serializando objetos Java de e para strings JSON.

Este projeto de exemplo é definido e projetado para ser publicado como um componente WAR do Java EE. O WAR contém tanto HTML estático como JavaScript, que é inicialmente entregue e pode residir nos navegadores dos clientes, além dos endpoints no servidor de aplicações Java com o Sherpa JSON que conduzem a interface HTML5.

Aqui está definido o endpoint Java no servidor, que disponibiliza objetos de preços de ações (stock) no formato JSON. Os endpoints são invocados usando uma URL HTTP get.

A aplicação de exemplo apenas necessita de um endpoint para obter a coleção de objetos Stock. No entanto, aplicações mais realistas podem precisar de autenticação e endpoints adicionais para suportar operações CRUD. Esse framework suporta esses requisitos. Para mais informações quanto às funcionalidades, verifique o framework no Github.

Conclusões

Mesmo com um exemplo simples, pudemos apresentar uma arquitetura MVC para aplicações executando no navegador. Eliminar a necessidade de os servidores renderizarem HTML dinâmico nas interfaces da aplicação é a característica mais importante da arquitetura apresentada.

O JavaScript não é uma linguagem de programação natural para todos os propósitos; porém a explosão de dispositivos móveis e a grande adoção do HTML5, assim como a falta de suporte de plug-ins, torna JavaScript/HTML5 um caminho viável para entregar aplicações ricas baseadas em navegadores para dispositivos móveis.

O código completo da aplicação de exemplo pode ser encontrado no GitHub.


Sobre o autor

David Pitt é Arquiteto de Soluções Sênior e Sócio-Diretor da Keyhole Software. Com quase 25 anos de experiência em TI, passou os últimos 15 ajudando departamentos de TI corporativos a adotarem a tecnologia de objetos. Desde 1999, lidera e ensina equipes de desenvolvimento de softwares que utilizam como base as tecnologias Java (Java EE) e .NET (com C#). É autor de vários artigos técnicos e co-autor de um popular livro sobre o WebSphere da IBM, que documenta alguns de seus padrões arquiteturais.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT