View
243
Download
0
Category
Preview:
Citation preview
@flaviohalmeida
flavio.almeida@caelum.com.br
FLÁVIO ALMEIDA
JavaC#PythonRubyGroovyJavaScript
Desenvolvedor Java à procura da menor impedância para construção
de aplicações web
Once upon a time…
Impedância?
Impedância
“Discrepância da estrutura dos dados armazenados no banco de dados e as estruturas de dados em memória” - Martin Fowler
Impedância
ESTRUTURA TABULAR E RELACIONAL, SQL
POJO (PLAIN OLD JAVA OBJECTS)
JSON (JAVASCRIPT OBJECT NOTATION)
Isomorphic JavaScript
Back-end e front-end compartilham o mesmo código
JavaScript é considerada a língua franca da web
Língua Franca
É aquela que um grupo multilíngue de pessoas intencionalmente adota ou desenvolve para que todos consigam sistematicamente comunicar-se uns com os outros.
Língua franca ou torre de babel?
ESTRUTURA TABULAR E RELACIONAL, SQL
POJO (PLAIN OLD JAVA OBJECTS)
JSON (JAVASCRIPT OBJECT NOTATION)
"Não são as respostas que movem o mundo, são as perguntas” — Albert Einstein
Testes de unidade
Testes de integração
One commit deploy
Integração contínua(Travis)
Grunt(Automaçã
o)
Bootstrap
Karma(Jasmine)
Protractor
(Selenium)
AngularJS
To be or not to be MEAN?
Tradução da palavra mean
Adjetivos
inferior, insignificante, malvado, mediano, pobre, ruim, sórdido, etc.
Significado do acrônimo MEAN
MongoDBExpressAngularJSNodejs
Contexto Histórico
Contexto Histórico
Era do AJAX 2005
"Nova abordagem de criação de páginas web" - Jesse James Garret
Era do SPA 2005
SINGLE PAGE APPLICATION
"Elementos de interface e lógica da aplicação são criados e executados no cliente" —Steve Yen
Era do Extreme Go Horse2005
2010 Backbone Angular
Era dos Frameworks2009
2011 Batman2012 Ember
a) Popularidade meteóricab) Pioneiro na injeção de dependênciasc) Solução própria para criação de módulosd) Sistema próprio de rotase) Two-way data bindingf) Ferramentas para testes
Era "The Book is on the Table" 2013…
Progressive Enhancement
X SPA
"Pensamos no que deveria ser e fechamos os olhos para o que é" - Michel Maffesoli
SPA's chegaram para ficar, quer você queira ou não
Hoje é a “palavra de ordem“ em aplicações híbridas
Paralelamente…
2009
Bancos que não se baseiam em esquemas (Eric Evans)
N SQL
2009
Banco NoSQL baseado em documento BSON, MUITO semelhante ao JSON, porém com mais tipos
2009
Boa parte da responsabilidade das regras de validação fica nas mãos dos desenvolvedores.
2009
Quero aplicações Web!!!
2010
2011
var mongoose = require('mongoose');
var schema = mongoose.Schema({ nome: { type: String, required: true }, email: { type: String, required: true, index: { unique: true } } }); return mongoose.model('Contato', schema);
2011
2012
VALERI KARPOV
Cunhou o acrônimo MEAN para denotar as tecnologias utilizadas durante uma
competição de hackathron que venceu.
MEAN
2012
VALERI KARPOV
Ascot Project
Bookalokal
Vantagens constatadas durante o Hackathon
SPA desde o início
Menor impedância
API REST
Isomorphic JavaScript*
* não era para você conseguir ler isso!
SPA desde o início
ngRoute (default)
ui-router(extensão)
SPA desde o início
<!— index.html —><html ng-app="minhaApp"> <head> (…) </head> <body> <ng-view> </ng-view> </body></html>
<!-- partials/cadastro.html --><h1>Cadastro de fotos</h1><form> (...)</form>
<!-- partials/listagem.html --><h1>Listagem de fotos</h1>
index.html/#/fotos
index.html/#/fotos/new
SPA desde o inícioangular.module('minhaApp', ['ngRoute']) .config(function($routeProvider) {
$routeProvider.when('/fotos', { templateUrl: 'partials/listagem.html', controller: 'FotosController' });
$routeProvider.when('/fotos/new', { templateUrl: 'partials/cadastro.html', controller: 'FotoController' }); });
Menor impedância
ESTRUTURA TABULAR E RELACIONAL
Autor autor = new Autor();autor.setNome(…);
{ "_id": "1" "nome": "Flávio Almeida"}
OUTROS
Navegador(JSON)
Banco(SQL)
Servidor(Object)
Menor impedância
{ "_id": ObjectId("5303e0649fd139619aeb783e") "nome": "Flávio Almeida"}
{ "_id": "5303e0649fd139619aeb783e" "nome": "Flávio Almeida"}
{ "_id": "5303e0649fd139619aeb783e" "nome": "Flávio Almeida"}
MEAN STACK
Navegador(JSON)
Banco(BSON)
Servidor(JSON)
Menor impedância
$http('/v1/fotos').then(function(fotos){ $scope.fotos = fotos;});
app.get('v1/fotos', function(req, res){ db.collection('contatos').find({}, function(erro, contatos){ if(erro) throw err; res.json(contatos); } });};
Client(Angular
)
Server (API REST)(Express/MongoDB driver)
<img ng-repeat="foto in fotos"
ng-src=“{foto.src}">
Performance
Escalabilidade
Estado no cliente, servidor stateless
Single thread e non-blocking I/O
non-blocking I/O
Tudo roda em paralelo, exceto seu código!
Blocking Vs non-blocking I/O
db.collection('contatos').find({}, function(erro, contatos) { console.log(contatos); });console.log('FIM');
var contatos = db.collection('contatos').find({});console.log(contatos);console.log('FIM');
Pseudo Blocking I/O
Non-blocking I/O
Mas na prática, é tudo essa maravilha?
Não há um Scaffold consolidado
mean.ioVS
mean.js
Você já implementou um DAO, não importa a linguagem?
DAO patterndao.porNome = function(nomeProcurado, cb) { db.collection('contatos') .findOne({nome : procurado}, function(erro, contato) { if (erro) cb('Não foi possível…', null); cb(null, contato); });};dao.dependenteDoContato = function(contato, cb) { db.collection('dependentes') .find({contatoId : contato_id}, function(erro, dependente) { if (erro) cb('Não foi possível…', null); cb(null, dependente) ; });};dao.adicionaBeneficio = function(dependente, cb) { db.collection('beneficios') .insert(dependente, function(erro) { if (erro) cb('Não foi possível…’, null); cb(null, true); });};
Callback HELL
dao.porNome('Flávio Almeida', function(erro, contato) { if(erro) throw console.log(erro); dao.dependenteDoContato(contato, function(erro, dependente) { if(erro) throw console.log(erro); dao.adicionaBeneficio(dependente, function(erro, adicionado){ if(erro) throw console.log(erro); if (adicionado) console.log('Benefício adicionado'); }); });});
Callback HELL
dao.porNome('Flávio Almeida', function(erro, contato) { if(erro) throw console.log(erro); dao.dependenteDoContato(contato, function(erro, dependente) { if(erro) throw console.log(erro); dao.adicionaBeneficio(dependente, function(erro, adicionado){ if(erro) throw console.log(erro); if (adicionado) console.log('Benefício adicionado'); }); });});
Synchronous Heaven
try { var contato = dao.porNome('Flávio Almeida'); var dependente = dao.depententeDoContato(contato); console.log(dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
Callback HELL
No cliente (browser) acontece a mesma coisa!
Mas tem cura doutor?
Só se você fizer uma promessa!
Callback HELL
dao.porNome('Flávio Almeida', function(erro, contato) { if(erro) throw console.log(erro); dao.dependenteDoContato(contato, function(erro, dependente) { if(erro) throw console.log(erro); dao.adicionaBeneficio(dependente, function(erro, adicionado){ if(erro) throw console.log(erro); if (adicionado) console.log('Benefício adicionado'); }); });});
Promise Pattern
dao.porNome('Flávio Almeida').then(dao.depententeDoContato).then(dao.adicionaBeneficio).then(function(adicionado) { if (adicionado) console.log('Benefício adicionado’);}).catch(function(erro) { console.log(erro); });
DAO pattern
dao.porNome = function(nomeProcurado, cb) { db.collection('contatos') .findOne({nome : procurado}, function(erro, contato) { if (erro) cb('Não foi possível…', null); cb(null, contato); });};dao.dependenteDoContato = function(contato, cb) { db.collection('dependentes') .find({contatoId : contato_id}, function(erro, dependente) { if (erro) cb('Não foi possível…’, null); cb(null, dependente) ; });};(…)
DAO + Promise Pattern
dao.porNome = function(nomeProcurado) { return Q.Promise(function(resolve, reject) { db.collection('contatos') .findOne({nome : procurado}, function(erro, contato) { if (erro) reject(erro); resolve(contato); }); });};dao.dependenteDoContato = function(contato) { return Q.Promise(function(resolve, reject) { db.collection('dependentes') .find({contatoId : contato_id}, function(erro, dependente) { if (erro) reject(erro); resolve(dependente) ; }); }); };(...)
Promise Pattern
dao.porNome('Flávio Almeida').then(dao.depententeDoContato).then(dao.adicionaBeneficio).then(function(adicionado) { if (adicionado) console.log('Benefício adicionado');}).catch(function(erro) { console.log(erro); });
Synchronous Heaven
try { var contato = dao.porNome('Flávio Almeida'); var dependente = dao.depententeDoContato(contato); console.log(dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
Mas eu ainda quero o paraíso!
Promise Pattern
dao.porNome('Flávio Almeida').then(dao.depententeDoContato).then(dao.adicionaBeneficio).then(function(adicionado) { if (adicionado) console.log('Benefício adicionado’);}).catch(function(erro) { console.log(erro); });
Q.async(function*() {try { var contato = yield dao.porNome('Flávio Almeida'); var dependente = yield dao.depententeDoContato(contato); console.log(yield dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}}).done();
É quase um paraíso
Synchronous Heaven
try { var contato = dao.porNome('Flávio Almeida'); var dependente = dao.depententeDoContato(contato); console.log(dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
Permite suspender a execução no meio de uma função para mais tarde retomá-la
Generator
Generatorfunction * meuGerador() { var num1 = 1; var num2 = 2; var num3 = 3; yield num1; yield num2; yield num3;}
var gerador = meuGerador();console.log(gerador.next().value); // 1console.log(gerador.next().value) // 2console.log(gerador.next().value) // 3console.log(gerador.next().value) // undefined
Generators e Promises
Q.async(function*() {try { var contato = yield dao.porNome('Flávio Almeida'); var dependente = yield dao.depententeDoContato(contato); console.log(yield dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}}).done();
Synchronous Heaven
try { var contato = dao.porNome('Flávio Almeida'); var dependente = dao.depententeDoContato(contato); console.log(dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
Mas eu ainda quero o paraíso!
Synchronous Heaven
try { var contato = dao.porNome('Flávio Almeida'); var dependente = dao.depententeDoContato(contato); console.log(dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
try { var contato = yield dao.porNome('Flávio Almeida'); var dependente = yield dao.depententeDoContato(contato); console.log(yield dao.adicionaBeneficio(dependente));} catch(erro) { console.log(erro);}
Generators e Promises
E as ferramentas de BI do cliente?
Injection Free!
Injection Free
// Controller ExpressJS
controller.removeContato = function(req, res) { var _id = req.params.id; Contato.remove({'_id' : _id}).exec() .then(function() { res.status(204).end(); }, function(err) { return console.error(erro); } );};
{"_id" : 5}
{"_id" : { "$ne" : null}}
Injection Free???
// Controller ExpressJS
controller.removeContato = function(req, res) { var _id = req.params.id; Contato.remove({'_id' : _id}).exec() .then(function() { res.status(204).end(); }, function(err) { return console.error(erro); } );};
{"_id" : { "$ne" : null}}
Agora, Injection Free
// Controller ExpressJS
var sanitize = require(‘mongo-sanitize');
controller.removeContato = function(req, res) { var _id = sanitize(req.params.id); Contato.remove({'_id' : _id}).exec() .then(function() { res.status(204).end(); }, function(err) { return console.error(erro); } );};
Carlinhos Aguiar, document replace é uma …
PÉSSIMA IDEIA, SÍLVIO!
Document Replace
controller.salvaContato = function(req, res) { var _id = req.body._id; Contato.findByIdAndUpdate(_id, req.body).exec() .then( // código omitido );
Document Replace
controller.salvaContato = function(req, res) { var _id = req.body._id; var dados = { "nome" : req.body.nome, "email" : req.body.email }; Contato.findByIdAndUpdate(_id, dados).exec()
Pince os dados…
Sistema de Módulos
AMD CommonJSES6
http://addyosmani.com/writing-modular-js/
Sistema de Módulos
AMD CommonJSES6
http://addyosmani.com/writing-modular-js/
A luta deixa deixa de ser pela menor "impedância "e passa a ser por uma
standardization dentro do ecossistema JavaScript.
MANK
Alternativas à MEAN Stack
MRKN
MyEAN
METEOR
Obrigado!
@flaviohalmeida
flavio.almeida@caelum.com.br
FLÁVIO ALMEIDA
Perguntas?
Recommended