Desenvolvendo serviços web com Redstone.dart –



Desenvolvendo serviços web com Redstone.dart –

0 0


devfest_sp_2014


On Github luizmineo / devfest_sp_2014

Desenvolvendo serviços web com Redstone.dart

Luiz Henrique Farcic Mineo / @lhfmineo

O que é Dart?

  • Plataforma para desenvolvimento de aplicações web
  • 100% open source (BSD)
  • Pode ser executada no navegador web e no servidor

Como Dart funciona?

  • dart2js: Compila código Dart para Javascript
  • DartVM: Permite a execução de código Dart no servidor
    • Oferece APIs para acesso a recursos do sistema operacional

Por que usar Dart para criar serviços web?

  • Produtividade
    • Dart é uma linguagem moderna e flexível
  • Desempenho
    • A DartVM possui um desempenho competitivo
  • Suporte
    • Dart possui uma incrível e ativa comunidade
  • Integração
    • Compartilhe código com sua aplicação cliente

A linguagem Dart

  • Tipagem opcional
    //tipos não são obrigatórios
    var resposta = 42;
    
    //mas podem ser usados quando desejado
    int resposta = 42;
    					
  • Orientada a objetos, com suporte a classes
    class Pessoa {
    
      String nome;
      int idade;
      String endereco;
    
      Pessoa([this.nome, this.idade, this.endereco]);
    }
    
    var pessoa = new Pessoa("José", 35);
    					

A linguagem Dart

  • Programação assíncrona, com fila de eventos
  • Suporte nativo ao promise pattern
Future future = operacaoAssincrona();
future..then((resp) => print(resp))
      ..catchError((e) => print("erro: $e"));
					

A linguagem Dart

  • Parâmetros opcionais (posicionais e nomeados)
  • Herança múltipla com mixins
  • Getters e setters implícitos
  • Interface implícita
  • Funções como objetos de primeira classe
  • Módulos
  • Metadados

O que é Redstone.dart?

  • Framework para criação de serviços web
  • Motivação: lidar com o protocolo HTTP diretamente é chato e cansativo
import 'dart:io';

void main() {
  HttpServer.bind('0.0.0.0', 8080).then((server) {
    server.listen((HttpRequest request) {
      request.response
        ..headers.contentType = 
             new ContentType("text", "plain", charset: "utf-8")
        ..write('Olá, mundo!')
        ..close();
    });
  });
}
					

O que é Redstone.dart?

  • Redstone usa metadados para definir serviços
    import 'package:redstone/server.dart' as app;
    
    @app.Route("/")
    olaMundo() => "Olá, mundo!";
    
    main() {
      app.start();
    }
    					
  • Inspiração: Flask framework (Python)

Criando serviços

//Ex.: http://localhost:8080/ola/luiz
@app.Route("/ola/:usuario")
olaUsuario(String usuario) => "Olá, $usuario";

//Ex.: http://localhost:8080/usuario?id=1234
@app.Route("/usuario")
buscaUsuario(@app.QueryParam("id") int id) {
  ...
};

//Suporte a JSON
@app.Route("/usuario", methods: const [app.POST])
salvaUsuario(@app.Body(app.JSON) Map json) {
  ...
};

//Suporte ao objeto Future
@app.Route("/usuario/:id")
Future<Map> buscaUsuario(int id) =>
  database.find(id);
					

Interceptadores

  • Podem ser usados para aplicar um comportamento comum a um conjunto de serviços
  • Similares aos filtros do JEE, porém com uma API assíncrona
  • Exemplo: configuração do cabeçalho de resposta
    @app.Interceptor(r'/.*')
    handleResponseHeader() {
    
      app.chain.next(() 
        => app.response.change(headers: 
           {"Access-Control-Allow-Origin": "*"}));
    
    }
    					

Tratadores de erro

  • Erros são interceptados através do código HTTP
    @app.ErrorHandler(404)
    recursoNaoEncontrado() => app.redirect("/error/not_found.html");
    					
  • Se um serviço lança uma exceção, o código 500 é associado a requisição
    @app.ErrorHandler(500)
    erroInterno() {
      //exceção gerada
      print(app.chain.error);
    }
    					

Grupos

  • Grupos são usados para agrupar serviços, interceptadores e tratadores de erro
    @Group("/usuario")
    class Usuario {
    
      //Ex.: http://localhost:8080/usuario/buscar?n=luiz
      @app.Route("/buscar")
      buscar(@app.QueryParam("n") String nome) {
        ...
      }
    
      @app.Route("/salvar", methods: const [app.POST])
      salvar(@app.Body(app.JSON) Map json) {
        ...
      }
    }
    					

Plugin redstone_mapper

  • Permite serializar facilmente objetos Dart para JSON
    class Usuario {
    
      @Field() String nome;
      @Field() int idade;
    
    }
    
    //conteúdo da requisição é convertido
    //de JSON para Usuario
    @app.Route('/usuario', methods = const[app.POST])
    salvaUsuario(@Decode() Usuario usuario) {
      ...
    }
    					

Plugin redstone_mapper

  • Oferece integração com banco de dados
    • MongoDB
      //Retorno da função é convertido para JSON
      @app.Route("/usuarios")
      @Encode()
      Future<List<Usuario>> buscaUsuarios() => 
        //busca documentos da coleção 'usuarios',
        //e os converte para List<Usuario>
        mongoDb.find("usuarios", Usuario); 
      					
    • PostgreSQL
      //Retorno da função é convertido para JSON
      @app.Route("/usuarios")
      @Encode()
      Future<List<Usuario>> buscaUsuarios() => 
        //busca registros da tabela 'usuario',
        //e os converte para List<Usuario>
        postgreSql.query("select * from usuario", 
            Usuario);
      					

Outros recursos

  • Suporte a injeção de dependências
  • Suporte a testes unitários
  • Integrado ao Shelf framework
  • Suporte a web sockets (plugin redstone_web_socket)
  • Pode ser implantado facilmente no Heroku e outras soluções de cloud computing

Obrigado!