Darter: RESTful APIs em Dart

Lembram da última publicação que escrevi falando sobre as ferramentas disponíveis em Dart para criar APIs RESTful? Eu reclamei de algumas características que essas ferramentas não tinham, certo? E como resolver isso? Uma forma seria contribuir para o Redstone, por exemplo. Só que, infelizmente, não dá para modificar o Redstone para permitir o controle de versionamento de APIs, conforme você pode ver nessa issue que abri lá. Outra forma seria trabalhar em cima do RPC da Google. Só que nesse eu não abri issues e nada. hehe. Resolvi logo partir para a violência: criar uma biblioteca própria, considerando não cometer as mesmas falhas que encontrei nessas duas.

O meu guia de referência para essa biblioteca foi o Grape, para Ruby. Em minha opinião, é o framework, para desenvolver APIs RESTful, mais completo e simples de ser usado, independente de linguagem. Uso ele para todas as minhas APIs. Entretanto, é óbvio que não pude criar uma DSL em Dart, já que essa linguagem não dá facilidades para fazer isso da mesma forma como Ruby. Precisei usar a maneira Dart de codificar. Acho que o resultado ficou bom!

Darter

Apresento-lhes o Darter! Meu primeiro projeto open-source para Dart. Ele está servindo para muitos propósitos: estou aprendendo a fundo a linguagem, estou me divertindo pacas e estou contribuindo! O Darter ainda não está em versão final. Precisa de melhorias e correções. Como ainda estou na fase de codificação para provar meu conceito, ainda não escrevi os testes. E, por favor, deixa de #mimimi se isso é certo ou errado, preferi primeiro validar minha ideia para depois partir para tornar a ferramenta mais madura, com testes, exemplos e etc.

Mas, já é possível usá-lo? É sim, companheiro. O Darter já está no Github mas ainda não publicado no Pub. Inclusive, estou escrevendo todo um projeto em cima dele e que também está no Github aqui. Trata-se do meu “projeto-prova-de-conceito”. Ele está totalmente funcional! Agora, vamos ver como funciona o Darter?

 

Exemplo de Uso

O primeiro passo é criar uma classe e anotá-la com @API, assim como fizemos no exemplo abaixo. Observe que esta anotação precisa do argumento path. No caso abaixo, teremos uma rota da seguinte forma: http://localhost/categories.

import 'package:darter/darter.dart';
@API(path: 'categories') 
class MyDarterAPI { }

Depois disso, você já pode iniciar a criação de seus métodos que irão tratar as diversas requisições. Para isso, precisamos usar as anotações @GET@POST@PUT@DELETE e @PATCH. Vamos incrementar a classe acima para refletir isso!

import 'package:darter/darter.dart';

@API(path: 'categories')
class MyDarterAPI {

    @GET()
    List<MyModel> list() {
    }

    @GET(path: ':id')
    MyModel get(Map pathParams) {
    }

    @PUT(path: ':id')
    MyModel put(PathParams params, MyModel myModel) {
    }

    @POST()
    MyModel post(MyModel myModel) {
    }

    @DELETE(path: 'id')
    void delete(Map pathParams) {
    }
}

Observe que omiti o corpo dos métodos, pois meu objetivo é só exemplificar o Darter. Como era de se esperar, com essa classe aí, teremos as rotas:

  • GET http://localhost/categories
  • POST http://localhost/categories
  • PUT http://localhost/categories/<id>
  • GET http://localhost/categories/<id>
  • DELETE http://localhost/categories/<id>

Parâmetros

No exemplo que vimos na seção anterior, note que recebemos como parâmetro um objeto MyModel em alguns casos, enquanto em outros, recebemos um Map. No primeiro caso, o Darter tenta transformar os parâmetros encontrados em uma classe de negócio da sua aplicação. Por exemplo, suponha que você envia uma String JSON para o Darter e seu método tem como parâmetro um objeto de negócio. O Darter vai criar esse objeto e preencher seus atributos com os valores obtidos do JSON.

Mas, é claro, isso não abrange todos os cenários, certo? Claro que não. Existem os Path parameters e Query parameters. E como ter acesso a eles? Através de uma convenção bem simples: crie um parâmetro do tipo Map e dê o nome de pathParams ou queryParams. Você pode me perguntar porque não fiz igual ao JAX-RS (Java), que tem anotações @PathParam e @QueryParam. Simplesmente porque eu acho essa solução feia, medonha. Polui seu código.

Em minha humilde opinião, é muito mais simples e clean você receber um Map contendo os dados. Rápido, caceteiro, simples e eficiente.

Versionamento

Opa! Você não reclamou tanto de versionamento nas outras ferramentas? Sim! E fiz isso de forma mais flexível no Darter! Vamos melhorar a classe anterior (vou omitir agora os métodos só para exemplificar o versionamento).

@API(path: 'categories')
@Version(version: 'v1', vendor: 'company', format: Format.JSON, using: Using.HEADER)
class MyDarterAPI { }

O Darter permite usar dois tipos de estratégias de versionamento: por path e por header. No caso do header, exemplificado acima, você precisa usar a anotação @Version e informar quatro argumentos obrigatórios. Por que? Porque o Darter vai procurar por isso no cabeçalho Accept. Como? Ele espera que esteja no formato application/vnd.<vendor>.<version>+<format>. Entendeu agora o motivo dos argumentos extra? No caso acima, ele espera o cabeçalho formatado assim application/vnd.company.v1+json.

E caso você queira o versionamento no path? Eu não aconselho essa estratégia, mas ela existe e eu não poderia deixar ela de fora. Neste caso, basta modificar a anotação e esquecer os parâmetros extras.

@API(path: 'categories')
@Version(version: 'v1', using: Using.PATH)
class MyDarterAPI { }

Nesta estratégia, você terá a URL http://localhost/v1/categories.

Error Handlers

Suponha que seu método recebe um ID e você vai buscar esse ID na base de dados. Seu mecanismo de busca não encontra e lança uma exceção chamada ObjectNotFoundException. O que sua API deve fazer com essa exceção? O correto é pegar essa exceção e retornar na API um status 404 e uma mensagem de erro! O Darter facilita isso? Claro!

@API(path: 'categories')
@Version(version: 'v1', using: Using.PATH)
class MyDarterAPI { 
    
