Um framework Javascript para construção de
interfaces adaptativas em aplicações REST
Apoio
W3C Brazil Office | NiC.br | Mi...
Olá, eu sou Ezequiel Bertti
• MSc Engenharia de Software para Web
• Arquiteto de Sistema
• Desenvolvedor FullStack
• https...
Bagagem
Simples/PHP/Java C#/Asp.net Python/Django Javascript/Backbone
Desktop
Web Backend Frontend
Bacharel Mestrado Pesqu...
Quantos dispositivos acessam sua
aplicação?
Alguns poucos...
A responsividade resolve?
As vezes SIM!
E nesses casos?
Qual o esforço necessário para
desenvolver a interface de uma
aplicação?
Qual a proporção de tempo? De linhas de código? D...
Podemos dizer que é quase a metade de tudo
Tipicamente, a interface gráfica, representa cerca de 48% do código
fonte, requ...
Ferramentas para diminuir o tamanho do problema
Mas e quando a
regra de negócio
muda?
Quando o modelo de dados muda?
Quando uma validação muda?
Quando um bug é encontrado...
Mogiana Paulista[2] agradece
[2] Região com a maior produção de café no Brasil
Abordagem convencional para
construção de interface
URI Contexto Dado Exibição
Exemplo:
http://meudominio.com.br/feed/xbox-one
Parser: (assunto)/(subtipo)
Protocolo: http
Dom...
Atualizando as visualizações de feed com
novas regras
• Destacar tipos de feed com css
• External → out
• Internal → in
• ...
<div id="feeds">
<div ng-repeat="feed in feeds" ng-class="['feed',
{ out:feed.type == 'external',
in:feed.type == 'interna...
Você reparou que algo não
mudou?
A estrutura da comunicação
Como o MIRA pode ajudar?
Model Interface for REST Aplications
Interface dirigida por modelos utilizando
regras para adaptar as interfaces
Modelo de
dados
Seleção de
interface
Interface...
Estrutura de uma interface com MIRA
Dado Contexto Interface Exibição
Exemplo:
http://mira.tecweb/#?URI=http://api.meudominio.com.br/feed/xbox-one
api.meudominio.com.br
var selection = [{ when...
Um exemplo com a API REST do
GitHub
Condições e Seleção de Interface
var conditions = [{
name: 'isUser',
validate: '$data.login != null'
},{
name: 'hasDetail'...
Interface Abstrata
detail
box
Interface Concretastructure:[
{'user': ['avatar', {'detail': ['user_name', 'login', 'bio', 'blog', 'company', 'location']}...
E como são tratados os eventos?
{name:'status', value:'Aguardando',
events:{click:'marcar_feito'}
},
{name:'status', value...
Exemplo com eventos
var maps = [
{ name: 'input_tarefa', widget:'BootstrapFormControl',
input:{type:'text', events:{ keydo...
E como eu crio meus widgets?
http://mira.tecweb.inf.puc-rio.br
var custom_widgets = {
TitleLink: function($parent, name, $...
Mas não tem um jeito mais fácil
para construir estas estruturas de
interface do MIRA?
Ferramenta de edição para Interface Abstrata
http://ebertti.github.io/mira-ui
MIRA – Editor
http://tecweblab.github.io/mira-editor/
Feito por: João Victor Magela
Aqui estão mais exemplos de aplicações
Orientador:
Daniel Schwabe
LINKS
Exemplos:
http://mira.tecweb.inf.puc-rio.br/
Documentação em Português:
http://mira.tecwe...
Próximos SlideShares
Carregando em…5
×

MIRA - Um framework Javascript para construção de interfaces adaptativas em aplicações REST

836 visualizações

Publicada em

http://mira.tecweb.inf.puc-rio.br/

Esta palestra apresenta o MIRA, um framework Javascript dirigido por dados, que permite a construção de interfaces adaptáveis para qualquer aplicação que disponibilize uma API REST.

Esta adaptação vai além da acomodação de diversos dispositivos, sendo capaz de se alterar também em função dos próprios dados sendo exibidos, entre outros fatores. Esta abordagem facilita também a manutenção e evolução dos projetos, minimizando o retrabalho, facilitando a comunicação do projetista da aplicação com a equipe de desenvolvimento e permitindo o reaproveitamento de soluções prévias.

Uma facilidade adicional pemitida pelo MIRA é o controle da distribuição do processamento entre cliente e servidor.

Serão apresentados exemplos de aplicações reais e complexas encontradas na Web.

Apoio da W3c Brazil Office, Nic.br e Microsoft Brasil Open Source

Publicada em: Internet
  • Seja o primeiro a comentar

  • Seja a primeira pessoa a gostar disto

MIRA - Um framework Javascript para construção de interfaces adaptativas em aplicações REST

  1. 1. Um framework Javascript para construção de interfaces adaptativas em aplicações REST Apoio W3C Brazil Office | NiC.br | Microsoft Brasil Open Source http://mira.tecweb.inf.puc-rio.br/
  2. 2. Olá, eu sou Ezequiel Bertti • MSc Engenharia de Software para Web • Arquiteto de Sistema • Desenvolvedor FullStack • https://twitter.com/ebertti • https://github.com/ebertti • https://br.linkedin.com/in/ebertti • ebertti@gmail.com EBertti, Ezeq, .exe, Exec, Zeq ou Zequinha
  3. 3. Bagagem Simples/PHP/Java C#/Asp.net Python/Django Javascript/Backbone Desktop Web Backend Frontend Bacharel Mestrado Pesquisa 0 1 2 3 4 5 6 7 8 9 10 11 12 Acadêmica Foco Profissional
  4. 4. Quantos dispositivos acessam sua aplicação?
  5. 5. Alguns poucos...
  6. 6. A responsividade resolve?
  7. 7. As vezes SIM!
  8. 8. E nesses casos?
  9. 9. Qual o esforço necessário para desenvolver a interface de uma aplicação? Qual a proporção de tempo? De linhas de código? De testes? E depois de “pronto”? Como é dar manutenção?
  10. 10. Podemos dizer que é quase a metade de tudo Tipicamente, a interface gráfica, representa cerca de 48% do código fonte, requer cerca de 45% do tempo de desenvolvimento e de 50% do tempo de aplicação, e atinge 37% do tempo de manutenção [1] [1] BRAD A. MYERS, M. B. R. Survey on user interface programming 37% 50% 45% 48% 0% 20% 40% 60% 80% 100% Manutenção Aplicação Desenvolvimento Código Fonte Interface Outros
  11. 11. Ferramentas para diminuir o tamanho do problema
  12. 12. Mas e quando a regra de negócio muda? Quando o modelo de dados muda? Quando uma validação muda? Quando um bug é encontrado? Como fazer para dar manutenção a tantas interfaces?
  13. 13. Mogiana Paulista[2] agradece [2] Região com a maior produção de café no Brasil
  14. 14. Abordagem convencional para construção de interface
  15. 15. URI Contexto Dado Exibição Exemplo: http://meudominio.com.br/feed/xbox-one Parser: (assunto)/(subtipo) Protocolo: http Domain: meudominio.com.br View: listar Tipo: feed Subtipo: xbox-one SELECT * FROM feed WHERE subtipo == ‘xbox-one’; <html> <body> <div id="feeds"> {% for feed in feeds %} <div class="feed"> <img src="{{ feed.image }}"/> <h3> <a href="{{ feed.link }}">{{ feed.title }}</a> </h3> </div> {% endfor %} </div> </body> </html>
  16. 16. Atualizando as visualizações de feed com novas regras • Destacar tipos de feed com css • External → out • Internal → in • Tweet → twt • Alguns feeds podem não ter link • Alguns feeds podem ter imagem, e conter link, caso o feed tenha link <html><body><div id="feeds"> {% for feed in feeds %} <div class="feed {% if feed.type == 'external' %} out {% elif feed.type == 'internal' %} in {% elif feed.type == 'tweet' %} twt {% endif %}"> {% if feed.image %} {% if feed.link %} <a href="{{ feed.link }}"> <img src="{{ feed.image }}"/> </a> {% else %} <img src="{{ feed.image }}"/> {% endif %} {% endif %} <h3> {% if feed.link %} <a href="{{ feed.link }}">{{ feed.title }}</a> {% else %} {{ feed.title }} {% endif %} </h3> </div> {% endfor %} </div></body></html>
  17. 17. <div id="feeds"> <div ng-repeat="feed in feeds" ng-class="['feed', { out:feed.type == 'external', in:feed.type == 'internal', twt:feed.type == 'tweet' }]"> <a ng-if="feed.link && feed.image"> <img ng-src="feed.image"/> </a> <img ng-hide="feed.link" ng-show="feed.image“ ng-src="feed.image"/> <h3> <a ng-if="feed.link" ng-href="feed.link"> {{ feed.title }} </a> <span ng-hide="feed.link"> {{ feed.title }} </span> </h3> </div> </div> E com um framework moderno, não muda mui
  18. 18. Você reparou que algo não mudou?
  19. 19. A estrutura da comunicação
  20. 20. Como o MIRA pode ajudar? Model Interface for REST Aplications
  21. 21. Interface dirigida por modelos utilizando regras para adaptar as interfaces Modelo de dados Seleção de interface Interface Abstrata Interface concreta Widgets Concretos Projetista (analista/arquiteto/engenheiro) UX (desenvolvedor/designer)
  22. 22. Estrutura de uma interface com MIRA Dado Contexto Interface Exibição
  23. 23. Exemplo: http://mira.tecweb/#?URI=http://api.meudominio.com.br/feed/xbox-one api.meudominio.com.br var selection = [{ when: 'isFeed', abstract: 'feed‘ }]; var abstracts = [{ name: 'feed', widgets: [ { name:'feeds', datasource:'$data.items', children: [ { name:'feed', children:[ {name:'image', bind:'$data.image'}, {name:'title', bind:'$data.title'} ]}]}]}]; var conditions = [ {name: 'isFeed', validate:'$data.type == "feed"'}, {name: 'isExternal', validate:'$data.type == "external"'}, {name: 'isInternal', validate:'$data.type == "internal"'}, {name: 'isTweet', validate:'$data.type == "tweet"'}, {name: 'hasImage', validate:'$data.image != null'}, {name: 'hasLink', validate:'$data.link != null'}, ]; var response = { type: 'feed', items: [ { title: 'titulo', link: 'url', image: 'url_of_image', type: 'internal || ' + 'external || ' + 'tweet || ... ' } /* ... */ ]}; var concrete = [{ name:"feed", maps: [ { name:"feeds" }, { name:"feed", class:'feed' }, { name:"feed", when:'isExternal', class:'feed out' }, { name:"feed", when:'isInternal', class:'feed int' }, { name:"feed", when:'isTweet', class:'feed twt' }, { name:"image", when:"hasImage", src:"$bind"}, { name:"image", when:"hasImage,hasLink", widget:'ImageLink', href:'navigate($data.link)', src:"$bind"}, { name:"title", tag: 'h3', value:'$bind'}, { name:"title", when:"hasLink", widget:'TitleLink', value:'$bind', href:'navigate($data.link)'} ]}];
  24. 24. Um exemplo com a API REST do GitHub
  25. 25. Condições e Seleção de Interface var conditions = [{ name: 'isUser', validate: '$data.login != null' },{ name: 'hasDetail', validate: '$bind != null' },{ name: 'haveWatch', validate: '$data.watchers_count > 0' }]; var selection = [ { when: 'isUser', abstract: 'user' } ]; var response = { "login": "ebertti", "id": 140394, "avatar_url": "https://avatars.githubusercontent.com/u/140394?v=3", "gravatar_id": "", "url": "https://api.github.com/users/ebertti", "html_url": "https://github.com/ebertti", "followers_url": "https://api.github.com/users/ebertti/followers", "following_url": "https://api.github.com/users/ebertti/following{/other_user}", "gists_url": "https://api.github.com/users/ebertti/gists{/gist_id}", "starred_url": "https://api.github.com/users/ebertti/starred{/owner}{/repo}", "subscriptions_url": "https://api.github.com/users/ebertti/subscriptions", "organizations_url": "https://api.github.com/users/ebertti/orgs", "repos_url": "https://api.github.com/users/ebertti/repos", "events_url": "https://api.github.com/users/ebertti/events{/privacy}", "received_events_url": "https://api.github.com/users/ebertti/received_events", "type": "User", "site_admin": false, "name": "Ezequiel Bertti", "company": "AmazingWorks", "blog": "www.amazingworks.com.br", "location": "Armação dos Búzios, Rio de Janeiro, Brazil", "email": "ebertti@gmail.com", "hireable": null, "bio": null, "public_repos": 19, "public_gists": 4, "followers": 32, "following": 23, "created_at": "2009-10-15T21:39:13Z", "updated_at": "2015-07-01T14:09:06Z" }; https://api.github.com /users/ebertti
  26. 26. Interface Abstrata detail box
  27. 27. Interface Concretastructure:[ {'user': ['avatar', {'detail': ['user_name', 'login', 'bio', 'blog', 'company', 'location']}]}, {'repository': ['repository_name', 'repository_description', {box: ['repository_watch']}]} ], maps: [ { name: 'navigation', widget: 'BootstrapNavigation', value:'"GitHub"'}, { name: 'navigation-list', widget: 'BootstrapNavigationList'}, { name: 'navigation-list-item', widget: 'BootstrapNavigationListItem', value:'$bind', href:'navigate($data.link)'}, { name: 'content', widget: 'ProfileContainer' }, { name: 'user', class:'clearfix' }, { name: 'avatar', widget: 'ProfileImage', value:'$bind' }, { name: 'detail', class:'col-xs-12 col-sm-8' }, { name: 'user_name', tag: 'h2', value: '$bind' }, { name: 'login', widget: 'ProfileDetail', detail: 'Login', value: '$bind'}, { name: 'bio', widget: 'ProfileDetail', detail: 'Bio', value: '$bind'}, { name: 'blog', widget: 'ProfileDetail', detail: 'Blog', value: '$bind'}, { name: 'company', widget: 'ProfileDetail', detail: 'Company', value: '$bind'}, { name: 'location', widget: 'ProfileDetail', detail: 'Location', value: '$bind'}, { name: 'follows_panel', class:'clearfix' }, { name: 'follows_title', tag: 'h3', class:'clearfix', value:'"Seguidores"'}, { name: 'follows' }, { name: 'follow', tag:'a', href: 'navigate($bind)'}, { name: 'follow_avatar', widget:'BootstrapSimple', md:'1', xs:'2', img:'circle,responsive', tag: 'img', src: '$bind + "s=80"', alt:'$data.login', title:'$data.login'}, { name: 'repositories_panel', class:'clearfix' }, { name: 'repositories_title', tag: 'h3', value:'"Repositórios"'}, { name: 'repositories' }, { name: 'repository', class:'media'}, { name: 'repository_name', tag: 'h4', value: '$data.name', class:'media-heading'}, { name: 'repository_description', tag: 'span', value: '$data.description'}, { name: 'box', tag: 'ul', class:'nav nav-pills nav-stacked pull-right'}, { name: 'repository_watch', widget: 'ProfileCount', icon:'eye-close', value:'$bind'}, { name: 'repository_watch', widget: 'ProfileCount', icon:'eye-open', value:'$bind', when:'haveWatch'}, { name: 'footer', widget: 'TecWebRodape' } { name: 'repository_watch', tag: 'ul', class:'nav nav-pills nav-stacked pull-right‘, children:[ { name: 'count', widget: 'ProfileCount', icon:'eye-close', value:'$bind'}, { name: 'count', widget: 'ProfileCount', icon:'eye-open', value:'$bind', when:'haveWatch'} ]} Duas formas de resolver a necessidade de widgets extras para exibir a contagem de Watch
  28. 28. E como são tratados os eventos? {name:'status', value:'Aguardando', events:{click:'marcar_feito'} }, {name:'status', value:'Feito', when:'isDone'} events.marcar_feito = function(options){ options.$dataObj.set('feito', true); }; Aguardando Feitoclick conditions = [{ name: 'isDone', validate:'$data.feito == true‘ }]; click Feito
  29. 29. Exemplo com eventos var maps = [ { name: 'input_tarefa', widget:'BootstrapFormControl', input:{type:'text', events:{ keydown:'adicionar' }, placeholder:'Descrição da Tarefa'}}, { name: 'feito', widget:'BootstrapIcon', value:'unchecked', events: { click: 'marcar' }}, { name: 'feito', when:'isFeito', widget:'BootstrapIcon', value:'check', events: { click: 'marcar' }}, { name: 'editar', widget:'BootstrapIcon', value:'edit', events: { click: 'habilitar_edicao' }}, { name: 'remover', widget:'BootstrapIcon', value:'remove', events: { click: 'remover' }}, { name: 'imagem_tarefa', when:'hasLocation', widget:'MapStatic', size:'450x200', class:'thumbnail', value:'$data.tarefa.substring($data.tarefa.indexOf("@"))'}, { name: 'tarefa', class:'lead', value:'$data.tarefa', md:'8', events: { click:'habilitar_edicao' }}, { name: 'tarefa', when:'inEdition', widget:'BootstrapFormControl', md:8, input:{ value:'$data.tarefa', events:{keydown:'editar'}} }, { name: 'tipo', alert:"warning", class:'row' }, { name: 'tipo', when:'isFeito', alert:"info", class:'row'}, ]; event.marcar = function(options){ options.$dataObj.set('feito', !options.$dataObj.get('feito')) }; event.habilitar_edicao = function(options){ if(!options.$dataObj.get('$edit')) { options.$dataObj.set('$edit', true); } else { options.$dataObj.set('$edit', undefined); } }; var conditions = [{ name: 'isFeito', validate: '$data.feito == true'}, { name: 'hasLocation', validate: '$data.tarefa.indexOf("@") != -1'}, { name: 'inEdition', validate: '$data.$edit != null'}];
  30. 30. E como eu crio meus widgets? http://mira.tecweb.inf.puc-rio.br var custom_widgets = { TitleLink: function($parent, name, $context, options, callback) { var element = document.createElement('h1'); element.id = name; element.setAttribute('class', 'title'); var link = document.createElement('a'); link.setAttribute('href', options.href); link.innerHTML = options.value; element.appendChild(link); $parent.append(element); var $element = $(element); var $link = $(link); if(callback){ callback({ $children: $link, $element: $element }) } } }; Mira.Widget.register(custom_widgets); var map = { name: 'title', widget: 'TitleLink', value:'MIRA', href: 'http://mira.tecweb.inf.puc-rio.br' }; <h1> <a href="http://mira.tecweb.inf.puc-rio.br"> MIRA </a> </h1> MIRA
  31. 31. Mas não tem um jeito mais fácil para construir estas estruturas de interface do MIRA?
  32. 32. Ferramenta de edição para Interface Abstrata http://ebertti.github.io/mira-ui
  33. 33. MIRA – Editor http://tecweblab.github.io/mira-editor/ Feito por: João Victor Magela
  34. 34. Aqui estão mais exemplos de aplicações
  35. 35. Orientador: Daniel Schwabe LINKS Exemplos: http://mira.tecweb.inf.puc-rio.br/ Documentação em Português: http://mira.tecweb.inf.puc-rio.br/docs Código: https://github.com/tecweblab/mira http://mira.codeplex.com/ Ferramentas: http://ebertti.github.io/mira-ui/ http://tecweblab.github.io/mira-editor/

×