Archive for the 'Desenvolvimento' Category

langs, bashes e encodings da vida

Acho que posso dizer sem medo de errar que na lista de dores de cabeças que meus projetos pessoais e startups me trouxeram, a questão da codificação de strings está tranquilamente entre os TOP 3. E quando eu achei que tudo nesta área estava resolvido, eis que me apareceu um novo bug do nada que me fez perder algumas horas de mal humor. Porque coisas que funcionam por meses e de repente param de funcionar sem motivo aparente em geral me tiram do sério.

O SigaSeuTime (cujo novo site acaba de estrear, se me permitem o autojabá) possui dois bots IM, GTalk e MSN, que fazem parte do conjunto de plataformas para distribuição de contéudo. Ambos os bots são escritos em Java, e a plataforma é escrita em Python. Para fazer a comunicação entre os subsistemas eu uso ou REST ou comunicação via UDP. No caso das notícias em tempo real, acabei optando por UDP para evitar pooling desnecessário. E isso funcionou perfeitamente nos últimos 6 meses: um agente se encarrega de puxar as notícias, processar, filtrar e gravar na base de dados. Outro agente lê as notícias novas e manda pros bots via UDP, para envio aos usuários online. .

Até que de repente, as mensagens começaram a aparecer tanto no MSN quanto no GTalk  com a acentuação totalmente errada. Típico resultado de strings codificadas de um jeito e interpretadas de outro (tinha que existir um jeito fácil e direto de se descobrir a codificação de uma string sem a necessidade de metadados)! Olhando para o histórico do meu SVN vi que as últimas modificações em códigos relativos aos componentes envolvidos neste processo datavam de no mínimo 3 meses.

Ou seja, só podia ser culpa do meu servidor, ou do alinhamento planetário, ou então do Bush! Não não…a culpa, obviamente era minha. Sempre é, por mais que a gente lute contra isso.

A causa do problema estava em um script SHELL que eu criei recentemente cujo objetivo é de reiniciar os bots em caso de falha de comunicação com os servidores. Até então, o processo de reboot era manual, feito por mim mesmo via shell SSH, e a função deste script é de automatizar o processo, matando e executando novamente o bot.

Inofensivo certo? Nem tanto. O script é executado periódicamente pelo crontab do sistema operacional, e foi aí que o problema nasceu: as variáveis de ambiente do cronjob são diferentes das variáveis de ambiente do SHELL SSH, e em particular o segundo possui a variável LANG=en_us.UTF-8, que é justamente a codificação usada internamente pelo sistema. Vivendo e aprendendo: isto influi diretamente na JRE, e a falta da variável fez com que o sistema assumisse outra codificação (provavelmente ISO Latin 1). A solução foi exportar a variável no meu script.

Fatos sobre Erlang

Compilação de alguns pontos relevantes sobre Erlang, feita por Odracir:

  • Linguagem de programação de propósito geral, com ambiente de execução (runtime environment) implementado numa máquina virtual;
  • Possui suporte “embutido” para concorrência, distribuição, e tolerência à falhas.
  • É “Open-Source”, distribuído através da licença “ERLANG PUBLIC LICENSE“, que é essencialmente a Mozilla (Netscape) Public Licence, porém com algumas poucas modificações para torna-la compatível com a legislação Sueca.
  • É escrito em C, e é  portável para diversas plataformas.
  • Muito escalável!  Sua máquina virtual é responsável pela criação de “processos leves” de forma  rápida e barata, tanto em termos de utilização de recursos de CPU como de memória. Em outras linguagens de programação, normalmente estes serviços são delegados para o sistema operacional, o que limita  o número máximo de processos simultâneos permitidos.
  • Para modelar um sistema um Erlang nós usamos: “COP – Concurrency Oriented Programming”.
  • Não existe estado compartilhado…
  • Variáveis podem ser atribuídas apenas uma única vez. (Single assignment variables)
  • Os processos se comunicam entre si através do envio de mensagens (cópias imutáveis) assíncronas.
  • Tipicamente um código escrito em Erlang faz uso dos diversos núcleos disponíveis nas CPUs modernas, praticamente sem codificação adicional. Testes mostram que clusters com 16 máquinas executam um programa 14,55 vezes mais rápido do que o mesmo programa sendo executado numa única máquina, sem codificação adicional ou específica para isto!
  • Permite a interoperabilidade com C,C++, Java, Ruby, Python, Perl, etc …
  • Estudos mostram que para um mesmo projeto, o código Erlang é de 4 à 10 vezes menor que seu equivalente escrito em C++.
  • Possui a biblioteca  OTP (Open Telecom Platform).
  • Em situações extremas de “carga”, um sistema Erlang tende a degradar seu desempenho, mas não para de funcionar.