    @ErrorHandler
    Response handleObjectNotFound(ObjectNotFoundException ex) {
    }

}

A partir deste método, você pode retornar um objeto Response ou qualquer outro objeto, inclusive seus models. Observe que o parâmetro do método deve ser exatamente o tipo da exceção que você quer tratar. E caso você tenha mais de um handler com o mesmo parâmetro? O Darter pega o primeiro e ignora os outros, então, tome cuidado.

Interceptors

Agora, imagine outra situação: você precisa validar antes se o usuário tem permissão de acesso à sua API! Como fazer isso? Com interceptors, meu caro. Um interceptor, como o próprio nome já diz, intercepta uma requisição para que você possa tratar ela. Essa interceptação pode ocorrer antes ou depois que seu método seja chamado. Ah! E você também pode definir a ordem de execução dos interceptors! Vamos deixar de blá blá blá e ver um exemplo?

@Interceptor(when:Interceptor.BEFORE, priority: 1)
class Authentication {

    void intercept(Chain chain) {
        String token = chain.request.headers["X-Token"];
        if (token != "Test") {
          chain.abort(new Response()
            ..body = "{\"error\":\"Permission Denied\"}"
            ..statusCode = 401);
        }
    }
}

Você deve primeiro criar uma classe e anotá-la com @Interceptor, fornecendo dois parâmetros: quando ele será executado e sua prioridade. Em seguida, e isso é uma convenção, crie um método chamado intercept que recebe o parâmetro Chain. O objeto chain lhe dá acesso apenas ao Request, quando é um interceptor BEFORE, e acesso ao Request e Response quando é um interceptor AFTER.

Iniciando

Para fechar o exemplo, só precisamos iniciar o servidor, né? E isso é fácil! Basta criar uma instância de DarterServer, adicionar suas APIs e interceptors e mandar bala com start().

main() {
  new DarterServer()
    ..addApi(new MyDarterAPI())
    ..addInterceptor(new Authentication())
    ..start();
}

Vai me perguntar porque não fiz reflexão para encontrar as classes anotadas? Achei o mecanismo de mirrors do Dart muito massa, mas um pouco complicado de escanear o classpath de sua própria aplicação em busca das classes. Achei oneroso e propenso a erros. Até mesmo o RPC, do próprio Google, não faz isso. Então, resolvi ir na mesma onda deles! 🙂

Conclusão

Gostou? Achou a ideia interessante? Agora vem a parte mais legal: o projeto ainda está em estágios iniciais e, portanto, sua ajuda não é só permitida, é altamente desejada. Não precisa ser necessariamente com código, mas com sugestões de melhorias, testes e etc. Vamos lá? Manda suas dicas nos comentários!

Ah! Por último, porque o nome Darter? Em primeiro lugar, é óbvio, é pelo trocadilho com o nome da linguagem. Mas só isso não bastaria, eu também quis salientar a leveza e liberdade de um pássaro para voar da forma como quiser. Dois princípios que pretendo manter na biblioteca! O pássaro é esse da foto do post!

Dart: Syntax Sugar!

Que Dart é bacana, isso todo mundo sabe, certo? Mas, por que Dart é bacana mesmo? Um dos motivos é o que chamamos de syntax sugar. O que é isso? São facilitadores que a linguagem traz para que você faça tarefas muito comuns de forma mais fácil, com menos linhas de código. Algumas pessoas acham que syntax sugar é para os fracos. Outros dizem que é pura frescura. Ah vai, para! Se uma linguagem me dá uma forma de fazer uma coisa com menos trabalho, é claro, óbvio, cristalino, inteligente e outros mil bons adjetivos que eu quero usar isso!

Então, vamos começar falando sobre os syntax sugar que o Dart fornece para…

Construtores

Imagine, por exemplo, que você queira criar um construtor que recebe dois parâmetros e que atribui esses dois parâmetros para dois atributos que tem o mesmo nome. Trata-se de uma tarefa bem comum, certo? Então, porque não facilitar? Dart facilita. Vejamos como:

class Pessoa { 
   String nome; 
   String endereco; 

   Pessoa(this.nome, this.endereco); 
}

Pessoa marlon = new Pessoa("Marlon", "Rua dos Dartisans");

Lindo, não é? Observe que sua classe em Dart tem dois atributos e apenas um construtor, que recebe como parâmetro o nome e o endereço e já atribui o valor destes dois parâmetros para os atributos. Outro detalhe importante: essa atribuição ocorre antes de o corpo do construtor ser executado! Mas, peraí, e se eu precisar colocar um código no corpo desse construtor? Sem problemas.

class Pessoa { 
   String nome; 
   String endereco; 

   Pessoa(this.nome, this.endereco) {
      if(this.nome == "Marlon") {
         this.nome = "Marlon S. Carvalho";
      }
   }
}

Pessoa marlon = new Pessoa("Marlon", "Rua dos Dartisans");

Agora, e se sua classe herda de uma classe-pai e você precisa chamar o construtor do pai? Muito simples, meu caro, pois basta colocar um logo depois do construtor e chamar o construtor do pai. Observe também que você pode continuar usando a atribuição que vimos no exemplo anterior. Olha esse exemplo:

class Pessoa { 
   String nome; 
   String endereco; 

   Pessoa(this.nome, this.endereco);
}

class PessoaInteligente extends Pessoa {
    double qi;

    PessoaInteligente(nome, endereco, this.qi): super(nome,endereco) {
    }
}

Operador em Cascata

O operador em cascata é outro syntax sugar bem bacana. Quem nunca se deparou com a situação em que você precisa chamar diversos métodos de um objeto em sequência? Isso sempre acontece, né não? Principalmente quando você está inicializando um model ou entity e atribuindo aos seus atributos valores oriundos de um formulário HTML.

Pessoa pessoa = new Pessoa();
pessoa
    ..nome = "Marlon"
    ..endereco = "Rua dos Dartisans"
    ..save();

Métodos Assíncronos

Esta é bem recente e eu o considero como um syntax sugar também. Para você entender bem esse syntax sugar, lembre-se de como você trata requisições assíncronas com Javascript. Lembrou? Horrível, certo? Em Javascript temos o conhecido callback hell. Você precisa encadear um monte de funções de callback para atender a duas ou três chamadas assíncronas. Algo assim:

