
Às vezes temos que fazer operações de carga / extração em bases de dados.
Como não podia deixar de ser, muitas vezes esse banco de dados é um banco totalmente legado, entupido de chaves compostas, e pra piorar a situação, concorrido entre diversas aplicações da empresa.
Como extrair dados sem impactar a performance do banco de origem?
Antes que você me fale que existem ferramentas de ETL, meu objetivo é mostrar alternativas, certo? Então, vamos lá.
Uma abordagem simples e interessante é uma implementação do modelo de produtor / consumidor, utilizando uma fila e duas threads:
require 'thread'
fila = Queue.new
TAMANHO_TOTAL = 100
produtor = Thread.new do
# extrai os dados de algum lugar
(1..TAMANHO_TOTAL).each do |i|
# simulando trabalho
sleep rand(1)
fila << i
end
end
consumidor = Thread.new do
# array de trabalho
buffer = []
(1..TAMANHO_TOTAL).each do
buffer << fila.pop
# vamos processar de 4 em 4 items
if buffer.size >= 4 or not produtor.alive?
# faz alguma coisa com as tarefas
puts buffer.inspect
# limpa a fila
buffer.clear
end
end
# faz alguma coisa com as tarefas que sobraram
puts buffer.inspect
buffer.clear
end
consumidor.join
Simples não? E você ainda ganha muito mais se executar esse mesmo código com jruby, graças ao suporte à threads da JVM.
Here's a quick tip to highlight trailing whitespace - put this on your .vimrc:
match Todo /\s\+$/
This will flag them the same way as TODO or FIXME, with a ugly yellowish mark:

To remove them, run this on normal mode:
:%s/\s\+$//e
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:

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
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...
No último Ruby + Rails no Mundo Real, tive a oportunidade de falar mais um pouco sobre processamento batch.

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.
I've just finished deploying of my new useless app - it's called katch-up.
The main idea came after a slow working month, endangered to be a short money month - I've caught myself several times recounting how many hours I still needed to work to fill my monthly contract, and believe me, this is not a good experience.
So, despite most of us (including me) are with lots of extra hours (all months), I will probably make something simple to improve the app experience, like give people ability to inform how many hours they have already worked - perhaps the app could warn when a predefined threshold is attained...
What do you think? Do you have any idea to share?
Thanks to @scalone for pairing with me at this app. We've done it in a kinda dojo form. Rewarding, as usual.
Finally I got rid of enki's default theme!
What do you think? All critiques/comments will be more than welcome!!!
It doesn't ends with world's famine, but at least allows you to mark some methods of your ruby objects as deprecated and they will spit a warning every time you access them.
I think it has room for more - have you any idea to share?
install with gem install canivete or grab source code here
edit: I needed to change the name from ruutils as a gem with a very similar name exists (rutils) - thanks for pointing out jastix.
Não preciso tecer comentários sobre as vantagens da programação em par. Se você ainda tem dúvidas, leia isto