Normalização de sequências de caracteres

Um dos motivos que diminuiram minha participação neste blog nos últimos meses foi o meu trabalho intenso no SigaSeuTime. Entre os sócios no projeto, sou o único desenvolvedor, e a lista de tarefas não para de crescer. Gostaria de contar aqui um problema simples que tive que resolver, e que pode interessar outros desenvolvedores.

No mês passado, colocamos no ar dois bots, um para o MSN e outro para o GTalk/Orkut, que podem ser utilizados como alternativa para o Twitter para receber notícias e jogos ao vivo. Os bots funcionam como usuários normais: você adiciona o dito cujo na sua lista de amigos (usando o email sigaseutime@siga.st) e passa a receber mensagens. Ao contrário do Twitter, onde cada canal representa um time (@sigaFlamengo, @sigaVasco, @sigaCorinthians, etc…), nos bots um usuário pode selecionar um ou mais times, enviando a mensagem siga <nomedotime>.

Internamente, eu mantenho duas versões de nomes para cada canal do sistema: o nome completo (Corinthians, São Paulo, Palmeiras, Santo André, Seleção Brasileira, etc..) e um slug (corinthians, saopaulo, palmeiras, santoandre, selecaobr). Pra quem não sabe, um slug pode ser definido como uma versão URL Friendly do nome: sem acentos, espaços em branco e caracteres não ASCII. Originalmente, os bots aceitavam o uso de um dos dois nomes no comando. Por exemplo, siga Santo André ou siga santoandre.

Obviamente, fomos recebendo feedbacks de usuários que não conseguiam cadastrar um time. Em geral, isto acontecia com times com nomes compostos e/ou acentos. Analisei o log e percebi que era muito comum alguém digitar siga sao paulo por exemplo. Como o cliente tem sempre razão, decidi que um algoritmo mais espertinho de leitura do nome se fazia necessário: criei então uma funcionalidade de conversão de nomes para slugs. A primeira parte foi fácil: colocar tudo em letras minúsculas, remover espaços e outros simbolos não conformes.

Faltava a parte mais importantes: converter caracteres acentuados em caracteres não acentuados. afinal, para efeito de comparação, são e sao deveriam ser equivalentes. Inicialmente pensei em criar uma tabelinha de conversão simples, mas desisti porque a chance de alguém digitar um caso não contemplado era muito grande. Fui então pesquisar na Internet, e descobri que o UNICODE já prevê esta funcionalidade, e já tem tudo mapeado. Ainda bem que existem cientistas da computação prevenidos no mundo!

Este recurso se chama Normalização (como não pensei nisso antes….), e oferece 4 formas distintas: NFD, NDC, NFKC, e NFKD. Cada uma tem suas particularidades, e aconselho a quem se interessar pelo assunto pesquisar no site do UNICODE: http://www.unicode.org/faq/normalization.html.

O essencial é entender que existe um mapeamento de caracteres compostos (por exemplo ç = c + cedilha, ou ã = a + ˜), e que existem bibliotecas em algumas linguagens que implementam este mapeamento e que podem ser utilizadas para fazer a conversão. Vou dar um exemplo em Java e em Python:

Java:

import java.text.Normalizer;
import java.text.Normalizer.Form;
Normalizer.normalize(string, Form.NFD);

Python:

from unicodedata import normalize
unicodedata.normalize(forma, string)#forma pode ser 'NFC', 'NFD', 'NFKC' ou 'NFKD'

Utilizando este recurso, eu consigo facilmente converter SANto André, Santo Andre, SANTOandre ou qualquer outra combinação para o formato que eu espero: santoandre.

Histórico no Admin do Django

A funcionalidade de geração automática (de qualidade) de uma área de administração em projetos Django foi talvez a grande responsável por eu preferir esse framework ao Turbogears (junto com o fato do Turbogears ser na verdade uma federação de pequenos projetos). Pode parecer bobo, mas desenvolver uma área de admin bem feita é custoso, e ter uma versão básica bem feita de graça pode ser um grande diferencial na hora de construir algo novo.

Dentre as várias funções interessantes oferecidas por este admin, o histórico de operações sobre os objetos merece destaque:  cada ação efetuada sobre todo e qualquer objeto através do admin é gravada em uma tabela de histórico gerada automaticamente (data, usuário, objeto modificado, natureza da modificação), que pode ser visualizada em uma tabela web.

Infelizmente, este histórico é gerado automaticamente apenas para ações efetuadas através do admin. Recentemente, tive a necessidade de gravar o histórico de operações efetuadas por tarefas em background no SigaSeuTime (envio de anúncios comerciais para o Twitter), que me permitissem controlar de forma unificada e centralizada o bom funcionamento do sistema.