funcao_assincrona("param1", function(resultado) {
    funcao_assincrona2(resultado, function(resultado2) {
        funcao_assincrona3(resultado2, function(resultado3) {
            // Enfim, podemos fazer algo!
        });
    });
});

Meu amigo, esse código aí é feio demais! Nas primeiras versões do Dart, você também precisava fazer algo parecido com isso. A única diferença é que nós tínhamos a classe Future, mas a ideia era a mesma. E como o Dart resolveu isso? Com a biblioteca dart:async. Olha como as coisas agora ficaram lindas!

var resultado1 = await funcao_assincrona("param1");
var resultado2 = await funcao_assincrona2(resultado1);
var resultado3 = await funcao_assincrona3(resultado2);

Muito melhor, não? Com await, você programa quase como se estivesse programando um código síncrono. Quer saber mais sobre isso? Clica aqui.

Finalizando

Você acha que esqueci de citar alguma outra syntax sugar bacana do Dart? Então deixa um comentário! Eu adicionarei sua sugestão no artigo e com a devida citação para o autor.

APIs RESTful com Grape – Parte 1

Não é novidade para ninguém qual é a minha linguagem de programação favorita ultimamente. Ruby, oras! Provavelmente, também não é mais novidade para ninguém que venho focado em um único assunto: desenvolvimento de APIs RESTful. Inclusive, fazendo palestras aqui em Salvador. Então, como juntar esses dois mundos (Ruby + APIs)? A resposta é Grape! Um framework espetacular, que provê uma DSL muito simples e que facilita brutalmente a vida dos desenvolvedores de APIs.

Entretanto, percebi um probleminha! Não encontrei um tutorial sequer na Internet, sobre esse assunto, escrito em português ou espanhol. Péssimo! Portanto, meu objetivo aqui é escrever uma série de publicações sobre como instalar, configurar e usar o Grape para criar suas APIs. Primeiro, será um post em português, depois, me arriscarei a escrever em espanhol também. Será duplamente útil, porque terei a oportunidade de por em prática meus estudos de espanhol. 🙂

API do Bebum

Nosso projeto será uma API para um sistema que disponibilizará informações sobre cervejas. Começaremos com apenas dois modelos: Cerveja e Tipos de Cervejas. Futuramente, poderemos avançar, incluíndo mais modelos e incrementando nossa API! Todo o código que vocês verão aqui estará no Github, no endereço https://github.com/marloncarvalho/bebum-api.

Preste atenção que estamos seguindo rigorosamente (ou o máximo que pudermos) o modelo REST para a criação de APIs. Observe também que estou criando Tags no repositório com os nomes das partes de cada artigo. Por exemplo, teremos a Tag Parte 1, Parte 2 e assim por diante!

Montando seu Ambiente

Sou fã de Mac de longa data, portanto, vou focar basicamente nesta plataforma. Mas, como Mac é um *NIX, a maioria das coisas que farei aqui são replicáveis em um ambiente Linux. Quanto aos usuários Windows… bom, aí não tenho muito a ajudar, pois já tem 10 anos que não uso esse ambiente. Inicialmente, você precisa ter o interpretador Ruby instalado. No meu caso, eu uso o RVM – Ruby Version Manager para esta tarefa. O RVM instala e gerencia as versões do Ruby que você tem em sua máquina. Sugiro fortemente usá-lo!

Instalando o Ruby com o RVM

Para instalar o RVM, conforme descrito na página deles, basta digitar no console:

\curl -sSL https://get.rvm.io | bash -s stable

Depois disso, vamos instalar o Ruby na versão 2.1.2 usando o comando:

rvm install 2.1.2

Com o Ruby instalado, vamos agora instalar o Gem do Grape digitando no console:

sudo gem install grape

Pronto, seu ambiente está montado para nosso primeiro projeto com Grape. Fácil, não?

Bundler

Você já conhece o Bundler? Ainda não? Que feio! O Bundler é um gerenciador de dependências para Ruby. Com ele, fica mais fácil você definir quais gems seu projeto necessita e baixá-los. Caso ainda não o tenha instalado, faça gem install bundler no seu console para instalá-lo. O Bundler espera que você tenha um arquivo Gemfile na raiz do seu projeto. Neste arquivo, você deve listar cada Gem que seu projeto depende. Uma vez que você cria este arquivo, basta digitar bundle install no console, dentro do diretório onde está o arquivo Gemfile, para que ele baixe as dependências.

Estrutura do Projeto

Eu poderia começar com uma estrutura extremamente enxuta, mas seria simplista demais e já existem dezenas de artigos em inglês ensinando a usar o Grape que já fazem isso, então… Nosso próximo passo agora é montar a estrutura do nosso projeto. Crie um diretório qualquer em sua máquina e monte uma estrutura de diretórios semelhante à da imagem abaixo. Você também tem a possibilidade de baixar essa estrutura direto do nosso repositório.

Estrutura detalhada de diretórios do nosso projeto.

Esta é uma estrutura que eu sugiro, mas não significa que você deve utilizá-la sempre. Fique à vontade para modificá-la, conforme suas necessidades. Outro detalhe digno de nota é que ainda faltam alguns diretórios nessa estrutura. Por exemplo, ainda precisamos dos diretórios db e spec, mas faremos isso nos próximos artigos.

Nesta estrutura, o diretório app conterá todas as classes relacionadas ao negócio da nossa aplicação. Este diretório é subdividido em api models, onde api manterá somente as classes responsáveis em manter a lógica da nossa API RESTful e models conterá as classes de modelo, onde estarão, de fato, nossas regras de negócio.

Já o diretório api é subdividido em outros dois subdiretórios, chamados v1 v2. Esta divisão é interessante para facilitar a criação de novas versões da nossa API. Observe que tanto dentro de app, como dentro de v1v2, existe um arquivo chamado base.rb. Eles estão aí para unir em um único ponto todas as APIs que disponibilizaremos. Não se preocupe se ainda está confuso, pois detalharemos esses arquivos com cuidado a seguir. Dentro dos diretórios v1 v2 ainda temos uma pasta entities, que será responsável em manter as classes que irão expor os dados do nosso sistema em um formato de recursos.

