Morfeo é uma comunidade de código aberto européia engajada em definir padrões[1] e estimular a inovação e a colaboração em serviços web, provendo soluções para problemas em alguns cenários que vão desde usuários comuns a grandes corporações.[2] Iniciado em maio de 2007, um dos projetos ligados à comunidade pela Telefónica Investigación y Desarrollo (Telefónica I+D)[3] e sob a licença GNU Affero General Public License (GNU AGPL)[4] é a plataforma EzWeb.
A plataforma é um compositor em alto nível de mashups. Um mashup é uma composição não usual ou inovadora de conteúdo, geralmente de fontes diferentes, feita para interação humana.[5] Os dados são normalmente providos por serviços web, também considerado como back-end, e exibidos ao usuário em aplicações, também chamadas de front-end. Denominamos por gadget essa aplicação web, preferencialmente pequena, reutilizável e centradas no usuário.[6]
As idéias por trás do projeto trazem não apenas mais inovação e colaboração, mas abre espaço para destacar possíveis requisitos para que novos padrões e novas tecnologias possam solucionar problemas recorrentes das soluções atuais.
A plataforma EzWeb está sob desenvolvimento, mas as principais partes já estão disponíveis e funcionais, como o catálogo de gadgets, a área de vinculação (wiring) e a área de trabalho. Ela também possui alguns gadgets já implementados, como os de procura e tocador do YouTube, visualizador de fotos do Flikr, visualizador do Twitter, entre outros.
Os gadgets atualmente disponibilizados dificilmente interagem mais complexamente, com três ou mais gadgets funcionando colaborativamente para formar um mashup com uma finalidade bem definida. Um objetivo deste trabalho é justamente construir alguns gadgets simples e um mashup com uma complexidade maior.
O EzWeb é uma plataforma web implementada em Python, usando o arcabouço de desenvolvimento web Django no lado do servidor, e o arcabouço JavaScript de desenvolvimento de aplicativos web dinâmicas Prototype no lado do cliente.
A plataforma possui um catálogo de gadgets, onde pode-se adicionar ou remover gadgets, que podem ser ordenados a critério de nome, autor, popularidade, data de criação e distrbuidor, ou realizar busca pelas categorias. As informações com relação a um gadget catalogado na plataforma contém seu nome, o distribuidor responsável, sua popularidade, tags que o classificam, com uma breve descrição, opções para se obter gadgets que tenham afinidade pelo tipo de ligações disponíveis, e atalhos para versões anteriores, acesso ao template original, atualização do código HTML na plataforma, remoção do gadget do catálogo e adição de um gadget na área de trabalho.
Gadgets podem se comunicar um com os outros quando estão vinculados. Para tanto, são criados vínculos direcionados entre os gadgets na área de vinculação, sendo possível o uso de uma filtragrem simples na mensagem transmitida.
Por fim, é na área de trabalho que o usuário pode redimensionar e posicionar os gadgets em alguma de suas abas. Um usuário pode ter zero, uma ou várias áreas de trabalho, que podem ser criadas, removidas, renomeadas, travadas, publicadas ou compartilhadas. Cada área de trabalho pode conter uma ou mais abas. Quando uma área de trabalho é compartilhada, a plataforma disponibiliza ao usuário o endereço referente àquela área, que, neste modo, fica travada, possibilitando seu uso em outras páginas. A publicação é feita de forma a disponibilizar a área de trabalho desenvolvida no catálogo da plataforma.
Os gadgets na plataforma EzWeb podem ser qualquer aplicações web, normalmente baseados em uma arquitetura orientada a serviços (SOA).
Arquitetura de software é uma abstração da organização de um software, independente de tecnologia e implementação, evidenciando papéis, responsabilidades e relações tanto internas como externas. A arquitetura orientada a serviços é uma arquitetura de software onde grandes funcionalidades do aplicativo são obtidas através de serviços. A comunicação com os serviços é feita com troca de mensagens através de protocolos especificados em uma interface bem definida, normalmente recebendo o nome de API (Application Programming Interface).
A troca de mensagens também é independente de implementação, sendo que essas mensagens podem possuir qualquer tipo de dado. Para que essas mensagens possam ser manipuladas mais fácil e padronizadamente, alguns formatos foram criados, sendo XML e JSON dois deles.
O XML é uma notação simples, flexível e legível aos humanos, criada para armazenar e transmitir dados, estruturados hierarquicamente. A especificação feita pela W3C também possui mecanismos de consulta (XQuery), navegação (XPath) e transformação (XSLT) de documentos XML.
A linguagem de consulta XML (XQuery) é especificada através de expressões de consulta, formadas principalmente por expressões FLWOR (acrônimo correspondente a For
, Let
, Where
, Ordered by
e Return
), semelhantes ao SQL, provendo um recurso para extrair e interpretar os dados contidos em um documento XML. A linguagem de navegação XML (XPath) provê uma notação de endereçamento através dos nós da árvore de um documento XML. Finalmente, a linguagem de estilo extensível (XSL) é usada para se realizar transformações (XSLT) que reestruturam documentos XML de for a torná-los estilizados e apresentáveis a usuários.
Dois dialetos do XML bastante utilizados para propagação de informações são o ATOM e o RSS.
Objetos em JavaScript são conciderados vetores associativos, onde o valor de cada mapeamento pode ser qualquer valor que uma variável pode receber, ou seja, booleano, número, cadeia de caracteres, arrays, objeto, função, null
ou undefined
. A sua criação pode ser feita chamando-se new
antes de um construtor ou usando-se a notação literal de objetos, ou seja, uma lista de mapeamentos chave/valor, cercada por abre e fecha chaves.
O JSON é um subconjunto na notação literal de objetos, excluindo-se undefined
e função como valores aceitos. Uma expressão em JSON pode ser transformado em objeto com uma chamada à função eval
, em JavaScript.
Uma ramificação do JSON é o JSONP (JSON with Padding), onde um prefixo, usualmente o nome de uma função, é adicionado à requisição, que é avaliado assim que a transferência da requisição terminar.
Para que um servidor envie mensagens a um cliente, este precisa abrir um canal de comunicação com aquele. Através de uma conexão HTTP de longa duração, é possível este canal aberto, permitindo ao servidor realizar esta comunicação de uma forma bidirecional. Esta idéia é chamada de Comet, podendo também receber outros nomes, como AJAX push, HTTP server push, entre outros.
O Orbited é um roteador web e firewall com implementação Comet, permitindo conexões TCP, com suporte a alguns protocolos, como IRC (Internet Relay Chat, protocolo para um ambiente de chats), XMPP (Extensible Messaging and Presence Protocol, protocolo para troca de mensagens em XML) e STOMP (Streaming Text Orientated Messaging Protocol, protocolo com um formato interoperacional de comunicação).
Uma linguagem dinâmica é aquela que pode modificar seu comportamento em tempo de execução. O JavaScript, criado pela Netscape e posteriormente especificado pela Ecma Internacional, é uma linguagem dinâmica e interpretada com capacidades de orientação a objetos, herança baseada em protótipos e tipagem dinâmica, além da possibilidade do uso de funções anônimas e de fechamentos.
Apesar de poder ser utilizado em alguns outros contextos, a importância e popularidade do JavaScript vem justamente do seu uso para a atribuição de comportamento em elementos de um documento HTML, viabilizando a idéia de aplicativos web.
O EzWeb possui alguns pré-requisitos: um gerenciador de banco de dados (PostgreSQL, MySQL, SQLite e Oracle são suportados), Python 2.4 (ou mais recente) e o correspondente driver para o banco de dados, e Django 1.0 com PyXML 0.8 (ou mais recente). O ambiente de programação para este trabalho foi feita na distribuição Linux Gentoo, sendo que a configuração das ferramentas foi SQLite versão 3.6.18, Python versão 2.6.2-r1, Django versão 1.0.3 e PyXML versão 0.8.4-r2.
O projeto está armazenado em um servidor de controle de versões Subversion (SVN), no endereço do repositório logo abaixo. Para obtê-lo, é necessário um cliente SVN, sendo que o cliente usado no projeto foi o do Tigris.org (atualmente tornando-se um projeto da Apache Software Foundation). O comando utilizado foi o seguinte:
svn co https://svn.forge.morfeo-project.org/svn/ezwebplatform\ /ezweb_platform/src/trunk/
Obtido o projeto, foram realizadas apenas duas mudanças no arquivo de configuração settings.py: o valor de DATABASE_ENGINE foi mudado para "sqlite3" e o de DATABASE_NAME para o caminho do arquivo de banco de dados. Assim que a configuração foi feita, é necessário criar e preparar o arquivo do banco de dados, executando o seguinte comando, na raiz do projeto:
$ python manage.py syncdb
O comando prepara o esquema das tabelas utilizadas e pergunta ao usuário se este deseja criar um superusuário. Caso positivo, são perguntados o nome de usuário, e-mail, senha e confirmação da senha.
Com o banco de dados criado, é possível executar o projeto com o comando:
$ python manage.py runserver [endereço]:[porta]
, sendo [endereço] e [porta] o endereço e a porta da máquina onde se deseja acessar a plataforma, respectivamente.
O Jetrix é um servidor TetriNet usado para testes. A versão instalada é 0.2.3 e o único pré-requisito é o JRE 1.5 ou mais recente. Para iniciar o serviço, basta executar, na raiz do Jetrix:
$ ./jetrix
Os pré-requisitos para a instalação do Orbited são o Python 2.5 (ou mais recente), a biblioteca em Python demjson e o Twisted. A versão utilizada, neste trabalho, do demjson é 1.4 e a do Twisted é 8.1.0.
O Orbited deve ser configurado em uma porta para escutar conexões vindos dos clientes, e para redirecionar as conexões da porta 31457, utilizado pelo servidor TetriNET. Conciderando que o servidor TetriNET esteja no mesmo IP, as modificações mais significantes no arquivo de configurações orbited.cfg
são as seguintes:
[listen] http://:8000 [access] * -> 127.0.0.1:31457
Também é possível configurá-lo para hospedar arquivos, com a seguinte adição:
[static] urlAlias=/path/to/a/directory
Para iniciá-lo, basta executar o seguinte, na raiz do projeto:
$ ./start.py
A criação de um gadget é realizada através de um template, um arquivo XML contendo os meta-dados do gadget para a publicação no catálogo da plataforma, e o código da implementação do gadget, que pode se um documento HTML ou XHTML.
O template é dividido em alguns blocos conceituais: descrição, variáveis de integração e outros elementos.
O bloco de descrição possui os seguintes campos, relacionados ao gadget: distribuidor (vendor), nome (name), versão atual (version), autor (author), endereço de email do autor (mail), uma breve descrição do gadget (description), endereço da imagem do gadget para exibição no catálogo (imageuri) e endereço para maiores informações sobre o gadget (wikiuri).
A descrição segue o seguinte formato:
<Catalog.ResourceDescription> <Vendor>IMEUSP</Vendor> <Name>Nome do Gadget</Name> <Version>1.0</Version> <Author>Rafael</Author> <Mail>rafael.suguiura@gmail.com</Mail> <Description> Este é um exemplo de uma breve descrição do gadget. </Description> <ImageURI>http://servidor/imagem.png</ImageURI> <WikiURI>http://servidor/wiki</WikiURI> </Catalog.ResourceDescription>
O bloco de variáveis de integração é composto por quatro seções: preferências, propriedades de estado, vinculação e contexto.
Preferências podem ser mudadas através da interface oferecida pela plataforma. Cada preferência possui, obrigatoriamente: o nome da preferência (name), que será usado para referenciar a variável no gadget; o rótulo (label), que identificará a preferência na interface ao usuário; a descrição da preferência (description); e o tipo (type), que pode ser texto, número, booleano, senha ou lista. Caso a preferência seja do tipo lista, ela poderá conter um número qualquer de opções, sendo que cada opção deverá conter um nome e um valor associado. Por exemplo, posso limitar o acesso a servidores Tetrinet apenas aos que estiverem na lista:
<Platform.Preferences> <Preference name="nick" type="text" description="Apelido" label="Apelido" /> <Preference name="host" type="list" description="Servidor" label="Endereço do servidor" > <Option name="Jetrix(localhost)" value="127.0.0.1:31457"/> <Option name="TetriNET.no" value="tetrinet.no:31457"/> </Preference> </Platform.Preferences>
Já as propriedades de estado são variáveis em que a plataforma permite que valores do gadgets sejam persistidos para cada usuário. Cada propriedade de estado contém os atributos nome, tipo e rótulo, semelhantes aos da preferência, exceto pelo fato do único tipo aceito ser texto. Por exemplo, poderíamos armazenar o IP e a data do último acesso do usuário com o seguinte:
<Platform.StateProperties> <Property name="ip" type="text" label="IP do último acesso"/> <Property name="date" type="text" label="Data do último acesso"/> </Platform.StateProperties>
As variáveis de vinculação abre canais de comunicação entre gadgets. Existem dois tipos de variáveis de vinculação, o slot, variável esta que recebe mensagens de events, e event, que as envia. Cada variável de vinculação possui os campos nome, tipo, rótulo e código de correspondência (friendcode). Assim como as propriedades de estado, o único tipo aceito é texto. O código de correspondência permite que variáveis de vinculação correspondentes possam ser encontrados mais facilmente através da identificação do código de correspondência das variáveis de vinculação dos outros gadgets. Podemos pegar como exemplo um gadget de chat que envia e recebe mensagens de texto:
<Platform.Wiring> <Slot name="income" type="text" label="Message" friendcode="msg"/> <Event name="outcome" type="text" label="Message" friendcode="msg"/> </Platform.Wiring>
Um detalhe é que é possível vincular dois gadgets mesmo com códigos de correspondência diferentes.
As variáveis de contexto permitem obter informações sobre o ambiente, sendo ContextGadget
a variável que disponibiliza informações sobre o próprio gadget e Context
, a que disponibiliza informações externas, sobre a plataforma. Ambas as variáveis possuem tres atributos: nome, tipo e conceito (concept). Aqui, o tipo aceita apenas texto como valor. O conceito provê a semântica à variável, Atualmente, apenas altura (height) e largura (width) são oferecidas para o contexto do gadget, e nome de usuário (user_name) e idioma (language), para o contexto da plataforma. Exemplo:
<Platform.Context> <Context name="user" type="text" concept="user_name"/> <Context name="language" type="text" concept="language"/> <GadgetContext name="height" type="text" concept="height"/> <GadgetContext name="width" type="text" concept="width"/> </Platform.Context>
Os outros elementos do template são o endereço do código, que possui um elemento, o XHTML, com apenas o atributo href, que é a referência ao código do gadget; e a renderização, que contém os atributos altura e largura do gadget. Exemplo:
<Platform.Link> <XHTML href="http://servidor/gadget.html" /> </Platform.Link> <Platform.Rendering width=“5" height="7" />
A implementação do gadget na plataforma utiliza o JavaScript para a utilização das variáveis descritas no template. As variáveis são acessíveis através de uma biblioteca, também em JavaScript, fornecida pela plataforma, o EzWebAPI.
A API dispõe de dois métodos para tratamento das variáveis: o createRGadgetVariable, para criação de objetos para variáveis de leitura apenas e createRWGadgetVariable, para leitura e escrita. Os dois métodos tem o nome da variável como parâmetro. Porém, o método createRGadgetVariable recebe um segundo parâmetro que é uma função de tratamento. Essa função é chamada sempre que há uma mudança de valor da variável ao qual está associada. Quando isso acontece, ela é chamada com um parametro, o novo valor desta variável.
As variáveis de leitura apenas são o slot, as variáveis de preferência, e as de contexto. Já as variáveis de leitura e escrita são o event e as de propriedades de estado.
O objeto devolvido por esses métodos possuem o método get
e, para as variáveis de escrita, o método set
. Este possui um parâmetro, o novo valor da variável, enquanto aquele não possui parametros, mas devolve o valor da variável.
Assim, para as variáveis de propriedades de estado do exemplo da seção anterior, posso obter o valor do IP anterior e atribuir um novo valor da seguinte forma:
var ipVariable = EzWebAPI.createRWGadgetVariable("ip"); var oldIpValue = ipVariable.get(); var newIpValue = "127.0.0.1"; ipVariable.set(newIpValue);
Já um código para o tratamento da variável de contexto, também tomando o exemplo da seção anterior, é o seguinte:
var handler = function (username) { alert("Olá, " + username + "!"); }; var userVariable = EzWebAPI.createRGadgetVariable("user", handler);
Um objeto XMLHttpResquest permite a comunicação do cliente com o servidor através das chamadas HTTP usando métodos post
, get
, put
e delete
. Porém, devido a questões de segurança, essas chamadas são restritas apenas ao mesmo domínio da página. Contudo, com o uso do serviço da plataforma EzWeb como intermediário, é possível contornar tal restrição utilizando respectivos métodos que a biblioteca também disponibiliza: send_post
, send_get
, send_put
e send_delete
.
O jQuery é uma biblioteca JavaScript que oferece açúcares sintáticos para obter elementos DOM, tratamento de eventos, animação e AJAX. Com a biblioteca, é possível selecionar elementos DOM usando a sintaxe da linguagem CSS. A documentação mais detalhada pode ser encontrada no site do jQuery em http://docs.jquery.com/, mas uma breve descrição dos comandos mais utilizados vem a seguir:
$("div")
$("div.box")
$("div #username")
$("div #username").css("background", "blue")
$("div #username").html("<input type='text' name='username'>")
O TinyURL oferece um serviço de redução de links, recebendo um endereço e devolvendo um código correspondente, único e determinístico.
Para facilitar a organização da implementação, o código JavaScript deste gadget foi dividido em três arquivos: ezweb.js, app.js e url.js. O ezweb.js é um açúcar sintático para a criação de variáveis do EzWeb, disponibilizando a função createGadgetVariable
, cujos parâmetros são o nome da variável EzWeb e opcionalmente um método de tratamento (caso esse método seja dado, ele tenta criar uma variável de leitura apenas; caso contrário, ele tenta criar uma variável de leitura e escrita); o app.js faz todo o controle do aplicativo; e url.js faz o tratamento das variáveis do EzWeb:
url.js:
// Cria o namespace CONNECTOR, caso não exista. var CONNECTOR = CONNECTOR || {}; // Instancia o objeto assim que todo o documento estiver pronto. $(document).ready(function(){CONNECTOR.url = new CONNECTOR.Url();}); // Construtor. CONNECTOR.Url = function() { this.wire = EZWEB.createGadgetVariable("urlIn", this.handler); this.wire = EZWEB.createGadgetVariable("urlOut"); }; // Trata o URL recebido de algum outro gadget. CONNECTOR.Url.prototype.handler = function(url) { TINYURL.app.load(url); }; // Envia o URL para outro gadget. CONNECTOR.Url.prototype.send = function(url) { this.wire.set(url); }
app.js:
// Cria o namespace TINYURL, caso não exista. var TINYURL = TINYURL || {}; // Instancia o objeto assim que todo o documento estiver pronto. $(document).ready(function(){TINYURL.app = new TINYURL.App();}); // Construtor. TINYURL.App = function() { this.element = $("#tinyurl"); }; // Escreve o html no elemento. TINYURL.App.prototype.html = function(html) { this.element.html(html); }; // Envia uma mensagem para o send_get e, caso seja executado com sucesso, // chame o método tryGet. Caso contrário, chame o método this.catchGet. TINYURL.App.prototype.load = function(url) { var requestURL = "http://tinyurl.com/api-create.php?url=" + url; this.html("<p>Loading...</p>"); EzWebAPI.send_get(requestURL, this, this.tryGet, this.catchGet); }; TINYURL.App.prototype.tryGet = function(res) { var url = res.responseText; var html = '<a href="javascript:CONNECTOR.url.send(\'" + url + "\');">'; html += url; html += '</a>'; this.html(html); }; TINYURL.App.prototype.catchGet = function(res) { this.html("Error: could not get the url!"); };
Note que o método load
se utiliza da intermediação do serviço da plataforma para realizar uma requisição em outro domínio, o do TinyURL. A resposta é dada em um texto simples e sem formatação.
index.html:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <link type="text/css" rel="stylesheet" href="/files/tinyurl/style.css"> <!-- libraries --> <script type="text/javascript" src="/files/EzWebAPI.js"> </script> <script type="text/javascript" src="/files/jquery-1.3.2.min.js"> </script> <!-- utilities --> <script type="text/javascript" src="/files/ezweb.js"> </script> <!-- application --> <script type="text/javascript" src="/files/tinyurl/app.js"> </script> <!-- connectors --> <script type="text/javascript" src="/files/tinyurl/connector/url.js"> </script> </head> <body> <div id="tinyurl"></div> </body> </html>
template.xml:
<Template schemaLocation="http://morfeo-project.org/2007/Template"> <Catalog.ResourceDescription> <Name>TinyURL</Name> <Version>1.1</Version> <Author>Rafael</Author> <Mail>rafael.suguiura@gmail.com</Mail> <Vendor>IMEUSP</Vendor> <Description>A TinyURL generator</Description> <ImageURI>/files/tinyurl/image.png</ImageURI> <WikiURI>http://www.ime.usp.br/</WikiURI> </Catalog.ResourceDescription> <Platform.Wiring> <Slot name="urlIn" type="text" label="url" friendcode="url" /> <Event name="urlOut" type="text" label="url" friendcode="url" /> </Platform.Wiring> <Platform.Link> <XHTML href="/files/tinyurl/index.html" /> </Platform.Link> <Platform.Rendering width="3" height="3" /> </Template>
Para adicionar o gadget ao catálogo da plataforma, é preciso clicar na opção "Development Options", na aba "Add Gagets". O endereço do template deve ser colocado na entrada de texto de "Template URL" e, em seguida, adicionado ao catálogo ao se clicar em "Create resource".
O gadget de lista de vídeos relacionados do YouTube segue a mesma estrutura do gadget de links reduzidos do TinyURL. Devido à complexidade do conjunto de dados providos pelo serviço do YouTube, esses dados vem estruturados, tanto em dialetos do XML, como ATOM ou RSS, como JSON ou JSONP.
A especificação da estrutura dos dados está especificado em http://code.google.com/apis/gdata/docs/json.html, sendo que o formato do pedido dado em http://code.google.com/apis/youtube/2.0/reference.html#Related_videos_feed.
O gadget transformador XSL recebe o endereço de um arquivo XML e um correspondente transformador XSL, exibindo o resultado no corpo do gadget. O gadget utiliza uma implementação de XSL-T em javascript através do arcabouço AJAXSLT.
O TetriNET é uma modificação multi-jogador do jogo Tetris, permitindo até 6 jogadores simultaneamente, criado em 1997. O jogo possui, além da mecânica do Tetris, blocos especiais que adicionam comportamento ao campo do jogador alvo. Este projeto se baseou na versão 1.13 do jogo original, através do projeto de código aberto GTetrinet (versão 0.7.11), implementado em C usando o arcabouço GTK.
A comunicação é feita através do protocolo TCP. Os comandos utilizados na comunicação deste projeto são os seguintes:
noconnecting
.
Caso o cliente consiga conectar com sucesso, o cliente recebe o número de identificação através do comando playernum
. Se o jogador possuir o menor número de identificação, este obtém a responsabilidade de iniciar, pausar ou parar um jogo. Porém, se ele possuir esta responsabilidade e um outro jogador conectar ao servidor, sendo notificado através do playerjoin
, e obter um número de identificação menor, então estas operações passam a ser responsabilidades deste novo jogador. O oposto também ocorre, quando um jogador fica com o menor número de identificação quando outro jogador, que mantinha o menor número de identificação, sair, sendo esta operação notificada pelo comando playerleave
.
Durante todo o momento em que o jogador permanecer conectado, ele pode enviar e receber mensagens e realizar e notificar ações na sala de bate-papo, através dos comandos pline
e plineact
, respectivamente.
Com um jogo iniciado, através de startgame
, cada cliente envia o estado do seu campo usando o comando f
. O parâmetro de f
pode ter duas formas: uma cadeia de caracteres sendo que cada caracter representa um bloco da serialização simples de um campo; ou a diferença do campo anterior com o campo atual, contendo os códigos e as posições dos blocos que foram modificados.
O envio de um bloco especial pode ser feito a qualquer momento, enquanto o jogador ainda estiver em jogo e possuir blocos especiais na fila, com o comando sb
. O bloco é ativado quando o jogador pressionar o número correspondente ao jogador alvo. Cada bloco especial é descrito a seguir:
O jogo de um jogador termina na condição do bloco especial "a" ou quando não for possível movimentar um bloco a partir de sua posição inicial. Quando todos os jogadores oponentes perderem, o jogador ou a equipe que permanecer é declarado ganhador da partida.
A implementação da interface do usuário para cada gadget foi feita buscando-se exibir apenas as informações relevantes ao usuário. Todo o tratamento de elementos no documento foi feito utilizando o arcabouço jQuery e da linguagem de estilos CSS. A seguir, segue uma descrição sobre a implementação de cada gadget:
À parte da implementação do gadget responsável pelo tratamento da comunicação entre outros gadgets na plataforma foi dado o nome de conector. Um conector realiza o envio e o tratamento das mensagens recebidas com relação a apenas um dos gadgets com que o gadget se comunica.
Abaixo estão as descrições dos dados enviados pelos gadgets, por pares que trocam informações bidirecionalmente:
A tecnologia de comunição em tempo real oferecido pelo Orbited tornou possível a elaboração de um cliente Tetrinet, na forma de um mashup com um grau de complexidade maior, tanto com relação à interação (comunicação) entre os gadgets envolvidos, como a ferramentas e as técnicas utilizadas para o seu desenvolvimento.
Apesar da maior complexidade do mashup, que, como exercício acadêmico, não seguiu à risca toda a ideologia da plataforma, como se utilizar de serviços web, é possível dividir um gadget no blocos conceituais de exibição, obtenção de dados e comunicação com outros gadgets, facilitando a organização do código na criação de gadgets para serviços web. Uma ilustração desta divisão é feita a seguir:
Cada uma dessas divisões pode ser considerada uma componente do gadget que se comunicam internamente, cada um obtendo e repasando informações conforme estes lhe são atribuídos. Ressaltando essa conectividade e ampliando o escopo da organização, temos o seguinte diagrama:
Uma maior complexidade se deve ao tratamento dos dados, à forma de exibição e interação do usuário com a interface do gadget, e à influencia das mensagens de outros gadgets no aplicativo.
O fato do JavaScript ser uma linguagem interpretada e possuir uma tipagem dinâmica trouxe um grau de complexidade maior ao desenvolvimento do mashup, quanto à sua depuração. Uma ferramenta bastante utilizada para a verificação do código deste projeto foi o JSLint. O verificador, implementado em JavaScript, alerta sobre diversos erros de sintaxe, apontando também diversas práticas que possam levar a erros em JavaScript. Usar a engine JavaScript SpiderMonkey, implementada em C, tornou a verificação mais rápida do que a verificação realizada no navegador ou no Rhino, outra engine JavaScript, implementada em Java.
O projeto começou com a proposta do Flávio em estudar a plataforma, quando, após implementar alguns gadgets iniciais, surgir a idéia da implementação do TetriNET. As primeiras implementações eram extremamente demoradas, sendo que o teste para verificar uma mudança pequena chegava a demorar um minuto(!), um tempo enorme quando se está acostumado a compilações praticamente instantâneas. Esse problema foi superado ao utilizar usa organização que dependa o menos possível da plataforma, enviando os códigos JavaScript para arquivos externos e usando a opção do Firefox de atualizar apenas um determinado frame
.
Apesar de ter começado com bastante antecedência, o projeto começou a tomar alguma forma no final do primeiro semestre do ano, quando a implementação do mashup foi iniciada. Antes disso, procurei por serviços web que possam ser interessantes, entre eles os serviços oferecidos pelo Wikipedia, pelo AIM e pelo Bovespa, todos com oferecimento de algum tipo de informação, sendo que a não implementação delas foram as mais frustantes. Houve um motivo para cada um dos gadgets: em meio ao desenvolvimento do gadget do Wikipedia, o servidor de demonstração do EzWeb recebeu a submissão de um gadget seguindo a mesma idéia; já o serviço de mensagens instantâneas do AIM utiliza um código de reprodução de gadgets próprio, um ambiente complexo e encapsulado onde não consegui uma documentação para melhor explorá-lo (com este gadget já havia a pretenção em fazer algum tipo de comunicação em tempo real); e finalmente, o gadget do Bovespa foi feito procurando por alguma forma de se obter alguma informação da bolsa, sendo que, na época, não havia um oferecimento oficial dessas informações (o serviço era oferecido, mas não havia menção a ele no site da Bovespa). Mais tarde, ao dar os toque finais aos gadgets, este passara a não mais funcionar, já que a Bovespa havia reformulado a estrutura do seu site e, portanto, o gadget foi abandonado mesmo depois de estar pronto.
Este projeto exigiu um esforço grande no que diz respeito à busca e à quantidade de informações. Utilizar tecnologias e padrões requer, além de aprender sobre elas, aprender ou ter pelo menos alguma noção sobre as tecnologias e padrões relacionadas a elas.
Utilizar as férias de inverno para o projeto deu um enorme impulso no andamento do trabalho, mas, em compensação, toda a energia que normalmente seria recuperada nesse período não foi obtido, além de ter o esforço extra do trabalho efetuado. Dependendo da situação, essa energia pode fazer falta em algum momento.
O ideal seria disponibilizar este trabalho no servidor do Projeto Morfeo, que já possui diversos outros gadgets catalogados. Porém, devido à restrição de domínio do XMLHttpRequest, a biblioteda do Orbited não consegue acessar o ser servidor. Houve uma tentativa frustrada de se utilizar um iframe
, com um documento com a biblioteca do Obited no domínio do servidor, e fazer uma comunicação entre os frames, mas sem sucesso. Para a viabilização da disponibilização, seriam necessárias as instalações tanto do servidor do Orbited como o da plataforma EzWeb no mesmo domínio, ou então implementar modificações na plataforma e na biblioteca, adaptando-a à plataforma.
Apesar de tudo, o projeto teve foi desafiadora pela complexidade dada pela junção de uso de ferramentas não tão complexas, mas que trazem semânticas que precisam ser organizadas e trabalhadas.
Algumas disciplinas que poderiam ter contribuído para o projeto, mas que não foram cursadas foram a Programação Orientada a Objetos, uma vez que suas técnicas poderiam ser utilizadas na programação em JavaScript, e, em um grau bem maior, Sistemas de Middleware, que cobre muitos tópicos relacionados ao projeto.
Os próximos passos a serem tomados para a continuidade do projeto seria o estudo de outras tecnologias e outros padrões, como o BOSH (Bidirectional-streams Over Synchronous HTTP), XMPP (Extensible Messaging and Presence Protocol), Message Brokers, WSDL, entre outros.
A cultura de gadgets tem um grande potencial com a vinda da versão 5 da especificação do HTML. Apesar da web ser o maior propulsor, outras interfaces, como os celulares e as TVs digitais também poderiam se utilizar dessa idéia.
Além do EzWeb, existem diversos outros ambientes baseados em gadgets, como o iGoogle, o site da BBC e a área de trabalho do Windows. Porém, os gadgets desses ambiente não influenciam ou pouco influenciam outros gadgets. Uma nova plataforma a ser lançada pela Google tras um ambiente fortemente baseado em gadgets, em rede de contatos e em comunicação em tempo real, ambiente este que poder ser estudado e nomeado de Wave.
Existe outro projeto da Google para ambientação virtual em 3D para navegadores, programado em JavaScript, entitulado O3D