Pesquisando um pouco, descobri como fazer isso de forma simples com um código pequeno, que vou reproduzir abaixo:

from django.contrib.admin.models import LogEntry
from django.contrib.contenttypes.models import ContentType

def gravahistorico(objeto, mensagem, usuario): LogEntry.objects.logaction( userid         = usuario.id, contenttypeid = ContentType.objects.getformodel(objeto).pk, objectid       = objeto.pk, objectrepr     = mensagem, # Message you want to show in admin action list changemessage  = mensagem, # I used same action_flag     = 4 )

Chamando este código, ações sobre um objeto serão gravadas na tabela de histórico, e poderão ser vista na área de administração do Django. Simples e extremamente útil.

Código fluente

Com o advento e crescimento dos projetos Open Source, se intensificou o conceito de que em última instância a melhor documentação de um projeto é o seu próprio código fonte. Concordo plenamente com isso! Em projetos ativos, manter uma documentação sobre arquitetura completamente atualizada é uma tarefa ingrata (sobretudo se seguirmos os moldes de artefatos exigidos pelas metodologias waterfall), e documentação errada é a pior coisa que pode existir.

Em projetos Open Source, onde os recursos são muitas vezes escassos e não se pode dar o luxo de manter uma pessoa apenas para manter tudo atualizado, a necessidade de uma documentação simplificada impera. E a necessidade de um código organizado também.

O problema é que muita gente levou ao pé da letra esse conceito, e chegou-se à conclusão de que comentários são supérfluos, afinal o próprio CÓDIGO é a documentação. Resultado: tenho cada vez mais visto toneladas de linhas de código sem um puto de um comentário.

Ah, mas com nomes incrivelmente sugestivos: apagaORegistroDoUsuarioEMandeMensagemdeDesolePraEle.

Senhores e Senhoras, o código fluente!

Plagiando um exemplo que eu peguei no iMasters:

Vendedor.deNome("Abreu").
                 vende().
                 paraCliente("Rafael").
                 oProduto("Mouse Verde").
                 oProduto("Teclado de Pano").
                 comDescontoDe(20).
                 mostrandoDetalhes();
Não posso dizer que não entendo o que este código faz! Até minha avó de 92 anos entenderia. Lindo.

O problema é que por mais que se empacote todas as funções com nomes extremamente sugestivos, que se crie DSLs para se esconder a complexidade,  que as variáveis sejam extremamente bem nomeadas, alguma hora os detalhes sórdidos do código vão começar a aparecer: bases de dados, queries, estruturas de dados, rede, integrações com outra bibliotecas, etc…

(Aaaaaaaaa, você não trabalha com bibliotecas, nem com BD, nem com rede, e apenas integra código fluente? Meus pêsames, o mundo da computação é bem mais interessante e divertido do que isso. Próximo…)

E na hora que chegamos aos detalhes sórdidos, por mais que o nome do método explique o que está se fazendo, pode ficar a dúvida: porque o método faz isso desta forma? E entender o porque das coisas é essencial se você está tendo que corrigir/modificar/aprimorar/integrar/analisar código legado. Sim, porque o que torna o código legado tão infernal de se mexer é justamente entender O QUE SE PASSAVA PELA CABEÇA DO DESGRAÇADO QUE ESCREVEU AQUILO!

Exercício: pegue um código que você escreveu há 6 meses atrás, de um projeto do qual você não participa mais, e tente entender todas as minúcias….foi sofrido? Imagino que sim. Agora imagine o pobre coitado do estagiário que está tendo que resolver um bug que ocorre naquele trecho!

Muito se fala por aí que código tem que ser escrito para ser lido por seres humanos e não por máquinas. Uma máquina apenas interpreta aquilo que escrevemos, e não está nem aí se faz sentido ou não. Ao contrário de seres humanos. Todos ficamos muito felizes quando entramos no javadoc da Sun, e encontramos alguns detalhes de implementação interessantes de métodos cujos nomes muitas vezes são bem explicitos. Como por exemplo o remove(String key) de uma Collection. Ninguém tem dúvidas do que ele faz, mas o que acontece se eu passar um valor nulo? Ou se passar um objeto que não existe?

Comentários são uma ferramenta muito útil, presente em qualquer linguagem, e que fazem parte do código.  Devem ser utilizados com inteligência, para facilitar a vida de todo mundo, tornar o código realmente uma documentação completa e inteligente e poupar horas, cabelos e neurônios de desenvolvedores cansados, estressados ou que simplesmente não querem passar horas decifrando a mente alheia.

Babel

Eu já escrevi uma boa quantidade de linhas de código na minha vida. Talvez 100k, talvez mais. Não faço idéia. Com certeza este número diminuiu muito depois de eu ter começado a programar em Python :-) .