Finalizando, o diretório model não tem nenhum subdiretório. Todos os demais arquivos são velhos conhecidos de todo programador Ruby e não vou detalhá-los aqui!

Modelos

Vamos nos focar agora na pasta models, onde temos, até este momento, apenas um arquivo chamado model.rb. Este arquivo contém as nossas classes de modelo. Obviamente, você pode, caso prefira, separar as classes em arquivos distintos. Talvez façamos isso no futuro, entretanto, para simplificar, vamos deixar em apenas um arquivo.

module Models

   # Cervejas.
   class Cerveja
      attr_accessor :id, :nome, :tipo
   end

   # Tipos de Cervejas
   class Tipo
      attr_accessor :id, :nome
   end

end

Observe que são duas classes extremamente simples, ainda sem nenhuma lógica de negócio associada e também sem as informações de persistência. Vamos incrementá-las no futuro, entretanto!

Estrutura Geral da API

Vamos agora fazer nossa primeira API funcional. Vamos iniciar analisando a pasta api. Observe o arquivo base.rb. Ele é extremamente simples, pois serve apenas para agrupar TODAS as versões que estamos disponibilizando da nossa API. É óbvio, entretanto, que normalmente liberamos apenas duas versões por vez. Mas, caso seja necessário, esta estrutura nos permite disponibilizar quantas versões acharmos necessárias.

require 'api/v1/base'
require 'api/v2/base'

module API

   class Base < Grape::API
      mount API::V1::Base
      mount API::V2::Base
   end

end

Este arquivo tem um módulo chamado API e dentro dele há uma classe chamada Base que estende de Grape::API. Logo em seguida, montamos as APIs que queremos exibir. No nosso caso serão API::V1::Base e API::V2::Base. Como você deve estar imaginando, essas classes estão definidas nos arquivos /app/api/v1/base.rb /app/api/v2/base.rb. São duas versões da mesma API!

Agora, vamos bisbilhotar o arquivo /app/api/v1/base.rb. Ele tem um pouco mais de informações. Inicialmente, continuamos criando o módulo API, mas agora temos outro módulo dentro dele, chamado V1. Depois, definimos a classe Base, que monta as APIs de Cervejas e Tipos. Essas duas APIs estão definidas nos arquivos api/v1/cervejas.rb api/v1/tipos.rb.

Também definimos algumas informações importantes sobre essa API. Definimos que a versão da API será obtida através do cabeçalho Accept do HTTP. Para que esta versão da API seja invocada, o cabeçalho Accept deverá estar escrito assim: application/vnd.alienlabz-v1+json. Isto é um padrão, não se preocupe em entender os motivos de ele estar definido assim. Obviamente, caso queira acessar outra versão da API, basta trocar o v1 por v2, por exemplo.

Não entraremos em detalhes da estrutura do diretório v2, pois ele está exatamente da mesma forma que o v1, já que ainda não temos nenhuma intenção de lançar uma versão 2.0 da API.

API de Tipos de Cervejas

Analisemos agora o arquivo /api/v1/tipos.rb. Ele inicia, como deveria ser, com a definição dos módulos APIV1. Logo em seguida, cria a classe Tipos herdando de Grape::API. Lembre-se, toda classe que representa uma API deve herdar desta classe do Grape. Agora a mágica começa a acontecer. Observe a definição do bloco resources. Ele serve para definir um namespace, dentro do qual estaremos servindo dados sobre um determinado recurso que estará disponível através de nossa API. No nosso caso, temos um recurso chamado Tipos, certo? Portanto, usamos o símbolo :tipos para criar o bloco de recursos referentes ao recurso tipos. Trocando em miúdos, isto significa que teremos uma URL do tipo http://localhost:port/tipos. Seguindo, definimos outro bloco, agora chamado de get.

module API
   module V1
      class Tipos < Grape::API
         resources :tipos do
            # Obter uma lista de Tipos de Cervejas
            get do
               tipo = Models::Tipo.new
               tipo.id = 1
               tipo.nome = 'Pilsen'
               [tipo]
            end
         end
      end
   end
end

Observe atentamente esse método e tenha em mente que o Grape é uma DSL (Domain Specific Language). O que estamos fazendo nesta linha é chamar o método get (definido em Grape::API) passando como parâmetro a String ‘:id’ e um bloco de código que será chamado futuramente. Parece confuso? Mas é mais simples do que você pensa e é por isso que eu amo Ruby! O que estamos fazendo é informando ao Grape que temos uma rota ‘http://dominio/tipos/id’, acessível através do método GET do HTTP. Dentro do bloco de código, você escreverá o código que tratará toda requisição que chegar a essa rota através de um GET. Simples, certo? Lógico que é!

Nossa primeira API RESTful com Grape está quase pronta!

Configurando o config.ru

Ainda precisamos configurar o arquivo config.ru para conseguirmos rodar nosso projeto. Este arquivo contém os requires mais genéricos, necessários para rodar nosso projeto, como o graperubygems e rack. Depois, usamos o CORS para liberar as requisições cross-origin para todos os métodos HTTP (GET, POST,…). No final, rodamos a API com run API::Base. Observe que só precisamos de um require de módulos de nosso projeto: require ‘api/base.rb’.

$:.unshift "./app"

require 'rack/cors'

require 'rubygems'
require 'grape'
require 'rack'
require 'grape-entity'

require 'api/base.rb'

use Rack::Cors do
   allow do
      origins '*'
      resource '*', headers: :any, methods: [:get, :post, :put, :delete, :options, :patch]
   end
end

run API::Base

Feito isto, agora vá no seu console e digite rackup. Sugiro instalar o Chrome junto com o plugin Postman. É um excelente plugin para executar chamadas a APIs RESTful. Veja abaixo como chamar nossa API na versão 1.

Usando o Postman para chamar nossa API.

 Pronto, meu caro, já temos nossa primeira versão da API executando! Não acredita? Testa aí! Nos próximos artigos, vamos fuçar mais o Grape, usando mais features dele. O objetivo deste primeiro artigo foi criar a estrutura e colocar uma primeira API simples executando!

Android Cards

Vocês conhecem aqueles Cards da DZone? Eu acho eles sensacionais. Trazem um resumão sobre um determinado assunto em um formato de fácil consulta. Até impresso fica bem bacana. Pra quem tem tablet, também fica sucesso. Eu já gostava deles, mas sinto falta de uns cards mais específicos, menos “genéricos”.

