Android & Lua

Neste post, vou apresentar um pequeno projeto de exemplo que mostra uma integração de Lua com uma aplicação Android.


O que é Lua?

Lua é uma “embed language”, ou seja, tem como objetivo ser usada dentro de uma aplicação escrita com outra linguagem (para estender a app, configurar, etc.). Quando foi criada na PUC-Rio, por exemplo, era usada por engenheiros da Petrobras (que nem mesmo eram programadores) para configurar o funcionamento de alguns softwares usados nas plataformas de petróleo.

Mais detalhes na página oficial: http://www.lua.org


Como um programa escrito em Lua roda dentro de uma aplicação?

Lua nada mais é que uma biblioteca escrita em C. É multiplataforma, pois usa apenas as funções e tipos da biblioteca padrão do C. É possível executar programas escritos em Lua (scripts) através da linha de comando, mas isso nada mais é que um pequeno executável que tem a biblioteca Lua dentro.

Então, para incluir Lua na sua aplicação, basta incluir essa biblioteca no seu programa e usar suas funções. É possível carregar arquivos com os scripts, executá-los e integrar funções e dados; por exemplo, funções escritas em C que podem ser chamadas pelo script Lua, e funções do script podem ser chamadas pelo código em C.


Lua e Android

No link https://github.com/marciodrosa/LuaAndAndroidSample há um sample que mostra como integrar Lua em uma aplicação mobile. No caso, Android. Teoricamente, deve ser possível também em outras plataformas, como iOS e Windows Phone 8 (o Windows Phone 7 não tem suporte a programação com C, logo, só é possível executar Lua caso exista alguma implementação não oficial da biblioteca em C#).

O objetivo é mostrar como uma aplicação poderia ser estendida com um plug-in escrito pelo usuário.

Ao executar a app, são exibidos três caixas de texto. Ao alterar valores das duas primeiras, a soma destes valores aparece na terceira. Essa lógica e manipulação do terceiro campo é feita por um script Lua.

postimg1 - screenshot


Mas as aplicações Android são escritas em Java, não em C!