E quando releio alguns destes códigos, considero que na média a qualidade é boa (e pelos feedbacks de colegas, outras pessoas devem concordar com isso). Mas se me perguntarem o que me incomoda no meu estilo de codificar (sim, porque codificar é muito parecido com escrever livros: requer prática, cultura geral, leitura de outros textos, etc…) eu responderei na lata: a minha total falta de padronização da língua utilizada na nomenclatura de classes, métodos, atributos. Até hoje eu não me decido por escrever 100% em inglês, ou 100% em português. E faço isso sem perceber.

Em tempos de internet, globalização, software livre e colaboração, me agrada a idéia de existir uma língua universal para desenvolvimento de código. Facilita o intercâmbio de informações com pessoas de outros países, permite que se entre em mundos diferentes, quebrando a barreira da língua.

E inglês é a língua ideal para isso, simplesmente porque ela é a lingua internacional de fato (talvez um dia tenhamos que codificar em mandarin, mas isso é tema pra outra conversa). Além disso, boa parte das linguagens hoje (perto de 100% eu diria) utilizam primitivas e bibliotecas em inglês, para não se falar dos padrões e codificação. Por exemplo, em Java é padrão usar getters e setters para se ter acesso à informações internas a um objeto. Fica razoavelmente ridículo escrever getMinhaVariavel…mas ainda assim, eu faço isso com certa frequência.

Isto porque,  pior do que ter um código não universal (escrito em português por exemplo) é ter um código escrito em inglês errado. Eu com certeza já escrevi vários métodos que soariam ridículos para um falante nativo, e já li uma tonelada que soavam ridículo até pra mim. O problema é que, apesar de ler constantemente textos de computação em inglês e me virar bastante bem na língua do Tio Sam, na hora do cansaço ou da necessidade de termos mais rebuscados, as vezes o cérebro pede arrego. E aí vai em português mesmo. Já tive casos de precisar codificar conceitos ligados ao plantio de eucaliptos para produçao de papel, e fui atrás de termos em inglês para colheita, plantio, talhão, gleba….o resultado foi bom, mas tomou um bom tempo.

Ou seja: tenho que aprimorar meu inglês.

Em tempo: recentemente dei uma folheada em um livro sobre SCRUM, escrito em português por um brasileiro, e desisti de comprar o dito cujo quando vi um “printar” no meio de uma frase. Parece que do mesmo jeito que as vezes eu tenho preguiça de procurar termos em inglês, certas pessoas tem preguiça de escrever direito em português.

Last, but not least: a questão de escrever em inglês entrou em pauta várias vezes no Log4Dev. Temos pelo menos um expert no assunto, Lullis, tradutor nas horas vagas. Com certeza, mudar de língua tornaria nosso blog internacional, e fama e riqueza bateriam às nossas portas. Mas, por modéstia, vontade de manter uma vida calma e anônima, e falta de proficiência absoluta, decidimos manter os textos em português. Antes uma idéia bem transmitida para poucos do que mal escritas para a humanidade.

A grama do vizinho

Eu ando meio ausente deste blog. Percebo que a atividade de escrever requer tempo, e sobretudo, ócio criativo. Raramente consigo escrever um texto entre uma atividade e outra, menos quando são textos com notícias breves, como este sobre o Job4Dev no UOL. E o leitor há de se perguntar: “o que toma tanto o tempo deste pobre rapaz?”.

Respondo: o SigaSeuTime, startup que vem crescendo de forma animadora e que me tem tomado todo o tempo livre fora do horário comercial (sim, porque no horário comercial eu brinco de desenvolver sistemas de controle de tráfego aéreo, que ainda é a minha fonte de renda principal…e única).

Mas, acreditem, não passa um dia sequer sem que eu pense que deveria me dedicar mais a este espaço. E não passa um dia sequer sem que eu leve sermão do Raphael por não meter mais a mão no Job4Dev (assumi o papel de captador de vagas…). Mas isto é assunto pra outro dia.

Vou aproveitar o momento de inspiração para relatar uma experiência que tive recentemente trabalhando com o SigaSeuTime, que me parece interessante.

O ditado “A grama do vizinho é sempre mais verde” se aplica a quase todas as áreas do comportamento humano: nós temos uma tendência a achar que o que os outros têm é melhor. Em termos de linguagem de programação, o fanatismo de certos grupos tende a contrariar este ditado: é muito raro algum fã de uma linguagem admitir falhas, e ver outras opções como sendo mais eficientes, modernas, seguras…