Ultimamente teve um aumento na demanda por cursos de Android e uma forma que achei de me manter atualizado, relembrar e compartilhar esses estudos é fazendo uns cards bem no estilo dos RefCards da DZone. A diferença é que vou abordar de forma resumida cada assunto do Android. Por exemplo, farei cards sobre Activity, SQLite, SharedPreferences e por aí vai. Já comecei a fazer alguns e deixarei eles sob a licença Creative Commons – Attribution-NonCommercial-ShareAlike 3.0.

Fiz eles usando o Pages, para o Mac. Tanto os arquivos fonte (.pages) como os arquivos em PDF estão disponíveis em meu perfil no Github. Portanto, para quem quiser usar, compartilhar, melhorar e por aí vai, acessem o endereço  https://github.com/marloncarvalho/curso-android.

Espero que gostem!

Alfred is Alive!

Você já conhece o Alfred? Não? Que zorra é essa? É um projeto que criei já a algum tempo e que contém milhares de centenas de dezenas de milhões de utilitários e afins para você criar sua aplicação muito louca em Java. Como assim? Seguinte, sua aplicação precisa ter as dezenas sorteadas da megasena? O Alfred ajuda. Da quina? O cara também ajuda. E precisa de algumas formatações, validações e afins? O maluco aí ajuda pacas! Ou então, a lista de bancos cadastrados na Febraban? Alfred é o cara pra isso. Teste a versão 1.X do Alfred que está no Google Code no endereço http://alfredlibrary.googlecode.com/.

Agora, você em sua total sapiência me pergunta: e daí, cara? Deixe de ser miserável e entenda o seguinte: o Alfred vai mudar. Aliás, já mudou. Ou não. Mudou sim. Agora ele está no Github no endereço http://www.github.com/alfredlibrary/. E é só isso? Porra nenhuma! O projeto vai ser reestruturado totalmente e absolutamente. Estou pensando em diversas melhorias para ele, além de uma reestruturação catastrófica! Agora não será apenas um único “jar” contendo tudo. Quero separar por funcionalidades. Tipo assim: vai ter um repositório no Github para o projeto “postal-services”, no qual você terá todas as funcionalidades para serviços postais. Este projeto gera um jar separado que pode ser adicionado ao seu projeto. Captou a ideia?

E o que mais? Ah! Quero uma integração com o CDI também. Aí você poderá injetar os serviços do Alfred apenas com um @Inject. Sucesso, né não? O Github já vai ajudar substancialmente no recebimento de contribuições, não tenho dúvidas. Outro detalhe, a API será totalmente refeita, mas agora em inglês. A questão de ter apenas métodos estáticos também não será uma regra e talvez a não dependência de APIs externas também. Tudo depende, é caso a caso.

Maluco, é o seguinte: quero sua ajuda. Precisamos de sua ajuda. Ajude mesmo! Deixe de preguiça, na moral! Contribua com código. Esculhambe quando é pra esculhambar. Chame o autor do código de anta quando é pra chamar, mas não fique calado, não. Senão eu que vou lhe esculhambar. Faz um follow no projeto no Github. Faz logo seu fork, agora, sem demora, sem pestanejar e sem pensar! Aja na emoção e faça isso logo. Eu imploro!

DSL no DemoDroid

Eu curto muito estas linguagens novas, como Groovy e Ruby. A sintaxe delas permite fazer códigos lindos. A melhor parte, para mim, é poder criar uma DSL de forma fácil e bem intuitiva. No Java, também é possível, mas não fica tão bonito como ficaria em um Groovy, por exemplo. Ah! Você está por fora do que é uma DSL? Tradução: Domain Specific Language. Eu gosto de dizer que uma DSL pode ser vista como um subconjunto de uma linguagem, ou até mesmo uma linguagem própria, para resolver problemas específicos.

Você vai por aí muitas DSLs. Já encontrei o Mirror, que é uma DSL para usar Reflexão em Java. Parece-me que é um projeto de brasileiros. Então, fica aqui meus parabéns! E você pode criar DSLs para diversos tipos de situações específicas. Olha como é o código do Mirror para definir o valor de um atributo de um objeto:

new Mirror().on(target).set().field(fieldName).withValue(value)

Percebe como a leitura deste código parece mais natural do que aquele monte de linhas da API de Reflection do Java? Você pode até ler naturalmente como: Mirror (new Mirror()), no (on) objeto tal (target) defina (set) o atributo tal (fieldName) com o valor tal (withValue). Bacana, né não? E que diabos eu quero com esse blá blá blá? Vamos lá! Nessa ideia de DSL, é que eu resolvi criar uma para incorporar no DemoDroid. Uma coisa recorrente no desenvolvimento em Android é precisar disparar uma tarefa que leva um tempo razoável de processamento e você quer exibir uma mensagem de progresso.

Para quem já programa em Android, sabe que é necessário usar a class android.os.AsyncTask. Veja abaixo um exemplo de utilização dela, retirado do BrasileirãoZ:

new AsyncTask<Void, Void, List<Jogo>>() {

	private ProgressDialog dialog;
			
	protected List<Jogo> doInBackground(Void... params) {
		try {
			return campeonato.getRodada(final_rodada).getJogos();
		} catch (Exception e) {
			messageContext.add("Erro");
		}
		return new ArrayList<Jogo>();
	}

	protected void onPreExecute() {
		if (dialog == null) {
			dialog = ProgressDialog.show(getView(), "Consultando...", "Obtendo Jogos.", true);
		}
	}

	protected void onPostExecute(java.util.List<Jogo> result) {
		JogosPresenter.this.getView().setJogos(result);
		JogosPresenter.this.getView().setRodada(final_rodada);
		dialog.dismiss();
	}
}.execute();

Nada mal, não é? Um monte de linha de código para fazer muito pouca coisa. E também pouco intuitivo para quem está lendo. Uma pessoa que pega este código para ler, precisa ter um conhecimento bem legal da classe AsyncTask para poder usá-la. E olhe que esta classe do Android até que é bem simples. Existem outras muito mais difíceis. E por que não trocar este monte de linha de código, por isso aí embaixo? Não acha mais intuitivo? Claro, ainda posso melhorar e fica aí para você me sugerir melhorias. Esse código faz um processamento muito semelhante ao daí de cima:

