sql ou não, eis a questão

http://www.flickr.com/photos/timothymorgan/75593157/sizes/s/in/photostream/ Ultimamente tenho visto um grande movimento de tecnologias NoSQL pipocando na comunidade de desenvolvimento. Conversando com o @dcrec1, ele soltou uma frase bem interessante:

“parece que o povo tem medo de ir crescendo sabe, ja querem pegar a arma mais poderosa logo de cara”

Falávamos de como a tecnologia NoSQL virou febre, e tem sido utilizada muitas vezes de forma indiscriminada. Não quero dizer que a tecnologia é ruim (longe disso, sou fã de NoSQL, que inclusive pode ser uma das abordagens para solucionar problemas de escalabilidade).

Antes de adotar alguma solução NoSQL, vale a pena refletir sobre alguns pontos interessantes: (antes de mais nada, isso é uma reflexão, YMMV, IMO, então não corte os pulsos, etc)

1. Conheça seu problema

Não adianta você tentar usar um banco NoSQL se a sua aplicação precisa de um monte de relatórios de projeção de dados; um banco relacional vai tornar a tarefa bem mais agradável (e rápida, talvez)

2. Conheça a tecnologia

Não adianta você tentar usar um banco baseado em java se você nunca sequer brincou com código java. Não que você vá ter que mexer no código, mas normalmente cada linguagem tem seu ambiente e jeitão de executar tarefas; (o mesmo vale pra erlang, python, etc) Esse conhecimento pode vir a fazer falta em um momento de crise! (a regra perde sentido caso você possua um programador 7 por perto).

3. Conheça o seu ambiente

Um grande risco em projetos greenfield com soluções NoSQL é a falta de cultura em torno das novas ferramentas. Você sabe responder estas questões de bate-pronto? (Sim, eu sei, RTFM, mas pense "na hora da dor de barriga"....)

  • O que você faz quando o banco cair?
  • Como é o processo de backup?
  • Como monitorar?
  • Existe consolidação das bases de dados?

Essas perguntas, por mais inocentes que pareçam, podem ser respondidas com facilidade no caso de bancos SQL tradicionais, que possuem toda uma cultura em torno dos procedimentos de operação e manutenção.

E agora?

Por fim, mesmo que sua resposta tenha sido negativa à essas questões, ainda assim pode ser que um banco de dados não relacional seja adequado para atender perfeitamente as suas necessidades!

Se você tem testes e um domínio de objetos rico, fica muito mais fácil evoluir a “camada” de persistência da sua aplicação. Será que vale a pena adiar a implantação do banco NoSQL da moda (que de fato simplifica e muito a vida do desenvolvedor) e continuar com o bom e velho MySQL | Postgres | XptoSQL?

Os bancos SQL estão de fato com os dias contados?

Eu acho que não! A melhor ferramenta é aquela que você domina, não é?

Continuo acreditando fortemente no uso complementar de ambas tecnologias.

E você?


vá de bike

Post meio off-topic, mas acho que vale a pena falar sobre isso.

Há um bom tempo venho fazendo uma dieta forte, tentando reduzir o excesso de gordura sobrepeso acumulado.

Perdi 20kg nessa brincadeira, mas ficar “de regime” muito tempo é complicado, logo, pensei em procurar outra solução para o meu problema. Como todo bom sedentário, exercícios seriam a última (e inevitável) opção.

Já sem opção mesmo, me recordei de como gostava de andar de bike na minha adolescência, daí lembrei do Shadow e sua bike dobrável; a ficha caiu imediatamente:

Porquê cargas d’água eu não arranjo uma dobrável e começo a usá-la como meio de transporte intermodal?

@qmx na bike

Fiquei um bom tempo pensando no assunto, e acabei por comprar uma dahon mu p8, na freecycle, onde fui muito bem atendido por sinal - Recomendo!

E finalmente, comecei a peregrinação. Sabendo que ia ser complicado voltar a pedalar forte depois de 13 anos parado, comecei bem devagar, sem expectativas de conseguir concluir o percurso todo. Comecei subindo a av. sumaré, pela direita, tentando me acostumar com a bike nova (mesmo tendo ficado muito tempo sem andar, ainda senti um pouco de dificuldade pra acostumar com o tamanho reduzido das rodas (aro 20), dificuldade que sumiu rapidinho :)