Eu já comentei em algum outro texto que o conjunto Python/Django funcionou como um catalizador da minha capacidade produtiva/criativa. Sempre tive várias idéias (não forçosamente boas) mas tinha uma grande dificuldade de colocá-las em prática em Java (que é a minha linguagem de atuação profissional), e Python me permitiu concretizar algumas de forma rápida e eficiente.

Hoje, depois de uma boa quantidade de linhas de código escritas nesta linguagem, das quais a grande maioria em produção de forma estável  no SigaSeuTime e no Job4Dev, me pego pensando em algumas características presentes em linguagens como Java que eu sinto falta. Na verdade, existe uma principal: tipagem de parâmetros de funções e métodos. Apesar dos amantes de Python me dizerem por meio de comentários que eu preciso mudar minha forma de pensar, ainda acho que tipagem de parâmetros facilita a leitura de códigos alheios, e que sobrecarga de métodos é um recurso bastante elegante e útil.

Por vários motivos, incorporei um subsistema em Java dentro do SigaSeuTime, que implementa uma das plataformas. Este subsistema foi desenvolvido por um programador freelancer, e recentemente tive que mexer no código para fazer algumas adaptações. E foi um ótimo estudo comparativo de ambientes: Java/Eclipse vs Python/Emacs (já testei Python/Eclipse, e não vi grandes vantagens…). Cheguei à conclusão de que, no quadro da minha startup, entre a rede de proteção gigantesca oferecida por Java e a rapidez de desenvolvimento oferecida por Python, eu ainda prefiro a segunda opção.

Não trabalhei em projetos com muitos desenvolvedores em Python (no máximo, eu e mais um ou dois), e tenho certeza de que a rede de proteção de Java evita muitos problemas potenciais de gente mexendo onde não devia, chamadas erradas, etc… Mas como eu sempre trabalhei com pessoas de alto nível no SigaSeuTime e no Job4Dev, a eficiência do ciclo de desenvolvimento/deploy do Python (e das linguagens de script dinâmicas em geral) me parece ser muito vantajosa em um projeto onde o importante é desenvolver rápido para colocar em produção rápido.

E quando eu digo rápido, significa eventualmente resolver um bug no código em produção, através de um Vi ou Emacs rodando em um terminal SSH. Sim, eu já fiz isso mais de uma vez, para o desespero de muitos dos leitores deste blog e defensores de CMMIs da vida.

Grandes empresas precisam implementar processos e mecanismos de controle para organizar o crescimento (muitas vezes desordenado) de pessoas, muitas vezes acompanhado pela redução da qualidade média dos desenvolvedores.

Em ambientes pequenos de startup, onde é possível imaginar uma equipe apenas composta por boas pessoas, os controles e processos são desnecessários e muitas vezes indesejáveis. Neste contexto, todas aquelas preocupações enterprise padrões devem ser deixadas de lado, e os participantes do projeto devem focar suas energias em apenas duas coisas: tornar o projeto uma realidade e trabalhar para que ele seja viável economicamente. O resto é resto…

O que há de legal em desenvolver o Eclipse?

O que eu acho mais legal em desenvolver O Eclipse é que se a extensão que você idealizar e implementar for algo que você acha que pode ser útil para várias pessoas você tem a possibilidade de contribuir esta funcionalidade de volta para o Eclipse.

O Eclipse é um projeto de código-aberto, com uma comunidade extremamente ativa. Para contribuir sua funcionalidade para o Eclipse funciona mais ou menos como em qualquer projeto de código-aberto: é necessário um certo grau de envolvimento com a comunidade de uma forma geral, por exemplo, através da participação em listas de discussão ou fóruns; é necessário que o que você deseje contribuir seja algo que a comunidade gostaria de adicionar ao projeto; e o seu código deve ser totalmente original e isento de qualquer impedimento jurídico, por exemplo, se tiver sido distribuído pelo resultado do seu trabalho para uma empresa, é necessário que a empresa libere o código para ser contribuído. Cumpridas estas premissas básicas, é só contribuir o código!

Agora, se você está achando que este processo pode ser burocrático e demorado eu lhes digo o seguinte: eu também pensava assim. Até que após trabalhar dois anos desenvovendo plug-ins para Eclipse a minha equipe e eu conseguimos ultrapassar todas as barreiras (internas e externas, sendo que as externas às vezes são as mais fáceis) e contribuimos todo o nosso produto de volta para o Eclipse. Hoje as mais de 45.000 linhas de código do Cell IDE, um conjunto de plug-ins que facilita a programação em C/C++ para processadores Cell é parte do PTP (Parallel Tools Platform), um sub-projeto do Eclipse que adiciona à plataforma básica funcionalidades específicas para facilitar a programação em C/C++ para clusters.