Java permite integração com código escrito em C, a chamada Java Native Interface (JNI). O código escrito em C precisa ser compilado em uma lib, e por isso existem as ferramentas do Android para isso: o Android NDK (http://developer.android.com/tools/sdk/ndk/index.html). Além do compilador, há algumas bibliotecas disponíveis no NDK.

Assim, no Android, ocorre uma conversa entre três linguagens: Java <—> C <—> Lua.


Como funciona a app de exemplo LuaAndAndroidSample

Dentro do projeto há um arquivo “myscript.lua”, que é empacotado junto com a aplicação. Essa foi a maneira utilizada por este projeto de exemplo, mas é claro que poderia ser feito de outras maneiras, afinal, o script é apenas um texto; poderia ser recebido pela rede, lido de um arquivo, ou até mesmo criado dentro da app, em uma caixa de texto. O conteúdo do script é o seguinte:

 return {
   onfieldvaluechangedbyuser = function(context)
     local op1 = tonumber(context.fields["Field one"].value) or 0
     local op2 = tonumber(context.fields["Field two"].value) or 0
     return {
       newfieldvalue = {
         field = "Field three",
         value = op1 + op2,
       }
     }
   end
 }

Este script é como um plugin, ele altera o comportamento da aplicação para mostrar uma nova informação na terceira caixa de texto. Quando a app é iniciada, ela carrega e executa o script, que apenas retorna uma tabela (objeto) com as funções de callback para serem chamadas em determinados eventos. No exemplo, esta tabela tem uma função chamada “onfieldvaluechangedbyuser”, que é chamada pela app quando uma caixa de texto tem o valor alterado pelo usuário.

A função onfieldvaluechangedbyuser recebe um objeto de contexto, que possui os dados da aplicação (como os valores das três caixas de texto). Na implementação, ela retorna um outro objeto (result), que é então processado pela app. Este outro objeto pode possuir um novo valor para algum campo. No myscript.lua, o script retorna um novo valor para ser setado na terceira caixa de texto.

Resumidamente, este é o fluxo do que ocorre:

Usuário altera um valor na caixa de texto –> app chama o callback do script, passando o contexto –> script retorna um resultado –> app processa o resultado.

A idéia dessa arquitetura é isolar a execução do script em uma sandbox: não há interação entre a app e o script (por exemplo, o script não altera o valor da terceira caixa de texto; ao invés disso, ele retorna um objeto solicitando que a app faça isso). Esse isolamento é feito para deixar a execução do script mais unitária, facilitar os testes e simplificar o fluxo.

Além disso, usei um pouco da idéia dos plugins do Blender (blender.org), que também são executados assim que a aplicação é iniciada, e que possui funções de callback para serem chamadas mais tarde, quando ocorrem eventos (também recebendo um objeto de contexto como parâmetro).

postimg2 - flow


Como foi feita a integração na app (a “engine” de plug-ins)

A arquitetura básica da “engine” é exemplificada na seguinte imagem:

postimg3 - languageflow

  • A biblioteca em C foi nomeada de “Bridge”, já que é uma ponte entre a app e os scripts.
  • A aplicação Java e o “Bridge” em C conversam entre si (Java solicita para a Bridge que o plugin execute; a Bridge retorna resultados para a aplicação Java).
  • A Bridge e uma engine Lua conversam entre si. Essa engine não é o plugin em si. Ela é usada para fazer a lógica de chamada do plugin, processar erros, resultados, etc. Isso mostra como Lua pode ser usado não apenas para estender a aplicação: neste caso, foi usada para implementar uma lógica que pertence nativamente à aplicação. Isso pode ser muito útil para aplicações multiplataforma. Por exemplo, se a mesma app for implementada para outro sistema, como iOS, o código dessa engine em Lua pode ser reaproveitado.
  • Por fim, a engine em Lua faz o plugin executar. O plugin não se comunica com ninguém, ele executa em uma sandbox isolada, evitando que a lógica implementada por um usuário possa agir de maneira inesperada na aplicação. Toda a comunicação é feita entre a engine Lua e a Brigde C.

Algumas informações adicionais

  • Embora Lua utilize ANSI C (apenas as bibliotecas padrão), nem tudo são flores: o NDK, por exemplo, não possui a API de internacionalização do C (utilizada pelo Lua para saber se um número decimal usa ponto ou vírgula). Então, pequenos ajustes são necessários. O código fonte do Lua 5.2 pronto para ser compilado para Android pode ser pego no meu repositório do Github: https://github.com/marciodrosa/LuaAndroid. Além dos ajustes necessários, ele também direciona as mensagens de erro e log para o logcat.
  • Para fazer o build de uma lib para Android usando código-fonte C, os arquivos de código devem ser colocados dentro de uma pasta chamada “jni” e o comando “ndk-build” deve ser executado. Dentro da pasta “jni” também há alguns arquivos de configuração, como “Android.mk” e “Application.mk”, e outras libs pré-compiladas, caso sejam usadas pelo projeto. O NDK automaticamente move os binários gerados para dentro da pasta “lib”. No projeto Java do Android, as libs que serão usadas devem ser carregadas usando System.loadLibrary (ver a classe StartActivity do projeto LuaAndAndroidSample). O build pode parecer um pouco difícil de entender no começo. Para mais detalhes, é necessário ler a documentação do NDK. A maior parte da documentação não está disponível online; ao invés disso, vem junto com o projeto do Android NDK, quando ele é baixado.
  • No projeto AndroidAndLuaSample, há um método que gera o objeto “context”, que é passado para o callback do script. Ele gera o context concatenando scripts. Obviamente, isso não é uma boa prática, não estamos lidando com linguagens orientadas a string! Que fique claro que isso foi feito apenas para demonstração. O correto seria criar o objeto de contexto usando a API C do Lua.
  • Este sample funciona apenas em dispositivos com processador ARM. É necessário fazer outro build das bibliotecas C para que elas funcionem com outros processadores, como Intel.

Links

Página oficial do Lua:
http://www.lua.org/

Documentação do Lua (manual, referência da API e referência da API C):
http://www.lua.org/manual/5.2/

Livro online gratuito sobre Lua (mas é de uma versão antiga do Lua, com algumas features desatualizadas):
http://www.lua.org/pil/contents.html

Android NDK:
http://developer.android.com/tools/sdk/ndk/index.html

Lua 5.2 para Android:
https://github.com/marciodrosa/LuaAndroid

Código-fonte do projeto de exemplo “LuaAndAndroid”:
https://github.com/marciodrosa/LuaAndAndroidSample

Anúncios

Métricas de Software X Saúde do Código

Você já deve ter ouvido falar sobre a importância da qualidade de um produto ou serviço certo?

Diversas áreas se preocupam com isso, da construção civil e seus prédios, à um médico ao realizar uma cirurgia. Mas e na área de desenvolvimento de software, quais ferramentas temos a disposição para garantir a qualidade e excelência de nosso produto, o software? Temos diversas respostas para estas pergunta: metodologias e processos, testes de aceitação, testes funcionais, testes de stress. Estas ferramentas tem por objetivo garantir a qualidade a nível de cliente, fazendo com que o produto atenda as demandas corretamente para as quais foi projetado.

Mas e para nós desenvolvedores, o que pode ser considerado como um software de qualidade? O estudo da engenharia de software nos remete a diversos problemas que o desenvolvedor deve procurar evitar para obter código fonte de qualidade. Duplicidade de código, métodos e classes com muitas responsabilidades, alta complexidade ciclomática, ausência de testes unitários, entre outros.

Partindo da premissa de que o desenvolvedor conhece as boas práticas de programação, controlar a propagação destes fatores indesejáveis, em um projeto pequeno pode ser fácil. Mas atualmente a realidade é outra, projetos tendem a serem escaláveis e crescerem ao longo do tempo. Além disso dificilmente o desenvolvedor irá trabalhar sozinho, o desenvolvimento distribuído já é realidade na maioria da empresas. Nesses casos é muito fácil a equipe perder o controle da dimensão do software e de seus problemas.

E é neste cenário que entram as métricas de software. Existem diversas métricas, cada uma medindo um aspecto do software. Abaixo seguem alguns exemplos:

Número de linhas de código (LOC, KLOC): Mostra a quantidade de linhas do código fonte. Deve-se ter cuidado com está métrica quando utilizada para fazer comparações. Um maior número de linhas de código não significa necessariamente que um software é maior que outro. Por exemplo diferentes linguagens de programação necessitam de número de instruções diferentes para executarem as mesmas coisas.

Complexidade Ciclomática (CC): Fornece uma medida sobre a complexidade do software. O cálculo de complexidade ciclomática leva em conta quantos desvios uma função possui. Cada comando if, switch, for, while, é considerado um desvio do fluxo principal do código. Toda função possui como valor padrão 1, já que pelo menos um caminho é possível para o código. Conforme são inseridos os desvios este número aumenta. Como dito por Robert C. Martin em seu livro Código Limpo, cada método deve ter uma única responsabilidade, portanto devemos sempre buscar manter este indicador baixo, garantindo a manutenibilidade de nosso código.

Falta de coesão em métodos (LCOM): Esta métrica mede o nível de coesão de uma classe através da verificação do número de acessos a atributos em comum pelos métodos. Se a classe possui um método A que acessa os atributos B e C, e um método D que acessa os atributos E e F, a métrica considera que essa classe tem duas responsabilidades. Quanto maior o LCOM, mais responsabilidades a classe possui, tornando-a pouco coesa. Assim como outras métricas, este valor não pode ser considerado totalmente verdadeiro. Em algumas ocasiões, em virtude das regras de negócio, dois conceitos que parecem ser responsabilidades distintas, na verdade fazem parte do mesmo escopo. Portanto sempre deve-se analisar minuciosamente o código com LCOM alto, para tomar as ações corretas.

Estas métricas são apenas um exemplo, existem outras diversas. Mas a pergunta que fica é como calcular de forma efetiva estas métricas? Existem diversas ferramentas utilizadas para medição de software, algumas servem para métricas específicas, mas existem soluções como Sonarqube que oferecem um pacote de métricas que podem ser utilizadas pelos desenvolvedores para monitorar o estado do código de maneira simples e rápida. Algumas destas ferramentas também auxiliam a comparação do código em um período de tempo, assim possibilitando a criação de gráficos que mostrem a evolução de nosso software.

Um bom exemplo disso seria um gráfico do tipo Cobertura de testes X Complexidade ciclomática. Quando evoluímos o software inserindo novas features, devemos ter o cuidado de não inserir complexidade desnecessária, visando a boa evolução do código. Abaixo segue um exemplo de como esse tipo de gráfico nos fornece um rápido feedback sobre o código:

Gráfico de complexidade do framework Struts

Este gráfico mostra claramente que o framework Struts inseriu alguma funcionalidade que aumentou a complexidade do código drasticamente, e que a cobertura de código caiu quase na mesma proporção.

Como vimos o monitoramento das métricas de software pode ser essencial para a manutenção da saúde de nosso código. Cabe a nós desenvolvedores, ou aos times que resolverem adotar esta prática, utilizarem com parcimônia. De nada adianta possuirmos um dashboard com diversas métricas se a maioria não faz sentido para o nosso caso. Também vale ressaltar que as medições devem servir como base para planos de ação, caso contrário se tornam apenas números. Para começar, escolha de 3 a 5 métricas e ataque os pontos críticos, com o tempo você pode adotar outras, mas sempre visando a melhoria continua e consequentemente a qualidade de seu código.

Anatomia de uma Mensagem de Erro (ou de Alerta)

Thiago Esser, Designer

Elas são necessárias, mas nem sempre tão espertas ou simpáticas quando a gente gostaria. São aquelas mensagenzinhas que volta e meia aparecem quando estamos preenchendo um formulário na web, ou quando estamos usando um aplicativo no smartphone.

Guia pro designer ou desenvolvedor

Abaixo, compartilho um pequeno guia pra escrever esse tipo de mensagem, o que, pela minha experiência, não é uma tarefa que se faz com as mãos nas costas.

  1. Informe o que aconteceu?
    Tip: Você não está tratando com idiotas e, muito provavelmente, não está falando com especialistas.
  2. Diga o que pode serfeito?
    Tip: A sua meta é sempre resolver o problema ali na hora.
  3. Ese, mesmo assim, o problema continuar?
    Tip: Vá até o fim, afinal de contas, o problema também é seu.

20130701-125314.jpg

[Update de 03/07/2013] Para revisar, além dessa estrutura básica, você pode pedir pra alguém olhar e avaliar esses quesitos:

  • O português está…

Ver o post original 133 mais palavras

Design Thinking Dojo na uMov.me

Num Dojo com mais conversa do que qualquer outra coisa, discutimos a abordagem do design thinking e de como podemos usá-la no nosso dia-a-dia. Em qualquer profissão, mas especialmente no desenvolvimento de software, para:

  • Validarmos pensamentos/idéias, transformando-as em algo visual
  • Gerando um entendimento compartilhado do que estamos discutindo
  • Fazendo perguntas que tragam à tona o sentido daquilo que produzimos
  • Repetindo esse processo sempre que necessário, levando-o na nossa “caixa de ferramentas” (toolbox)

Abaixo, a apresentação que guiou o nosso papo sobre o tema.

Escalando Horizontalmente – AWS Auto Scaling – Parte#1

Finalmente depois de alguns aprendizados e experiências chegou a hora de compartilharmos um pouco sobre Amazon Web Services. Vamos então falar sobre  escalar de forma horizontal utilizando o serviço Auto Scaling da AWS. Para aqueles que não conhecem o AWS Auto Scaling indico fortemente dar uma boa leitura na vasta documentação do serviço que aborda desde conceitos básicos de utilização até mesmo referencias da API.

Outra dica também é assistir a palestra realizada no uMov.Me Labs Summit realizado em Abril 🙂

Para interagirmos com os serviços web services da Amazon relacionados a política de Auto Scaling podemos escolher basicamente entre:

  • SDK – Utilizando a API de desenvolvimento da AWS disponível hoje para as principais linguagens de programação como Java, .Net, Ruby, PHP, Node.JS e também plataformas móveis como Android, iOS. Através da API de desenvolvimento é possível interagir diretamente com os web services da Amazon, manipulando grande parte dos serviços oferecidos via console de gerenciamento.
  • Command Line Tools – Grande amigo dos SysAdmins, o Command Line Tools, veio para facilitar a interação com os principais serviços disponíveis pela AWS, onde sem precisar desenvolver nenhuma linha de código ou instanciar nem objeto é possível gerenciar sua infraestrutura usando apenas o terminal.

Neste primeiro exemplo iremos adotar o Command Line Tools como ferramenta para criarmos uma política de auto scaling. Nesta abordagem iremos fazer com que nossa infraestrutura esteja preparada para escalar de forma horizontal. É possível utilizando o serviço Auto Scaling prever períodos de grande utilização de uma determinada aplicação ou serviço, mas também simplesmente reduzir o número de instancias durante os períodos de inatividade das mesmas, impactando diretamente assim nos custos com infraestrutura.

Através de alguns poucos passos utilizando o Command Line Tools você poderá obter significativa redução no seu bolso ao final do mês. Então chega de bla bla bla e vamos ao que interessa: Setup:

  1. Para iniciar realize o download da ferramenta Command Line Tools de Auto Scaling;
  2. Uma vez descompactado o arquivo, será criada a pasta ‘AutoScaling-xxx’. Iremos seguir os passos descritos na seção “Installation” do arquivo README.TXT situado dentro da pasta descompactada, setando assim todas as variáveis de ambiente necessárias para rodarmos os scripts;
  3. Agora é a vez de obter suas chaves de segurança da AWS para conseguirmos interagir com a API da AWS. Para obter as suas credenciais basta acessar as configurações da sua conta e obter as duas chaves(Chave de acesso, Chave de acesso secreta).
  4. Com as chaves em mãos, basta seguir a seção “Using AWS Keys” do arquivo README.TXT situado dentro da pasta descompactada.
  5. Para ter certeza de que tudo está funcionando corretamente digite no terminal o comando “as-cmd”. Se todos os passos foram seguidos corretamente você verá uma lista com os comando disponíveis da ferramente de auto scaling via Command Line Tools.
  6. Dúvidas?

Escalando:

  1. O primeiro passo a ser realizado basicamente irá identificar qual AMI(Amazon Machine Images) servirá de base para criar novas VMs quando necessário. Para isso basta executar o comando abaixo:  
    as-create-launch-config my_config --image-id ami-xxxxxxxx --instance-type m1.micro
  2. Uma vez criada a configuração de inicialização de novas VMs, precisamos informar agora através da criação de um novo grupo de auto scaling em quais zonas estas VMs devem ser criadas. Algumas outras informações importantes são número mínimo e máximo de VMs bem como para qual ELB(Elastic Load Balancer) estas VMs devem ser atribuídas. Crie um novo grupo executando:
    as-create-auto-scaling-group my_as_group --launch-configuration my_config --availability-zones us-east-1a us-east-1b --min-size 2 --max-size 20 --load-balancers MyLB
  3. Para que possamos iniciar uma nova VM e desta forma escalar horizontalmente é necessário a criação de políticas de auto scaling. Desta forma criaremos uma política para adicionar novas VMs respondendo ao load balancer associado. Para isso precisamos executar o comando:
    as-put-scaling-policy scale_up --auto-scaling-group my_as_group --adjustment=1 --type ChangeInCapacity --cooldown 300
  4. Uma vez incrementado o número de VMs e satisfeito o aumento na demanda das aplicações, você também pode ter uma política de auto scaling para desligar VMs uma vez identificado baixo tráfego de requisições através do ELB em questão. Semelhantemente ao passo 3 iremos criar uma nova política, porém agora estaremos subtraindo uma VM de modo a economizar recursos não utilizadas executando o comando:
    as-put-scaling-policy scale_down --auto-scaling-group my_as_group --adjustment=-1 --type ChangeInCapacity  --cooldown 300

    Você ainda pode resolver diminuir o número de VMs após o horário comercial onde o volume de acessos diminui consideravelmente e através do monitoramento de memória ou CPU indicam inatividade de algumas VMs. Mas este é um assunto para o próximo post, AWS Auto Scaling – Parte#2 🙂

  5. Vamos testar? Uma vez que não atrelamos nenhuma rotina de monitoramento onde poderíamos criar e remover instancias automáticamente, podemos criar e remover instancias manualmente através do comando “as-execute-policy“.
  • Baseado na política para criar VMs podemos executa-la assim:
    as-execute-policy --name scale_up --auto-scaling-group my_as_group
  • Baseado na política para remover VMs podemos executa-la assim:
    as-execute-policy --name scale_down --auto-scaling-group my_as_group

Desta forma temos uma primeira política de auto scaling! Em um próximo post estaremos explicando como automatizar a criação e remoção de VMs utilizando o serviço AWS CloudWatch. #ficadica

Boot2Gecko (FirefoxOS) o novo sistema operacional para smartphones

Seguindo a tendência do uso de dispositivos móveis, a Mozilla também pretende ocupar uma fatia deste mercado com o lançamento de seu sistema operacional para dispositivos móveis.

Utilizando inicialmente um codinome boot2gecko, o FirefoxOS está trazendo mais uma opção para bater de frente com os gigantes atuais Android, iOS e Windows Phone, para ser vendido junto aos atuais smartphones.

Um ponto muito interessante que está embalando a comunidade é o fato que seus aplicativos serão desenvolvidos todos utilizando puramente HTML, CSS e JavaScript. Potencializando assim a comunidade de desenvolvedores e agregando profissionais que hoje trabalham para o desenvolvimento web e não precisarão aprender uma nova tecnologia em relação a seus concorrentes.

Você pode saber mais sobre o projeto aqui: http://www.mozilla.org/en-US/b2g/

É possível também acompanhar a evolução do projeto por sua conta no github: https://github.com/mozilla-b2g

E este é o projeto que contém sua parte de interface com todos os seus aplicativos iniciais: https://github.com/mozilla-b2g/gaia

A Mozilla anunciou que pretende lançar este sistema primeiro “pasmem” no Brasil. Se por motivos de mercado ou estratégia da empresa não sabemos, mas podemos ficar felizes brasileiros por sermos os primeiros a colocar as mãos nele.

Enquanto não temos suporte oficial em nenhum aparelho, podemos ver como ele está ficando rodando ele emulado em seu sistema operacional. Algumas dicas de como fazer isso aqui: https://wiki.mozilla.org/Gaia/Hacking

Abaixo alguns screenshots que tirei realizando uma breve exploração do sistema.

Screen_shot_2012-08-16_at_12Screen_shot_2012-08-16_at_12Screen_shot_2012-08-16_at_12Screen_shot_2012-08-16_at_12Screen_shot_2012-08-16_at_12Screen_shot_2012-08-16_at_12

 

E você, acredita que ele vem para fazer frente ?