Continuei andando bem até a metade da cardeal arco verde, onde logo percebi que a minha glicemia havia baixado e eu já estava começando a desidratar, (dieta ensina cada coisa pra gente...), parei num boteco e dobrei a bike, e já embarquei num ônibus cinco minutos depois. Apanhei bastante pra dobrar e guardar a bike na "mochila", mas acho que é uma simples questão de costume.

Resumindo: Pra um gordo que não andava de bike há mais de uma década, eu me saí muito bem: consegui andar mais de 5km, com uma velocidade média de quase 15km/h!

Espero conseguir fazer o percurso completo em breve: 17km da minha casa até a locaweb.

Os resultados foram nítidos logo de imediato: cheguei na locaweb bem cansado, mas bem mais disposto pra encarar o dia de trabalho.

Vá de bike! Melhor pra sua saúde, melhor pro meio ambiente!


da teoria à prática - levenshtein

http://www.flickr.com/photos/crosswordman/3930231228/sizes/s/in/photostream/ Normalmente, nossa área possui duas vertentes totalmente polarizadas: os práticos e os acadêmicos.

Antes de mais nada, espera-se de um bom profissional um equilíbrio interessante entre conhecimento acadêmico (não necessáriamente adquirido na academia) e o conhecimento prático.

Ambas as coisas são boas, o problema é a falta de equilíbrio entre as duas!

Vez por outra, alguns problemas da vida real se mostram verdadeiros “cases” para a aplicação de coisas altamente teóricas da academia, e como não podia deixar de ser, fui vítima me deparei com uma dessas recentemente.

Como comparar um dado oficial com um dado digitado por uma pessoa? A resposta inicial seria bem simples, não?

nome1 = “Av. Morvan dias de Figueiredo, nº 3600”
nome2 = “Av. Morvan dias de Figueiredo, nº 3600”

nome1 == nome2
=> true

O fato é que as coisas não são tão simples assim na vida real:

nome1 = “Av. Morvan dias de Figueiredo, nº 3600”
nome2 = “Av. Morvan dias de figueiredo, nº 3600”
nome1 == nome2
=> false

Oops, mas não é o mesmo nome?

O fato é que não é tão trivial assim fazer comparações de strings; o caminho natural seria imediatamente colocar tudo em maiúsculas ou minúsculas e comparar; daí teriamos os acentos esquecidos; depois teríamos alguém mais criativo:

nome1 = “Av. Morvan dias de Figueiredo, 3600”
nome2 = “Av. Morvan dias de Figueiredo, N 3600”
nome1 == nome2
=> false

Ué... mas não é o mesmo nome, qual o problema de retornar false? Isso se torna um problema enorme, já que tecnicamente as duas strings representam sim a mesma coisa! Nesse caso seria muito mais interessante medir a similaridade entre essas strings. Como fazer isso?

Existe um algoritmo muito interessante que calcula a quantidade de alterações que eu tenho que fazer pra que um grupo de dados fique igual ao outro, mais conhecido como Distância Levenshtein. Neste caso, ao comparar as duas strings usando levenshtein, obteria o valor 2. (tenho que colocar a letra “N” e mais um espaço, para que o nome1 fique igual ao nome 2, logo duas alterações).

Para conseguir um índice de similaridade, nada melhor do que inventar uma escala e tomá-la como base: elegi minhas regras elementares e cheguei em uma escala em porcentagem, seguindo esta fórmula:

indice de similaridade = 1 - (distância / tamanho da primeira string)

Isso vai chegar a um número interessante, no nosso caso como a string possui 36 posições, vamos ter um valor de 0.9444444444, ou seja, quase 95% de semelhança!

Claro que a regra não é tão abrangente, mas para simples comparações já ajuda, e muito!

Como a maioria dos algoritmos, esse também já possuía implementação open-source. Existe uma gem de ruby chamada text que se encarrega de implementar coisas comuns a análise textual. Então, encapsulei o código de comparação da similaridade entre strings e coloquei na minha gem de utilidades a canivete.