Bom, é claro que este lado legal de desenvolver O Eclipse pode ser vivenciado ao se contribuir para qualquer projeto open source (do kernel do Linux ao ‘cp’, comando de cópia de arquivos em ambientes UNIX-like). O que você ganha com isso? Bom, além de reconhecimento da comunidade, você certamente ganhará experiência na leitura e entedimento de código-fonte, no desenvolvimento de projetos e na comunicação com equipes de desenvolvimento (nem sempre tão) grandes e dispersas por várias partes do planeta.

Desenvolvendo O Eclipse – construindo seu primeiro plug-in

Escutamos muito as pessoas falarem em desenvolvimento no Eclipse, utilizando esta ferramenta poderosa como plataforma de desenvolvimento. Para mim o Eclipse é a melhor plataforma de desenvolvimento genérica na qual eu já trabalhei. E, certamente, é uma das melhores plataformas de desenvolvimento para Java (para mim A melhor) e C/C++ (com certeza não A melhor) que eu já usei.

Opiniões pessoais a parte, eu passei três anos, de 2006 a 2008, não apenas utilizando o Eclipse como plataforma de desenvolvimento mas também como produto final do meu trabalho. Ou seja, eu não só desenvolvi no Eclipse. Eu desenvolvi O Eclipse.

Muitas pessoas escutam falar que o Eclipse é uma plataforma extensível. Afinal de contas, se fosse diferente, certamente não teríamos os incontáveis plug-ins para Eclipse que adicionam inúmeras funcionalidades interessantes. O que talvez nem todo mundo saiba é que extender o Eclipse é muito fácil! E talvez por não saberem disso, acabam achando que é algo difícil e não se aventuram por este mundo interessante.

O melhor de tudo é que para extender o Eclipse a única coisa que você precisa é do própio Eclipse! Ou seja, a melhor ferramenta para desenvolver o Eclipse é o próprio Eclipse.

Neste artigo vou abordar o passo-a-passo de como criar um plug-in simples para o Eclipse.

Primeiramente, alguns conceitos. O Eclipse possui o que chamamos de pontos de extensão (extension points). Estes são arquivos XML que possuem configurações que definem possíveis extensões do Eclipse. A plataforma básica já fornece uma série de pontos de extensão que podem ser facilmente utilizados para extender as funcionalidades já disponíveis (por exemplo, neste mini-tutorial iremos criar um novo menu com uma ação específica). À medida em que você for ganhando mais traquejo na implementação de pontos de extensão, você vai naturalmente notar a necessidade de você mesmo criar seus próprios pontos de extensão a partir de coisas que você extendeu anteriormente da plataforma básica (espero falar disso em um post futuro).

Mas vamos ao que interessa a este tutorial. Para começar você vai precisar ter instalado uma máquina virtual Java. Sugiro as da IBM ou da Sun, já que elas funcionam muito bem com o Eclipse. Um aviso aos usuários de Linux: as máquinas virtuais que veem com as distros (GCJ ou iced-tea) em geral não funcionam corretamente e possuem bugs em funcionalidades básicas, tornando difícil ou impossível rodar o Eclipse com elas. Se você já roda o Eclipse como plataforma de desenvolvimento você certamente já possui uma máquina virtual Java instalada.

Depois é necessário instalar o Eclipse SDK. Outro aviso aos usuários Linux: também não recomendo os empacotamentos de Eclipse SDK que vem com as distros. Em geral são ligeiramentes diferentes em relação ao Eclipse distribuído pela Eclipse.org e, muitas vezes, possuem bugs que não existem na versão original.

Quando usado como plataforma de desenvolvimento para Java ou C/C++ não é necessário ter o Eclipse SDK instalado. Basta o runtime do Eclipse. Para instalar o Eclipse SDK basta certificar-se de que você baixou o pacote com o nome Eclipse SDK do site Eclipse.org ou que você tenha instalado a feature “Eclipse Project SDK” através do Update Manager do Eclipse runtime.

Bom, feito isso, siga os seguintes passos:

1) Crie um novo projeto de desenvolvimento de Plug-In para Eclipse.

1.1) Clique no menu File -> New -> Project….

1.2) Selecione a opção Plug-in Development -> Plug-in Project na janela que se abrir e clique no botão “Next”.

1.3) Dê um nome para seu projeto, por exemplo org.eclipse.test e clique no botão “Next”.

1.4) Clique no botão “Next” no próximo passo do Wizard, chamado de “Content”.

1.5) No passo de escolha de Templates, selecione o template “Hello, World”. Clique no botão “Next”.

1.6) No último passo do wizard, não altere nada e clique no botão “Finish”.

2) O Eclipse irá perguntar se você deseja alterar a Perspectiva atual para a Perspectiva de desenvolvimento de plug-ins. Clique em “Yes”.