new Async()
	.using(getView())
	.call("getJogos").on(event.getClube()).noArgs()
	.during().show("Consultando...", "Obtendo Jogos do Clube.")
	.after().call("setJogos").on(getView()).withResultAsArg()
	.occurring().crash().alert("Tente novamente mais tarde",1)
	.occurring().success().alert("Jogos atualizados!", 1)
	.execute();  

Android: O Curso!

Gosta de programar? Já conhece o Android? Tem aquela vontade imensa de aprender a programar para Android e publicar várias aplicações no Android Market para ganhar aquela grana extra? Ah, entendi! Falta tempo para estudar através de livros e artigos. Aliás, você é daquelas pessoas que gostam de interagir com outras, trocar ideias ao vivo, tirar suas dúvidas rapidamente. Seja qual for seu perfil, se ligue nessa: estamos estruturando umas ideias para criar um curso de Android aqui em Salvador. Apresento-lhes o instrutor: eu mesmo!

As ideias são iniciais e seu feedback será essencial. O primeiro curso será para iniciantes mas que já tenham um entendimento bom de programação em Java. O objetivo é fazer um minicurso bem bacana. Vamos fugir do trivial “Professor Fala, Você Ouve, Você Acessa E-mail e Você Dorme”? Este tipo de aula é monótona e também acho que já está um pouco ultrapassada. Vamos aplicar Dojos e uma enorme interação entre todos os participantes! Vamos colocar um objetivo para o minicurso: criar uma aplicação e publicá-la na Android Market! Vamos ter um feedback rápido entre alunos e instrutor através dos Dojos, o que tornará o curso bastante dinâmico.

Não vamos apenas focar nas funcionalidades do Android, vendo componente por componente… Vamos passar dicas de como construir aplicativos bacanas. Vamos ver algumas técnicas que você pode usar ao programar para dispositivos. E como você pode entrar no Android Market para competir de verdade e não ser apenas mais um a fazer aplicativos meia-boca. Muita pretensão? Que nada, o negócio é pensar grande e sempre pra frente!

Você se pergunta: quem é esse cara que se acha bom o suficiente pra me ensinar Android? Já estou estudando Android desde o início do ano. Já tenho uma aplicação publicada lá, EncomendaZ. E o BrasileiraoZ já está bem próximo também. Ah, e não poderia esquecer do DemoDroid. Já tem um bom tempo que quero criar vídeo-aulas, tutoriais e um curso de Android. E chegou a hora. Acredito que tenho algo a contribuir na área!

E aí? O que acha? Topa? Tá colado na ideia? Deixe seu comentário e vamos tocar este curso pra frente! Se tem interesse em participar? Então, preencha este formulário. É importante para termos uma ideia da quantidade de pessoas interessadas! https://spreadsheets.google.com/embeddedform?formkey=dDlUT1E0VmtRdVFUd3NjbXpUUTNWMlE6MA

Quando o Maven vira um Tormento

Conhece o Maven? É uma ferramenta muito legal. Muito legal mesmo. Eu não o usava a até bem pouco tempo. Comecei a usar fortemente quando entrei pra equipe do Demoiselle. A partir daí, não consegui mais viver sem ele. E o principal motivo é o controle de dependências. É sucesso. É muito chato ter que sair procurando as dependências manualmente e incluir no seu projeto, né não? E quando tem versão nova de alguma biblioteca? É um saco ter que ir mudando tudo de novo! Ninguém merece.

E eu agora sempre uso o Maven para todos os meus projetos. E saiu colocando indiscriminadamente as dependências de que preciso. Sequer olho as dependências transitivas que cada projeto fornece consigo. Explicando para os incautos: dependências transitivas são aquelas dependências trazidas indiretamente por suas dependências diretas. Por exemplo, se seu projeto depende do Spring, você verá que não vem apenas o Jar do Spring, mas mais alguns que você nem esperava, como bibliotecas de log. E é aí que mora o perigo. Vou relatar para vocês como o aplicativo EncomendaZ saiu de 33mb de bibliotecas para 19mb. Vai ser um post meio que crítico e de desabafo. Vamos lá.

Começo alertando: usem o Maven com inteligência. Entendam que suas bibliotecas serão usadas em outros projetos e você não pode sobrecarregá-los com dependências desnecessárias. Veja na imagem abaixo uma pequena parte da árvore de dependências do EncomendaZ. Perceba a quantidade de dependências que existe. Você vai me perguntar: e você precisa de tanta dependência assim mesmo? Eu achava que sim. E agora descobri que não. Eu não entendia como um programa tão simples como o EncomendaZ poderia ter enormes 33mb de tamanho. Tinha algo errado.

Descobri erros dos mais simples a alguns gritantes. Vamos começar pelos mais loucos que vi. Estão vendo na imagem abaixo a biblioteca ezmorph? Ela é uma dependência indireta. E coloca indireta nisso. Mas, o mais curioso é você ver que o JUnit é uma dependência dele. Mas como “compile”?! JUnit é para ser uma dependência “test”. Esta biblioteca não é para ir junto com o deploy da aplicação. É apenas para estar na máquina dos desenvolvedores que realizam testes. Fail total!

Vamos a mais um exemplo, no mínimo, esquisito. Olha a imagem aí embaixo. É a biblioteca Jaxen. Eu sei que vocês já perceberam algo estranho. Por qual motivo uma versão mais recente de uma biblioteca precisaria depender de uma versão mais antiga dela mesma? Credo! Tem algo de errado com este projeto! Olha lá. A versão 1.1-beta-8 depende da versão 1.1-beta-6. Nunca tinha visto isso na minha vida. Eles devem ter um motivo, mas isto indica que tem algo de errado aí. Não faz sentido isso.

Mais uma. Tentem me explicar por qual motivo o Jasper Reports depende do jdtcore. Só tentem, porque não vão conseguir me convencer. Sabe o que é o JDT? Retirado do próprio site do Eclipse: “JDT Core is the Java infrastructure of the Java IDE“. WTF? Uma dependência de uma biblioteca da parte de infraestrutura do Eclipse? E o Jar dele é enorme, meu caro! Quase uns 4mb.