Veja o resultado final:

require 'rubygems'
require 'canivete/similarity'

string1 = “Av. Morvan dias de Figueiredo,  3600”
string2 = “Av. Morvan dias de Figueiredo,  N 3600”
string1.similarity_rate(string2)
=> 0.944444444444

Claro que isso pode não servir pra diversos casos, mas é bom conhecer esses algoritmos!

Você conhece mais algum caso? Comente!


acelerando vms linux no windows

http://www.flickr.com/photos/martin_heigan/4544138976/sizes/m Recentemente passei por uma situação onde o ambiente padrão é windows, mas podemos usar linux dentro de uma máquina virtual (VM). No geral tudo funciona muito bem, exceto o vídeo, que costuma ficar muito lento, especialmente se você está usando VirtualBox.

Minha motivação para não utilizar o VMware player, que proporcionaria um vídeo mais rápido, é o fato de não existir versão do player pra OSX (Apenas o VMware Fusion, que é bem pago) - e eu gosto de poder migrar as imagens de SO sem maiores complicações.

A ferramenta que salvou o dia é o Xming - um servidor X para windows, que utiliza os recursos de vídeo acelerado disponíveis para renderizar as janelas, etc, proporcionando uma experiência de uso bem legal!

O segredo é instalar o Xming, e após isso iniciar os processos dentro da VM, só que apontando para um display diferente, o display do Xming! Isso é muito fácil de fazer, basta usar a variável DISPLAY dentro de qualquer terminal.

Se você estiver usando VirtualBox no modo NAT (padrão), a sua máquina hospedeira estará acessível de dentro das VMs no endereço ip 10.0.2.2, então basta fazer isso (após iniciar o Xming)

DISPLAY=10.0.2.2:0 xterm &

Este comando pedirá ao linux que execute um xterm no display 0 da máquina 10.0.2.2.

A parte mais legal, é que uma vez que o xterm apareceu, tudo que você iniciar nele já usa o novo display automaticamente; dá até pra iniciar um gerenciador de janelas, como Gnome ou KDE!

Vale lembrar que o protocolo de rede usado pelo X é por padrão inseguro, então só serve mesmo pra usar em casos como esse ou redes locais; se precisar transitar esses dados via internet, usar x11 forwarding over ssh provavelmente será uma opção melhor; não tão rápida, mas mais segura com certeza!

Mão na roda!


DSLs externas

Um grande benefício trazido pelas idéias do Domain-Driven Design (DDD) é a diminuição da impedância na comunicação entre cliente e desenvolvedores, através de uma linguagem ubíqua. A ideia é que os termos do negócio sejam usados tanto por desenvolvedores, como por clientes.

Mas, que diferença isso faz afinal? Muita!

Os desenvolvedores, que por natureza tem enorme facilidade em adicionar complexidade, sofrem um efeito colateral muito interessante ao serem expostos à uma linguagem ubíqua: são obrigados a simplificar sua forma de pensar. Tarefas consideradas corriqueiras ganham mais atenção, ao passo que cenários onde a complexidade seria predominante, em um momento de inspiração, são reduzidas a pequenos incrementos.

Uma das formas de catalisar o entendimento do negócio do cliente é diminuir ainda mais o ruído durante o desenvolvimento, utilizando DSL’s.

DSL? De novo?

Assunto muito martelado, com aplicações bacanas tanto na teoria como na prática;

Apesar de possuirmos linguagens dinâmicas (ruby), flexíveis (lisp) e poderosas para criação de DSL’s (scala), às vezes se faz necessário criar linguagens totalmente fora do comum: mais declarativas e menos imperativas: as famosas DSL’s externas. Acredito que o exemplo mais popular de DSL externa seja a linguagem do cucumber, chamada gherkin:

Cenário: Adicionar um contato
    Dado que eu estou na página inicial
    E eu sou um usuário autenticado
    Então eu devo ver “adicionar novo usuário”

Muito legal de usar, mas como isso realmente funciona? Como fazer a minha própria DSL?