3) O Eclipse abrirá o editor no arquivo MANIFEST.MF. Este arquivo define as características de seu plug-in como, por exemplo, de quais outros plug-ins ele depende, quais pacotes ele exporta, quais extension points ele extende, quais extension points ele provê e outras configurações. Não vou me ater a este arquivo pois ele não será realmente importante para o desenvolvimento deste caso simples.

4) Utilizando este Template “Hello, World”, você verá que o Eclipse criou uma pasta src/org.eclipse.test.actions com uma classe SampleAction.java. Abra esta classe no editor dando um duplo clique no arquivo.

5) Esta classe possui um método public void run(IAction action) que define qual ação será executada ao se clicar no menu que estamos criando. No caso deste template, a ação executada é bem simples: abre-se uma janela com uma mensagem de “Hello, Eclipse world”.

6) Para ver seu plug-in em ação numa instância de Eclipse não é necessário instalá-lo, ainda. O Eclipse provê uma funcionalidade através da qual, de dentro do Eclipse, você pode lançar um novo Eclipse que carregará os plug-ins que você está desenvolvendo no seu workspace. Para fazer isto você terá que “executar” seu plug-in de maneira semelhante ao que você já faz para suas aplicações Java ou C/C++.

6.1) Clique no menu Run -> Run Configurations….

6.2) Dê dois cliques em “Eclipse application” no lado esquerdo da janela que se abrir. O Eclipse criará um novo launcher para aplicação Eclipse que, por padrão, a incluirá os plug-ins que estão no seu workspace.

6.3) Clique no botão “Run”.

7) Um novo Eclipse será executado. Note que nele aparecerá um menu novo, que não existia na instância anterior de Eclipse, com o nome “Sample Menu”. Clique em Sample Menu -> Sample Action.

8) Uma janela será aberta com a frase que você definiu na classe SampleAction.java.

Parabéns! Você acaba de criar um plug-in para Eclipse ao extender o extension point que permite a adição de novas opções de menu ao Eclipse.

Um tutorial semelhante a este pode ser acessado de dentro do próprio Eclipse através das “Cheat Sheets” providas pelo Eclipse SDK. Clique em Help -> Cheat Sheets… e depois selecione a opção Plug-in Development -> Creating an Eclipse Plug-in na janela que se abrir. Selecione “Create a plug-in” na view que se abrir e siga os passos descritos na tela. Este tutorial, apesar de estar em inglês, possui uma quantidade bem legal de informações sobre como criar plug-ins para Eclipse com links explicando vários conceitos relacionados. Vale a pena!

Scala: faz barba, cabelo e bigode

Aprender Scala está na minha TODO list faz um bom tempo. Finalmente tive algum tempo umas semanas atrás pra dar uma olhada na linguagem. A motivação veio de diversas fontes. No laboratório onde trabalho nós estamos tendendo à usar Scala nos nossos desenvolvimentos futuros, devido a integração de elementos funcionais que facilitam a implementação de algumas partes do código; a minha pesquisa usa uma boa pitada de linguagens específicas de domínio (domain specific languages, DSLs) e Scala parece adequada para o desenvolvimento de embedded DSLs (por exemplo, veja essa DSL para SWT em Scala); e finalmente, tivemos uma palestra sobre tagless interpreters, que haviam sido implementados em Haskell e OCaml, e eu queria ver como implementar um interpretador de cálculo lambda em Scala.

Bem, não importa se você não sabe o que são tagless interpreters ou se não se importa com lambda calculus, o foco desse post é outro. Quando comecei a aprender Scala, eu vi que a linguagem realmente faz jus ao nome (Scala vem de SCAlable LAnguage, e o objetivo era ter uma linguagem que serve pra fazer desde pequenos scripts até grandes aplicações enterprise). Basta olhar a lista de features da linguagem que você percebe que Scala faz barba, cabelo e bigode!

Como não faz sentido discorrer sobre todas as features de Scala (isso merece um livro), eu vou me concentrar em duas pequenas coisas que deixam qualquer programador Java com inveja: Local Type Inference e Traits.

Local Type Inference (Inferência Local de Tipos)

Quantas vezes eu odiei ter que escrever tipos redundantes em Java (que já expliquei em alguns comentários anteriores). Imagine um método que devolve uma lista inicializada com um inteiro (é um exemplo estúpido, mas é só pra mostrar type inference in action). public List<Integer> getList() { List<Integer> list = new ArrayList<Integer>(); list.add(0); return list; }