Agora chegamos na seção críticas construtivas. As críticas acima foram pra sacanear mesmo. Aliás, tem sacanagem maior do que fazer um POM porco como os caras acima fizeram? JUnit como compile? Haja paciência. Nesta sequência, quero apenas fazer um pedido para os criadores de bibliotecas. Modelem seus projetos pensando nas pessoas que irão usá-los. Seu projeto pode ser o MEGA-FAZ-TUDO, mas você não precisa incluir todas estas funcionalidades em um único módulo. Você acabará levando para o projeto dos outros dependências que eles podem não precisar. Vamos exemplificar.

Eu precisei gerar uma impressão no EncomendaZ e parti logo para o JasperReports. Mas minha impressão era bem simples. Eu não precisava gerar PDF. Não precisava gerar XLS. Era só mandar para a impressora e pronto. O JasperReports leva pra você, “de grátis”, o iText. Trata-se de uma ferramenta para geração de PDF. E o iText já lhe fornece o Bouncy Castle. Este último é uma biblioteca que será usada caso você queira assinar digitalmente seu PDF. O iText tem cerca de 2mb. O BouncyCastle uns 3mb. Veja a imagem abaixo.

Não acho a melhor estratégia embarcar o bcprov-jdk14 junto com o iText. Quantas pessoas vão querer realmente assinar digitalmente seus PDFs? Será que são tantas assim que é melhor incluí-lo logo? Eu, sinceramente, acho que não. Muito melhor seria o iText ter dois módulos: um core e outro que inclui assinatura digital. Teria me poupado 3mb. E digo mais, o JasperReports também poderia ter sido mais modularizado de forma que eu não precisasse trazer o iText caso não quisesse criar PDFs. Teria me poupado, agora, 5mb. Caso fossem mais modularizados, eu poderia ir escolhendo exatamente o que meu projeto necessita e não ficar criando EXCLUDES no meu POM. Esses excludes são chatos e poluem sensivelmente meu arquivo POM.

Eu sei que vocês perceberam mais um detalhe na última imagem. E é até engraçado. Não percebeu? Olha lá de novo. Tem uma dependência bcprov-jdk14 na versão 138 que o iText usa. E tem uma mesma bcprov-jdk14 mas na versão 1.38 de outra dependência. Sinistro, não? É simplesmente a mesma biblioteca mas com “groupId” e versões diferentes. Credo. Existia uma duplicidade de bibliotecas no meu projeto. Eram mais 3mb desnecessários.

Finalizando, quero deixar um alerta e um apelo! Cuidado com seus projetos Maven. Não coloquem indiscriminadamente as dependências. Analisem exatamente o que você precisa. No meu caso, eu precisava do JasperReports, mas não precisava de muitas das dependências transitivas que ele trazia. Consegui tirar quase 6mb de dependências indiretas só do JasperReports. O apelo fica para quem disponibiliza seus artefatos Maven. Cuidem com carinho o seu POM. Muito carinho. Não façam asneiras como colocar o Junit como dependência compile. Cuidem bem do seu projeto para que uma versão mais recente não precise depender de uma mais antiga. E tentem modularizar para que seus usuários escolham exatamente o que precisam e não sobrecarreguem seus projetos com megabytes a mais que são desnecessários. Vocês não tem ideia de quanto os usuários do EncomendaZ agradeceram em não terem que baixar 33mb ou mais a cada versão nova lançada.

DemoDroid++!

Vamos ver um pouco mais sobre o DemoDroid. Dessa vez, vou demonstrar só mais uma feature bem bacana. Para quem já programa para Android, já sabe que é necessário abrir manualmente as conexões com o banco de dados e gerenciar esta conexão. Já mostrei no post anterior que você não precisa mais fazer isso, pois já existe a classe EntityManager que trata tudo isto para você. Agora ficam umas perguntas para responder:

1. Quando abro um banco de dados, eu dou um nome a ele, como é feito isso agora?
R: Você pode fornecer um nome usando o seu arquivo de Manifest do Android (AndroidManifest.xml). Lá, você pode colocar qual o banco de dados e a versão.

<meta-data android:name="DATABASE_NAME" android:value="MeuBanco.db" />
<meta-data android:name="DATABASE_VERSION" android:value="2" />

2. Entendi. Mas, e se eu não informo isto no Manifest?
R: Será criado um banco de dados padrão, chamado Demoiselle.db.

3. Eu vi ali a versão e agora lembrei que eu usava a classe SQLiteOpenHelper do próprio Android. Eu estendia essa classe e depois sobrescrevia o método onUpgrade. E agora? Como faço?.
R: O DemoDroid vai prover umas três formas diferentes de você resolver isso. A primeira é bem simples. Você pode criar um método qualquer, mas que tem uma assinatura assim:

	public void databaseUpgrade(@Observes DatabaseUpgrade event) {
		Log.d("Persistence", "Verificada a necessidade de atualizar a Base de Dados");
	}

Toda vez que ocorrer a necessidade de atualizar a base de dados, este seu método será chamado. No objeto “event”, você poderá ver a versão antiga e a nova, além de ter o objeto SQLiteDatabase para fazer suas operações na base de dados.

4. Epa! Você falou em três ou mais! Quais são as outras formas?

R: Apressadinho. Eu já ia explicar. A segunda forma também é simples. Você pode criar uma classe que receberá esses eventos de outra forma. Veja:

@Upgrade(version = 4)
public class UpgradeToVersion4 implements UpgradeRequest {

	public void upgrade(SQLiteDatabase database) {
	}

}

Como funciona isso? Perceba que você usa a anotação @Upgrade e diz qual a versão. Imagine que um usuário pegou sua aplicação na versão 1 da base de dados. Alguns meses depois, ele atualiza a aplicação. Contudo, agora a base já está na versão 4. E agora? O DemoDroid vai procurar no seu classpath todas as classes que possuem a anotação @Upgrade e que implementa a interface UpgradeRequest. Ele irá executar as classes em sequência. Se tiver uma classe anotada com @Upgrade(version=2), ele vai chamar ela primeiro. Se tiver uma classe com a anotação @Upgrade(version=3), ela será chamada logo em seguida. Entendeu? Você fez um histórico de atualizações necessárias para cada versão. E elas serão executadas AUTOMATICAMENTE. Basta criar a classe como foi exemplificado acima!