Esta madrugada, o @rodrigoy me mostrou o kanban_sketch, uma ferramenta interessante pra montar um painel de kanban a partir de uma DSL simples:

selected(A,B,R,T)
development:5
  [acceptance:1(C,Z)]
  [in progress:3(Q,Y,W)]
  [done!()]
deployment:3(E)
in production(F,K,L,M,N)  

isso deve produzir um resultado mais ou menos assim:

kanban_sketch

Interessante!

Por mais que nós desenvolvedores conseguíssemos entender bem um hash de ruby {:selected => [‘A’, ‘B’, ‘R’, ’T’] ......}, acredito que o formato anterior ainda traz maior legibilidade: muitas vezes vale o esforço!

E no quê consiste esse esforço?

Para conseguir transformar o texto solto em código, precisamos inicialmente fazer o “parse” deste texto - transformá-lo em uma estrutura normalizada, e já identificar possíveis erros de sintaxe.

Sintaxe?

Sim, por mais que muita gente já torça o nariz lembrando das aulas de português, o fato é que para que haja uma sintaxe, precisamos construir uma gramática, que diga quais serão as regras que nosso texto deve obedecer. A gramática do kanban_sketch está ficando assim:

grammar KanbanDSL

  rule stage
    (name (':' limit)? (cards / substages) ';')*
  end

  rule substages
    substage*
  end

  rule substage
    '[' name (':' limit)? cards ']'
  end

  rule limit
    [0-9]+ {
      def text_value
        text_value.to_i
          end
    }
  end

  rule cards
    '(' ((name [,]?)+)? ')'
  end

  rule name
    [a-zA-Z0-9\s]+
  end

end

Como você pode ver, uma gramática é realmente uma série de regras - literalmente :)

Em segundo lugar, após ter passado pelo parser, vamos obter uma AST, que não é nada além de uma árvore de sintaxe abstrata, que descreve os blocos tratados pelo parser com objetos, prontos para serem manipulados!

Acredito que a ferramenta mais famosa para isso seja o antlr - muito poderoso (podemos usar pra praticamente qualquer tipo de linguagem), e por consequência, extremamente complexo. Uma alternativa bem mais simples é o treetop, que utiliza uma abordagem diferente do antlr, preferindo clareza de código à performance. Esse tradeoff entre performance e complexidade, será abordado em um post futuro, se o tempo me permitir :)

Você encontrará mais detalhes sobre como usar o antlr aqui e o treetop aqui.

Uma vez que os desenvolvedores passam a dominar os termos do negócio, se tornam poderosos instrumentos de mudanças e melhorias, não só no software como também no negócio do cliente!

Agradeço ao @rodrigoy pela #provocaçãogratuita :D


pareando remotamente com tmux

Este artigo é uma continuação do pareando remotamente

No outro post, havíamos falado do screen, uma excelente ferramenta tanto para pareamento remoto, como para simplesmente garantir que os programas continuem rodando mesmo que a sua conexão ssh caia.

Porém, como nem tudo é perfeito, o screen tem suas limitações, e, no melhor estilo, surge na comunidade uma alternativa interessante: tmux

Se eu tinha falado de zilhões de atalhos para você conseguir fazer uma sessão de pair-programming remoto via terminal, sinto desapontá-lo, mas o tmux tornou tudo mais fácil:

Enquanto um usuário conecta no servidor e executa

tmux

O outro usuário conecta com o mesmo usuário e executa

tmux attach

O resultado é instantâneo, simples e eficiente. Tudo que você estava acostumado a usar no screen continua funcionando no tmux; a única diferença é que o atalho ctrl+a virou ctrl+b, por questões de interoperabilidade (o criador do tmux era usuário do screen e desenvolveu o tmux usando screen). Isso pode ser configurado, mas isso fica para outra oportunidade.

Acho que a principal coisa a destacar no tmux é o suporte a splits (uma beleza pra usuários de vim como eu), suporte a unicode e 256 cores; falando das partes internas, uma arquitetura 100% client/server, permitindo inclusive que as janelas possam ser movidas de uma sessão para outra, além de retirar um monte de funcionalidades obscuras presentes no screen, como suporte a terminais seriais e outras coisas exóticas. A descrição completa das diferenças você pode encontrar aqui