Scala é staticamente tipada, o que significa que todos os tipos tem que ser verificados pelo compilador. Mas o compilador de Scala tenta ao máximo inferir o tipo que você está indicando. Você só precisa escrever o tipo se o compilador não conseguir determinar qual é o tipo correto. O mesmo código em Scala ficaria mais ou menos assim (Note que sou bem novato em Scala, então me perdoe se existem soluções mais elegantes): def getList() = 0 :: Nil

O código ficou pequeno não somente por inferência de tipos, mas vamos ver como que inferência ajudou (o que segue é como eu imagino o compilador pensando). Primeiro o compilador infere que Nil é uma lista vazia, então pode ter qualquer tipo. O “::” é na verdade uma chamada de método (o add) na lista Nil, passando zero (0) como parâmetro (em Scala, métodos que iniciam com “:” fazem bind à direita, então Nil – que é uma case class de List – é quem recebe o método). O compilador vê que 0 é um Int (o equivalente de Integer e int em Scala), então o resultado de chamar add em Nil é uma lista de inteiros (ou List[Int]). Finalmente, o compilador vê que essa lista é retornada pelo método, então o tipo do método é List[Int].

Com isso, ao invés de escrever o tipo de lista em 3 lugares diferentes, você não precisou escrever em lugar algum, pois o tipo foi inferido do conteúdo e essa informação foi propagada. Note que se a lista estivesse vazia, você teria que escrever pelo menos 1 vez qual é o tipo (pois não tem como inferir do conteúdo), mas é melhor que 3 vezes!

Traits

Traits são basicamente interfaces com implementação. Já é sabido faz um bom tempo que herança múltipla (multiple inheritance, MI) causa dores de cabeça enormes (o Google, por exemplo, proíbe uso de MI no desenvolvimento interno de aplicações C++). A resposta de Java foi o conceito de interfaces, que te dão um poder parecido com MI (porque uma classe pode estender diversas interfaces, então pode ser usada polimorficamente no lugar de qualquer uma delas), mas muito mais restrito (porque a classe tem que implementar os métodos de todas as interfaces).

Em Scala, as Traits são como interfaces, mas elas podem ser parcialmente implementadas, normalmente com código default. Isso resolve alguns problemas de interfaces. Em Java existem várias interfaces pra receber eventos de GUIs que contém diversos métodos (um pra cada tipo de evento, veja MouseListener por exemplo). Quando você só tá interessado em um tipo de evento (por exemplo, Mouse Pressed), você tem que implementar todos os métodos (normalmente deixando em branco). Se você tiver sorte e sua classe não estende nenhuma outra, você pode usar um dos adapters com implementações em branco (como MouseAdapter), mas não é sempre o caso. Outro caso típico é quando um dos métodos pode ser derivado dos outros, como no exemplo direto do tour de Scala: trait Similarity { def isSimilar(x: Any): Boolean def isNotSimilar(x: Any): Boolean = !isSimilar(x) }

Nesse caso, classes precisam somente implementar isSimilar pois elas já ganham de graça o isNotSimilar. Note que traits, como interfaces, não podem ser instanciadas, e têm que ser adicionadas a classes ou objetos.

E agora?

Eu dei aqui só uma mostra do que Scala tem, e na verdade não cheguei nem perto da parte que eu considero mais importante, que é a junção (bem elegante por sinal) dos paradigmas funcional e orientado a objetos. Inclusive, umas semanas atrás eu fui à uma palestra do Simon Peyton-Jones, que é um dos caras por trás de Haskell. Depois da apresentação eu conversei (por ótimos 2 minutos) com ele sobre Scala e ele se disse feliz que Scala está trazendo linguagens funcionais pra desenvolvedores que estariam presos em OO (tanto por instrução – o que se aprende nas universidades em geral – quanto pelo mercado de trabalho). Eu acho que ele ainda prefere Haskell, mas Scala introduz “desenvolvedores comuns” ao paradigma funcional, sem abdicar de ser prática (não que Haskell não seja, mas o fato de se poder chamar código Java de Scala faz com que a adoção seja bem mais fácil).

O que me pergunto é se “desenvolvedores comuns” vão conseguir entender o que Scala oferece e usar de forma eficiente (isso depois que surgirem “Scala Design Patterns”). Sempre ouço que na indústria o average Joe mal entende Java direito, imagina então Scala. Estaríamos chegando em uma era em que uns poucos desenvolvedores excepcionais, usando linguagens e ferramentas ultra eficientes, seriam capazes de desenvolver “qualquer” sistema e suprir a demanda do mercado? Ou seja, o mercado encolheria em termos de número de programadores, mas os que restarem teriam uma produtividade muito superior?

Não sei. Mas sei que Scala faz barba, cabelo e bigode. E se bobear, tem algum jeito daquele pelinho no fundo da orelha ir junto!

Next Page »

Switch to our mobile site