5. Nem invente. Pode ir me dizendo as outras formas. Só disse duas até agora.
R: As outras formas ainda não foram implementadas mas estão no nosso backlog. A terceira ideia é realizar atualização a partir de um arquivo XML. A quarta opção é ter uma classe utilitária que ajudará a fazer a atualização sem usar comandos SQL.

E aí? Curtiu?

Android é com o DemoDroid!

Comprei um celular com Android e, a esta altura, isto já não é mais novidade para ninguém. Mudei de iPhone para Android por um motivo muito simples: odeio Objective-C. Ah, e também odeio a política de publicação de aplicativos da Apple. Ah, e também acho simplesmente um assalto ter que dar 60% do valor do meu aplicativo para eles. É, acho que agora acabei minha lista negra contra o iPhone. 🙂 Mas, no mais, eu gostava dele. Só que agora, achei um concorrente: Samsung Galaxy S. Sensacional.

Mas, cala a boca, Marlon. Você não criou esse post para se vangloriar de seu novo celular e nem para falar mal da Apple. Na verdade, eu queria falar do DemoDroid. Não, não tem nenhuma relação com culto ao Satanás. DemoDroid é a junção das ideias que vivenciei no desenvolvimento do projeto Demoiselle com o ambiente do Android. E surgiram várias coisas legais dessa brincadeira. Por enquanto, vou só dar uma pincelada em umas ideias. Depois, faço mais alguns posts com mais detalhes! Agora é só para você ficar com vontade.

Vamos lá. Para quem já programou em Android, sabe que existem algumas tarefas chatas de serem feitas. Abrir e fechar conexão com o banco de dados é uma delas. Usar Cursor, então… para quem veio do mundo Java e sempre usou Hibernate, sente coceiras quando vê que no Android você precisa voltar a escrever código SQL e iterar em um Cursor para obter os dados. Então, resolvi criar um conjunto bem pequeno de classes, de forma que não tivessem impacto muito grande, para facilitar isto. E aí minha classe da camada de persistência ficou com trechos de código assim:

public class TrackingPersistence extends SQLiteCrud<Tracking> {

	@Inject
	@SQLite
	private EntityManager entityManager;

	public List<Tracking> findNotDeliveredTrackings() {
		Query query = entityManager.createQuery(Tracking.class, "select * from tracking where has_arrived = 0 and send_date IS NULL");
		return (List<Tracking>) query.getResultList();
	}
}

Bem mais clean, né não? E é isso mesmo que você está pensando: usei um pouco da ideia do JPA. Perceba ali que injeto um EntityManager e qualifico para ser injetado um que trabalhe com SQLite. Injetado? Como assim? Tem CDI no Android? É, tem sim. Na verdade, é o Google Guice. Você pode usar ele através do projeto RoboGuice. Vê lá que também tem a interface Query, igual ao JPA. A diferença é que você precisa colocar um código SQL puro e não mais HQL ou JPQL. Eu sei, isso é chato. Mas é Android, lembre. Fazer um parser de uma linguagem intermediária para SQL nativo seria muito custoso para um dispositivo. Ficou curioso para ver a entidade Tracking? Vamos lá:

@Entity
@Table(name = "tracking")
public class Tracking {

	@Id
	public long id;

	public String code;

	public Date send_date;

	public boolean has_arrived;

	public boolean taxed = false;

	@Transient
	public boolean has_changed = false;

	@Transient
	public Status lastStatus;

}

Ahhhhhhhh! Espertão! Também copiou as anotações de campos, né? Exatamente. 🙂 E funciona igualzinho a como você já sabe em JPA. Uma diferença: aqui não resolvemos relacionamentos entre entidades. Aliás, eu sequer indico que você faça relacionamentos de entidades quando estiver programando em Android. Relacionamentos são custosos demais para serem carregados e sempre bastante imprevisíveis à medida que você aumenta esta hierarquia de dependência entre os objetos. Evite!

Agora, você deve estar se perguntando: eu sei que tenho que criar as tabelas com SQL. Mas, onde você faz isso? Não faço. Ao iniciar a aplicação pela primeira vez, o próprio DemoDroid vai descobrir suas classes anotadas com @Entity e vai criar as tabelas para você. Sim, você quer saber, e que classe SQLiteCrud é essa? Ela já fornece alguns métodos CRUD por padrão para você. São os tradicionais Insert, Update, Delete, Find e FindAll. Já vem tudo implementado para você. Na sua classe de persistência você só precisa implementar os métodos a mais que precisa, como no exemplo que passei.

Vamos a outra coisa bastante usada em Android: exibição de mensagens de sucesso ou falha pra o usuário. E no Android, a forma mais trivial é usar a classe Toast. Ela é responsável em exibir aquele balão que some automaticamente depois de um tempo. Como você usaria ele normalmente? Seria assim:

	Toast toast = Toast.makeText(context, "Meu Texto", Toast.LENGTH_SHORT);
	toast.show();

Mas, certamente, você fará uma classe utilitária para evitar proliferar este mesmo código por toda a sua aplicação, certo? Pensando nisso, porque não usar algo assim?

	@Inject
	@Toaster
	private MessageContext messageContext;

	public void saveException(CodeExistsException exception) {
		messageContext.add(R.string.error_code_exists);
	}

Você poderia passar como parâmetro para o método “add” também uma String, mas o mais normal é passar o ID da string que está no seu arquivo de Resource. Feito isto, pronto. Sua mensagem vai ser exibida. Em qualquer parte da sua classe basta fazer igualzinho ao que foi feito no método saveException, pois você já injetou o contexto de mensagens. E olha uma coisa mais legal ainda: usando o MesageContext, você pode parametrizar as mensagens. Caso você crie uma mensagem no seu arquivo de resource que seja assim: “Uma Mensagem para {0}”, basta fazer messageContext.add(R.string.mensagem, “Marlon”). Entendeu? Nos próximos posts, mais pitacos sobre o DemoDroid! AH! Se eu estou usando o DemoDroid em algum projeto? Claro, no EncomendaZ para Android: https://market.android.com/details?id=net.silvacarvalho.encomendaz