Já experimentou? Aposentei o screen por aqui...


batch - escalando um sistema sem fermento

No último Ruby + Rails no Mundo Real, tive a oportunidade de falar mais um pouco sobre processamento batch.

http://www.flickr.com/photos/scarlet_rose/354921254/sizes/s/

Por mais que nós desenvolvedores sempre busquemos maior performance em nossas aplicações web, muitas vezes, a melhor alternativa para obter melhores tempos de resposta acaba sendo diminuir o tamanho dessa resposta!

Parafraseando, se o relatório anual demora 12 minutos para ser processado, é provável que você consiga reduzir o tempo para apenas 1 minuto se você devolver um relatório mensal. Parece até imbecil, mas lidamos com tantos problemas absurdos no dia-a-dia que acabamos por diversas vezes nos esquecendo do óbvio. (é claro que estou ilustrando um cenário onde já fizemos melhorias, chegando a um ponto onde teoricamente não teríamos mais como melhorar o tal relatório).

Migrar um processo para tarefas em segundo plano permite que possamos devolver de imediato uma resposta ao nosso cliente web, e nos bastidores dividir uma tarefa grande em pedaços menores, que por sua vez podem ser divididos entre vários processos ou até máquinas. Dependendo do nosso nível de automação, podemos até disparar mais instâncias no amazon ec2, por exemplo, para ajudar no processamento, e desligá-las em seguida. Tarefas que demandariam um enorme investimento inicial se tornaram acessíveis a pequenos empreendedores, abrindo um leque de possibilidades quase infinito.

Para começar a usar processos em batch, você não precisa de ferramentas caras, ou de soluções de alta complexidade. Basta desacoplar serviços em pedaços do sistema que possam ser iniciados em uma outra linha de execução, quer seja usando threads, fibers, actors ou uma ferramenta de processamento batch como resque, ou em casos mais avançados, alguma implementação de MapReduce, como o hadoop.

E você, usa batch hoje em dia?

Veja os slides da palestra ou assista o vídeo da palestra.

A você que me aturouprestigiou no evento, muito obrigado!

Um agradecimento especial ao @agaelebe, que sempre tem feito as filmagens e nos ajudado a divulgar o guru-sp.


Pareando Remotamente

Não preciso tecer comentários sobre as vantagens da programação em par. Se você ainda tem dúvidas, leia isto

pair - taken from http://www.flickr.com/photos/cobalt/677911778/sizes/m/

Às vezes não é possível a presença física de um dos pares, por diversos motivos. Para esse tipo de situação, screen! (contando que você consiga usar editor modo texto)

Não vou me aprofundar no screen em si, deixando uma receita de bolo para os impacientes:

Você vai precisar de uma máquina acessível por ssh, com o screen instalado - praticamente todas as distribuições de linux possuem um pacote pro screen.

Receita de bolo

  • acesse a máquina remota
  • execute screen
  • ctrl + a :multiuser on (sim, este comando é bem chato para quem não está acostumado, isso vai colocar o screen no modo de compartilhamento de tela
  • peça ao outro desenvolvedor para acessar a mesma máquina (com o mesmo usuário, sei que funciona com usuários diferentes, mas ainda não testei)
  • o outro desenvolvedor executa screen -rx e voilá, já temos uma tela compartilhada entre os pares.

Algumas dicas do screen

  • ctrl + a d => desconecta o terminal, e deixa ele rodando no servidor. Isso é extremamente útil em conexões que ficam caindo o tempo todo...
  • ctrl + a c => cria um novo terminal virtual, que pode ser acessado usando.....
  • ctrl + a 0 => acessa o terminal virtual #0
  • ctrl + a 1 => acessa o terminal virtual #1 e assim respectivamente...
  • ctlr + a ? => acessa a ajuda do screen

Viu como é fácil?

Agradeço ao Jeff Schoolcraft pela dica, me ajudou muito a começar a brincar com cucumber / rspec.