À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.
screenctrl + a :multiuser on (sim, este comando é bem chato para quem não está acostumado, isso vai colocar o screen no modo de compartilhamento de telascreen -rx e voilá, já temos uma tela compartilhada entre os pares.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 #0ctrl + a 1 => acessa o terminal virtual #1 e assim respectivamente...ctlr + a ? => acessa a ajuda do screenViu como é fácil?
Agradeço ao Jeff Schoolcraft pela dica, me ajudou muito a começar a brincar com cucumber / rspec.
How can we ignite somewhat sleepy/lazy brains?
I just had an insane idea - no guarantees - you'll need:
Instructions:
Would it work? Any neat ideas to share?
Inspiration shamelessly taken from softwarebyrob.com
Recently I moved to the cloud!
The experience is amazing - Rackspace has really beefed up their servers, all my services feel snappier. No turning back.
Yeah, finally I've moved from jekyll - jekyll is awesome, but there are times that you don't have ssh access, and want to blog. This is my main motivation to go to enki, a very smart blog engine written in ruby/rails. Stay tuned!
I know that the visual is horrible, I will fix it this ASAP
This is the first post of the git series - small useful tips for the everyday git.
This tutorial is about [Gitosis] setup. From the project's readme:
Gitosis aims to make hosting
gitrepos easier and safer. It manages multiple repositories under one user account, using SSH keys to identify users. End users do not need shell accounts on the server, they will talk to one shared account that will not let them run arbitrary commands.
For this recipe, we will use some conventions:
We will need a linux server; my setup will be based on a ubuntu system, but you can use almost any *nix flavor.
You will need to have an ssh server installed as pre-requisite - run sudo apt-get install ssh to install it. (thanks DJC)
Install Compilation Tools & required libs for git
user@srv:~$ sudo apt-get install build-essential libssl-dev \
zlib1g-dev libcurl4-openssl-dev libexpat-dev
Download & uncompress Git sources
user@srv:~$ wget http://kernel.org/pub/software/scm/git/git-1.6.4.4.tar.bz2
user@srv:~$ tar -jxvf git-1.6.4.4.tar.bz2
Build & install git
user@srv:~$ cd git-1.6.4.4
user@srv:~/git-1.6.4.4$ make prefix=/usr/local NO_TCLTK=1 all
user@srv:~/git-1.6.4.4$ sudo make prefix=/usr/local NO_TCLTK=1 install
user@srv:~/git-1.6.4.4$ cd
Install required python libs
user@srv:~$ sudo apt-get install python-setuptools
Download & install gitosis
user@srv:~$ git clone git://eagain.net/gitosis.git
user@srv:~$ cd gitosis
user@srv:~/gitosis$ sudo python setup.py install
Create our git user
user@srv:~$ sudo useradd -s /bin/bash -U -d /var/lib/git -m -r git
Generate the gitosis-admin ssh key (if you don't have one already)
user@local:~$ ssh-keygen -t rsa -C user
press enter for the default location, then provide it with a passphrase
copy the generated public key to server
user@local:~$ scp ~/.ssh/id_rsa.pub user@srv:/tmp/user.pub
Log in as the newly created git user
user@srv:~$ sudo su - git
git@srv:~$
Initialize gitosis
git@srv:~$ gitosis-init < /tmp/user.pub
Initialized empty Git repository in /var/lib/git/repositories/gitosis-admin.git/
Reinitialized existing Git repository in /var/lib/git/repositories/gitosis-admin.git/
Adjust some permissions on admin repository
git@srv:~$ chmod +x ~/repositories/gitosis-admin.git/hooks/post-update
Clone the gitosis-admin repository
user@local:~$ git clone git@srv:gitosis-admin.git
Initialized empty Git repository in /home/user/gitosis-admin/.git/
remote: Counting objects: 5, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 5 (delta 0), reused 5 (delta 0)
Receiving objects: 100% (5/5), done.
Voilà! Your gitosis setup is working! Let's take a look at gitosis's structure:
gitosis.conf
keydir/
keydir/user.pub
To finish our recipe, lets add a new user & a new repository
Let's call our new user john
Get john's ssh public key and put it inside keydir/john.pub
Add to gitosis.conf:
[group new-repo]
writable = new-repo
members = user john
As gitosis is managed by git itself, let's commit our changes:
user@local:~/gitosis-admin$ git status
# On branch master
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: gitosis.conf
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# keydir/john.pub
no changes added to commit (use "git add" and/or "git commit -a")
user@local:~/gitosis-admin$ git add keydir/john.pub gitosis.conf
user@local:~/gitosis-admin$ git commit -m "added new-repo + john keys"
[master ad62139] added new-repo + john keys
2 files changed, 4 insertions(+), 0 deletions(-)
create mode 100644 keydir/john.pub
user@local:~/gitosis-admin$ git push origin master
Counting objects: 8, done.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 1.02 KiB, done.
Total 5 (delta 0), reused 0 (delta 0)
To git@srv:gitosis-admin.git
bdc4dbc..ad62139 master -> master
Finally, let's john push his work to the shiny new repository:
john@local2:~/new-repo$ git remote add origin git@srv:new-repo.git
john@local2:~/new-repo$ git push origin master
Counting objects: 3, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 241 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@srv:new-repo.git
* [new branch] master -> master
C'est fini! A complete setup running. Enjoy!
If you have any doubts / corrections, please comment!