Mais produtividade com uma área de trabalho maior

Já faz um tempão que li um post do Martin Fowler que falava sobre o aumento de produtividade resultante do uso de dois monitores grandes, em lugar de um único e pequeno monitor. Na época, achei bem interessante a idéia, mas como estava totalmente fora do meu alcance ter uma área de trabalho dessas — em meu emprego da época —, preferi simplesmente deixar pra lá. Mas ultimamente, mesmo adorando a tela do meu MacBook 13.3” — que passei a levar pro meu emprego atual —, de tanto ver pessoas ao meu lado usando dois monitores grandes, de maneira tão inteligente e produtiva, passeir a querer testar isso também.

A deixa final

Como já disse algumas vezes aqui no blog, em meus times, além de alguns legados, lidamos basicamente com Ruby on RailsC#/ASP.NET MVC e Git como DVCS. Então, além de um bom editor de textos e um terminal, precisamos também de um Visual Studio — com ReSharper, porque sem isso, ele não é nada — que, infelizmente, para usuários de Mac e Linux, só roda em Windows. Tentei resolver isso usando Mono, mas acabei desistindo — por enquanto, porque vai ter revanche!

Bem, resolvi então usar o Parallels Desktop 5 para rodar o Visual Studio 2010 no conforto do meu Mac e, de tabela, adicionar mais um monitor à minha área de trabalho.

Meu space de programação

Pra mim ficou fantástico! Porque no meu space de programação deixei o Visual Studio maximizado na tela grande (à esquerda), rodando no Windows, que por sua vez está rodando no Parallels Desktop, em tela cheia e com look & feel de Mac OS X; e na tela do Mac (à direita) — que eu adoro! —, deixei o terminal, onde posso interagir com o Git e tudo mais. Yay!

Mac + VS
Visual Studio 2010 no Windows (à esquerda); Terminal no Mac OS X (à direita)

E tem mais: quando não precisar usar o Visual Studio por um longo tempo, tenho duas alternativas:

– desligar o Windows;
– ou simplesmente pausá-lo no Parallels Desktop.

E se for o caso, arrastar o TextMate pra tela grande.

Ficou muito bom isso, o Parallels Desktop é demais!

Meus outros spaces

Uma área de trabalho dessas não serve só pra programação. Hoje mesmo precisava editar um wiki enquanto olhava dados em uma planilha. Sem problemas! Planilha na tela grande e wiki sendo editado na tela do Mac. Fantástico!

Só faz um dia que estou com essa área de trabalho expandida e sinto que não posso mais trabalhar sem ela. hehehe

Erlang: system_info pode te dizer coisas legais

Ontem à noite, antes da sessão pão de queijo com chá mate aqui em casa, resolvi brincar um pouco com uns módulos de baixo nível de Erlang, porque de manhã havia me lembrado de um post bem legal, de um cara chamado Krzysztof Kliś, que li no ano passado. (Aliás, aproveitei e colei o código dele no meu gist, pra favorecer a leitura com syntax highlighting.)

Bem, dessa brincadeira saiu o módulo system_info, que você pode conferir no meu GitHub, no projeto de estudo getting_system_info.

O que ele faz?

Basicamente, ele oferece informações de load da máquina, quantidade de processos rodando e uso de memória do nó atual ou do cluster. Você pode ter mais detalhes sobre o formato dessas informações dando uma olhada nos testes do projeto.

Qual a utilidade disso?

Como disse, escrevi esse código depois de me lembrar do post do Krzysztof Kliś sobre seu load balancer [de apenas 48 linha]. Escrevi por pura diversão.

Mas, sim, se amanhã ou depois eu precisar escrever algum load balancer ou aplicativo que monitore load, processos e memória do meu cluster, ele poderá me servir de helper.

Dá pra testar e ver se funciona?

Sim, a menos que você seja usuário de Windows. Não, não é preconceito, é que algumas funções que uso não estão disponíveis pra Windows, apenas pra sistemas operacionais Unix-like.

Você pode fazer isso de duas maneiras:

1- Rodando os testes

Clone o projeto — o único problema é que você vai levar uma porção de outros projetos de brinde. I’m sorry! — e em seu diretório raíz, compile e rode os testes.

$ ./compile.sh
$ ./test.sh

Só que dessa maneira você não consegue ver nenhuma informação útil. Vamos à segunda maneira.

2- Rodando as funções no Eshell

Depois de devidamente clonado e compilado, crie um cluster com três nós. (Se não souber como a arquitetura de cluster de runtimes Erlang funciona, tenho um post introdutório pra você.)

Na raíz do projeto:

a. Inicie três nós, um em cada terminal

$ erl -sname n1 -pa ebin/
$ erl -sname n2 -pa ebin/
$ erl -sname n3 -pa ebin/

b. No n1, estabeleça conexão entre os nós

(n1@codezone)1> net_kernel:connect('n2@codezone').
(n1@codezone)2> net_kernel:connect('n3@codezone').

Agora, todos os três nós estão conectados uns aos outros, já que, por padrão, os nós compartilham suas conexões uns com os outros.

c. Ainda no n1, verifique as informações de system_info

(n1@codezone)3> system_info:node_load().
(n1@codezone)4> system_info:cluster_load().
(n1@codezone)5> system_info:node_processes().
(n1@codezone)6> system_info:cluster_processes().
(n1@codezone)7> system_info:node_memory().
(n1@codezone)8> system_info:cluster_memory().

Agora, sim, você tem informações a valer!

Gostou?

Espero que sim, porque system_info pode te dizer coisas legais. =)

Erlang: Programação Distribuída de maneira simples

Fazia tempo que estava para blogar algo sobre como é fácil fazer programação distribuída com Erlang. Derrepente, hoje, acabei perdendo o sono e eis aqui o post.

O mais simples do mundo

Pra começar, vamos ver o exemplo mais simples de computação distribuída que se pode fazer e aprender alguma coisa com ele. Ele é como um simples chat. Pois muito bem, vejamos!

Fazendo o setup

No terminal, inicie um Eshell com o seguinte comando:

$ erl -sname jose

E num outro terminal, inicie outro Eshell com:

$ erl -sname maria

Agora vá no primeiro terminal, no Eshell do José, e execute o seguinte comando:

(jose@codezone)1> register(console_jose, self()).

E no segundo terminal, no Eshell da Maria, faça o mesmo:

(maria@codezone)1> register(console_maria, self()).

Tudo bem, setup feito, hora do bate-papo!

Jogando conversa fora

“Ei José, diga oi…”

(jose@codezone)2> {console_maria, 'maria@codezone'} ! "Oi Maria, tudo bem?".

Veja o terminal da Maria. O que aconteceu? Nada? A mensagem não chegou? Chegou, chegou sim. Vejamos:

(maria@codezone)2> regs().

Na primeira coluna, procure pelo processo console_maria. Achou? Agora veja na última coluna desse processo. Que número tem aí? 1? Pois é, isso nos indica uma coisa. Ainda nesse Eshell, execute o seguinte comando:

(maria@codezone)3> flush().

Opa! E agora? Shell got “Oi Maria, tudo bem?”, certo? Taí a mensagem que a Maria recebeu do José.

Agora, que tal a Maria ser gentil com o José e responde-lo cordialmente?

(maria@codezone)4> {console_jose, 'jose@codezone'} ! "Vou bem, e voce?".

Se você quiser, pode ver o registro de processos no Eshell do José, como fez anteriormente com o da Maria. Ou pode simplesmente:

(jose@codezone)3> flush().

E receber a mensagem Shell got “Vou bem, e voce?”.

Entendendo tudo isso

Por sorte, não há muito o que explicar até aqui — já que fizemos o exemplo mais simples do mundo. Uff!

Que tal começar do começo? Vamos entender os passos de setup?

1- A primeira coisa que fizemos foi iniciar dois Eshell que, na verdade, tornaram-se dois nós do nosso cluster de runtimes Erlang.

Todas as vezes que você inicia um Eshell com a flag -sname, o que você está fazendo é criar um nó de runtime Erlang na sua rede. Na verdade, isso pode ser feito também com a flag -name.

Qual a diferença entre elas?

-sname cria o nó e dá a ele um “short name”: nome_do_no@host;
-name, pelo contrário, cria o nó dá a ele um “long name”: nome_do_no@ip_address ou nome_do_no@host.local, no caso de rede local.

Você pode perfeitamente iniciar diversos nós em uma mesma máquina, como fizemos a pouco. No entanto, você não pode duplicar os nomes dos nós, uma vez que estes são usados para identificá-los no cluster e torná-los comunicáveis uns com os outros.

“Lembrando que o nome dos nós são sempre sufixados pelo nome/ip do host, não há problema algum em ter o mesmo nome de nó em máquinas diferentes.”

Uma outra coisa interessante de aprender aqui é como os nós se comunicam. Toda comunicação entre nós é feita por um daemon chamado epmd. Este programa faz parte do sistema de runtime Erlang e tem um papel fundamental em sua arquitetura de clusters, porque sempre que “o primeiro nó” é iniciado numa máquina, automaticamente, ele também é iniciado, caso ainda não tenha sido, e passa a escutar mensagens na porta 4369 e rotea-las para o nó apropriado.

“Independente de quantos nós estejam rodando numa máquina, sempre haverá apenas uma instância do epmd rodando.”

Por fim, ainda sobre o setup dos nós do cluster, há uma outra flag que não demonstrei no exemplo acima, mas que é bem interessante e você depois pode pesquisar a respeito.

-setcookie define um “secret cookie” que serve como um tipo de token para autenticar a comunicação entre os nós do cluster. Isso quer dizer que, somente os nós iniciados com um mesmo cookie podem se comunicar. Por outro lado, sempre que um nó é iniciado sem especificar um cookie, o runtime Erlang toma a liberdade de cria um e gravar no arquivo ~/.erlang.cookie. Nestes casos, todos os nós não iniciados com um cookie compartilharão o mesmo cookie guardado nesse arquivo.

No caso do nosso exemplo ultra simples, um cookie poderia ser usado para criar uma sala de bate-papo, onde: se um nós é iniciado informando um cookie, ele entra na sala equivalente; no entanto, quando não informado, vai para uma sala genérica.

Interessante? Pois é… E esse assunto acaba puxando o da flag -hidden, que você pode aproveitar e pesquisar também.

2- A segunda coisa que fizemos no setup foi registrar um processo alvo de nossas mensagens.

Como a idéia aqui é explicar — um pouco, porque ainda há uma porção de coisas que poderiam ser faladas, mas isso deixaria esse post imenso! Dê uma olhada na documentação oficial como funciona a arquitetura de cluster de runtimes Erlang e mostrar como este provê uma maneira simples de programação distribuída, preferi não escrever um programa de chat, mas apenas usar o próprio Eshell para isso.

Com este pré-requisito em mente, o que fiz foi apenas registrar o próprio processo do Eshell — usando self(), que você entende como funciona com um nome especifico em cada nó do cluster (console_jose para um e console_maria em o outro) para fazer a troca de mensagens entre eles.

E o bate-papo, como é que rolou?

Essa é a parte mais fácil da coisa, na minha opinião. Se você já lidou com processos em Erlang, vai tirar de letra.

1- Trocamos mensagens entre os dois processos de maneira bem semelhante ao que fazemos normalmente com processos contidos num único runtime.

A única diferença aqui é que, em vez de simplesmente codarmos algo como console_jose ! “Show de bola”, codamos {console_jose, ‘jose@codezone’} ! “Show de bola”. Ou seja, além no nome do processo, informamos também em que nó do cluster ele está, tudo em uma tupla.

Um exercício legal de você fazer é o seguinte…

a. No Eshell da Maria execute:

(maria@codezone)5> console_maria ! "Show de bola".
(maria@codezone)6> flush().

b. Depois, ainda no Eshell dela, execute:

(maria@codezone)7> console_jose ! "Show de bola".

O que aconteceu? Na primeira execução, o Eshell da Maria recebeu uma mensagem, correto? Mas na segunda execução, o Eshell “crasheou”. Por quê? Porque ele não reconheceu o átomo console_jose como sendo o nome de um processo, uma vez que o processo registrado como console_jose está em outro nó do cluster. Aliás, como o Eshell da Maria crasheou, se você tentar enviar mensagens a ele novamente, como fez anteriormente e havia funcionado, ele vai crashear novamente, porque a referência ao processo que havia sido registrada tornou-se inválida.

Você precisa ficar muito atento a isso, porque quando você manda um mensagem para um processo que está em outro nó, mesmo que ele não exista, você não receberá erro — exatamente como acontece com envio de mensagens pra processos locais inexistentes.

Quer ver? Faça o seguinte teste:

(maria@codezone)8> {console_jose_123, 'jose_abc@codezone_xyz'} ! "Nao vai crashear".

E agora, o que aconteceu? Nada!

2- Outra coisa que fizemos foi usar os truques de flush() e regs(), mas esses já são bem conhecidos.

Se você costuma usar o Eshell, com certeza, já deve ter usado flush() e regs(). Caso ainda não tenha usado, aqui vai um resumo:

flush() descarrega as mensagens contidas na caixa postal do Eshell (que como você sabe, nada mais é do que um processo Erlang qualquer);
regs() lista os processos registrados do runtime em execução.

Só o gostinho

Como disse em algum canto nesse post, ainda há bastante o que falar sobre programação distribuída com Erlang. Só pra variar, esse post foi só pra dar o gostinho. Ainda há muito mais!

Bem, quem sabe qualquer dia desses não perco o sono novamente e escrevo um pouco mais sobre o assunto. Quem sabe?

Minha apresentação na Agile Brazil 2010

Há dois meses postei aqui minhas duas propostas para o evento Agile Brazil 2010. Uma delas foi aceita — “Como vi Scrum ser completamente rechaçado em uma grande empresa”.

Qual a idéia dessa palestra?

Bem, nem só de acertos vive um agilista — os contadores de “case”, sim; os agilistas, não. Aliás, pelo contrário, frequentemente aprendemos mais com nossos erros do que acerto. Porque muitas vezes nossos acertos são frutos de pura sorte e sequer conseguimos reproduzi-los novamente.

Dito isto, minha palestra não é sobre “dar carrinho” nos amigos que estiveram comigo nessa experiência, nem apontar culpados ou citar nomes. Não! Minha palestra é sobre apontar erros que cometemos — óbvio, querendo acertar; é sobre lições aprendidas — boas e ruins.

Essa apresentação é a visão e opinião de todos?

Não sei exatamente. Vou falar única e exclusivamente da minha visão e opinião sobre os fatos.

Que mais?

Nos vemos lá, ué! o/

Você ainda acha que programação em par é desperdício?

Como o Vinícius Teles sabiamente disse há alguns anos, “Programação em par é uma das práticas mais conhecidas e mais polêmicas utilizadas pelos que adotam o Extreme Programming. Emprestando mais algumas de suas palavras, o motivo é que:

“Ela sugere que todo e qualquer código produzido no projeto seja sempre implementado por duas pessoas juntas, diante do mesmo computador, revezando-se no teclado.

À primeira vista, a programação em par parece ser uma prática fadada ao fracasso e ao desperdício. Afinal, embora possa haver benefícios, temos a impressão de que ela irá consumir mais recursos ou irá elevar o tempo do desenvolvimento. Entretanto, não é exatamente isso o que ocorre.”

Não, não é isso mesmo!

Nossa experiência

Há quatro meses decidimos, de uma vez por todas, levarmos realmente à sério esse negócio de programação em par aqui nos times de desenvolvimento dos sistemas centrais da Locaweb. De imeditato, optamos pelo caminho mais eficaz: reduzimos pela metade o número de máquinas dos times. Sim, quase que do dia para a noite, passamos a ter apenas e  tão-somente uma máquina para cada dois desenvolvedores.

Estações de pareamento: como é que é isso?

Desde que fizemos a redução de 50% de nossas estações de trabalho, passamos a ter as chamadas estações de pareamento, máquinas destinadas exclusivamente para trabalho.

Galera de Sistemas Centrais pareando

Estações de pareamento precisam ter:

– usuário genérico para login;
– script para settar no git o dupla atual;
– configuração padrão de desktop, diretórios e ferramentas;
– apenas o instante messager de trabalho;
– apenas o cliente de e-mail de trabalho;
– acesso total à Internet;
– idealmente: 2 teclados, 2 mouses e 2 monitores (grandes!).

Mas não devem ter:

– arquivos pessoais;
– programas de distração.

Outra dupla de Sistemas Centrais

Bem, não está diretamente associado ao modelo de estações de pareamento, mas é bem importante também que as duplas tenham ao seu lado o monitor da integração contínua de seu time, para ter sempre à vista o feedback dos builds. No nosso caso, temos monitores suspensos como o que pode ser visto na foto ao lado — de preferência, sempre verdinhos!

Estação de relax: tem isso, é?

Junto com a idéia das estações de pareamento também adotamos a idéia de estação de relax. Atualmente temos apenas uma, dado o tamanho de nossa equipe.

A estação de relax é uma máquina com acesso total à Internet para a galera relaxar um pouco durante a jornada de trabalho, acessar e-mail pessoal, redes sociais, internet banking, enfim, o que quiserem e bem entenderem. Acesso total à qualquer hora do dia!

O que temos colhido com isso?

Até agora só ganhamos! Ganhamos produtividade, qualidade, propriedade coletiva de código, padronização, e por aí vai.

Desperdício isso? Não, acho com certeza não.

Um pouco de TDD com Eunit

No final do ano passado estava bem empolgado com a implementação Erlang do Restfulie e, algum tempo depois de ter começado o projeto, resolvi deixar de ser cowboy e escrever alguns testes. De lá pra cá, vez ou outra, dei uma melhorada nos testes, primeiro pra ficar mais útil, depois pra deixar mais fluente. Ainda não está lá essas coisas, mas já está, no mínimo, interessante. Se você quiser, pode conferir no meu GitHub.

Bem, no final das contas, isso acabou me motivando a escrever esse post, como um tutorial básico de TDD (talvez alguns queriam chamar de BDD, não tem problema, podem chamar como assim) com Eunit, a biblioteca de testes padrão que vem com qualquer instalação de Erlang.

A idéia desse tutorial é seguir numa linha um pouco diferente da documentação do Eunit e dos exemplos contidos no próprio projeto, escrevendo testes mais fluentes e interessantes de ler.

Mão na massa

Passo 1: criar a estrutura do projeto

O nome do nosso projeto será making_tdd_with_eunit (bem criativo!). Vamos criar então a seguinte estrutura de diretórios, que é frequentemente encontrada em projetos Erlang:

- making_tdd_with_eunit
  |
  +-- ebin
  +-- src
  +-- test

OK, apesar dos diretórios terem nomes auto explicativos, não custa nada reforçar, né?

ebin, contém os binários (.beam) resultantes da compilação dos fontes;
src, contém os fontes (.erl) dos módulos;
test, contém os fontes (.erl) dos testes.

Passo 2: escrever o primeiro teste que inevitavelmente falhará

Qual é o fluxo de trabalho com TDD mesmo, hein? Escrever o código a ser testado, rodar e, se funcionar, escrever o tal teste que passa de primeira, não é isso? Não, não é. Isso não é TDD.

Pois muito bem, vamos fazer então como realmente tem que ser feito. No diretório test, crie o seguinte teste (mobile_test.erl):

-module(mobile_test).

-include_lib("eunit/include/eunit.hrl").

describe_client_test_() ->
  {"Mobile",
    [fun should_have_a_number/0]}.

should_have_a_number() ->
  ?assertMatch({number, _}, mobile:number()).

Feito isso, compile e rode o teste com os seguintes comandos:

$ erlc -o ebin/ test/mobile_test.erl
$ erl -pa ebin/ -noshell -run mobile_test test -run init stop

Qual foi o resultado? O teste falhou, certo? Pois é, como manda o figurino!

“Escreva um teste, rode todos os testes e veja-o falhar; escreva o código mais simples possível para fazê-lo passar, mesmo que num primeiro momento não seja o mais bonito e eficiente; rode todos os testes e veja-os passar; depois, refatore para remover duplicações.” [1]

Passo 3: fazer o teste passar

Agora vamos fazer esse teste passar. No diretório src, crie o seguinte módulo:

-module(mobile).

-export([number/0]).

number() ->
  {number, "1212-1212"}.

Como fizemos anteriormente — agora acrescentando o módulo mobile à compilação —, compile e rode o teste com os seguintes comandos:

$ erlc -o ebin/ src/mobile.erl test/mobile_test.erl
$ erl -pa ebin/ -noshell -run mobile_test test -run init stop

Resultado? “Test passed.”

Passo 4: escrever mais testes

Só para não prolongar muito — este que deveria ser um pequeno tutorial — vamos para o ponto em que magicamente passamos a ter testes para as quatro funções (ultra dummies) contidas no módulo mobile, tudo bem?

-module(mobile_test).

-include_lib("eunit/include/eunit.hrl").

describe_client_test_() ->
  {"Mobile",
    [fun should_have_a_number/0,
     fun should_have_a_area_code/0,
     fun should_have_a_company/0,
     fun should_have_a_owner/0]}.

should_have_a_fixed_number() ->
  ?assertMatch({number, "1212-1212"}, mobile:number()).

should_have_a_fixed_area_code() ->
  ?assertMatch({area_code, "11"}, mobile:area_code()).

should_have_a_fixed_company() ->
  ?assertMatch({company, "DEAD"}, mobile:company()).

should_have_a_fixed_owner() ->
  ?assertMatch({owner, "Little Jose"}, mobile:owner()).
-module(mobile).

-export([number/0, area_code/0, company/0, owner/0]).

number() ->
  {number, "1212-1212"}.

area_code() ->
  {area_code, "11"}.

company() ->
  {company, "DEAD"}.

owner() ->
  {owner, "Little Jose"}.

OK, repetindo o passo anterior de compilação e execução dos testes, temos quatro testes passando, certo? Então é hora de um pouco de refatoração…

Passo 5: refatorar os testes para ficarem mais fluentes

Nesse ponto, vamos adicionar mais fluência ao nosso teste e melhorar a sua comunicação, inclusive, descrevendo um cenário “bem interessante”.

-module(mobile_test).

-include_lib("eunit/include/eunit.hrl").

describe_client_test_() ->
  {"Mobile",
    {"when is a dummy",
      [
        {"should have a fixed number",
          fun should_have_a_fixed_number/0},
        {"should have a fixed area code",
          fun should_have_a_fixed_area_code/0},
        {"should have a fixed company",
          fun should_have_a_fixed_company/0},
        {"should have a fixed owner",
          fun should_have_a_fixed_owner/0}
      ]}}.

should_have_a_fixed_number() ->
  ?assertMatch({number, "1212-1212"}, mobile:number()).

should_have_a_fixed_area_code() ->
  ?assertMatch({area_code, "11"}, mobile:area_code()).

should_have_a_fixed_company() ->
  ?assertMatch({company, "DEAD"}, mobile:company()).

should_have_a_fixed_owner() ->
  ?assertMatch({owner, "Little Jose"}, mobile:owner()).

Compilando e rodando os testes: “All 4 tests passed.”

Próximo passo: escrever mais testes e refatorar o módulo mobile

Até aqui, temos um módulo mobile totalmente dummy e um teste que usa apenas a macro ?assertMatch. Ainda há muito que pode ser feito, desde adicionar algum comportamento útil ao módulo mobile, até melhorar os testes, fazer diferentes asserções, adicionar befor_all e after_all (como nos testes do Restfulierl, por exemplo) para estado inicial e final, e por aí vai.

Bem, esse passo deixo por sua conta. É um bom exercício pra você praticar mais Erlang e Eunit.

Espero que tenha gostado e até mais!

[1] Beck, K. Test-Driven Development: By Example. Addison-Wesley Professional, 2002.

Rápidos conselhos para gerentes humanos

Gerenciar um time de desenvolvimento como um verdadeiro líder — e não um despota, ditador, que micro-gerencia cada passo — não é um tarefa fácil, acredite. Você não tem que lidar apenas e tão somente com Ruby, C#, Java, ou seja lá qual for a linguagem de programação que você use em seus projetos. Você tem que lidar na maior parte do tempo com algo muito maior e mais complexo do que isso. Você tem que lidar com “pessoas”.

Lidar com pessoas não é uma tarefa fácil. Não é mesmo!

1- Por causa das diferenças

Porque as pessoas são diferentes umas das outras; umas mais, outras menos, mas todas são.

Isso é muito bom [e dispensa dizer o porque], mas ao mesmo tempo é bem desafiador, porque você precisa aprender a maneira adequada para lidar com cada pessoa. Às vezes, o que deixa uma pessoas feliz e motiva, pode inesperadamente deixar outra completamente desmotivada.

2- Por causa das expectativas

Porque inevitavelmente as pessoas criam expectativas a seu respeito, que muitas vezes não podem ser correspondidas, seja por sua causa ou por causa do sistema no qual vocês estão inseridos. E infelizmente, a reciproca é verdadeira — afinal de contas, você também é uma pessoa —, o que quer dizer que você também corre o risco de acabar decepcionado, tanto quanto elas.

3- Por causa dos anseios

Porque as pessoas possuem seus próprios anseios, que algumas vezes são bem parecidos com os seus, mas outras tantas vezes são tão diferentes quanto o dia e a noite.

Uff! É preciso dizer mais? Acho que não…

O que fazer então?

Não. Tornar-se um ermitão não é uma opção. Esqueça isso!

1- Aceite, você não vai acertar sempre

Na verdade, algumas vezes você vai errar até mesmo quando pensa estar fazendo o maior acerto da sua vida. E a bem da verdade, talvez seja exatamente isso que torne esse trabalho tão interessante, tão humano e tão pouco tedioso.

2- Aprenda o máximo que puder com seus erros

É bem verdade que podemos aprender bastante com os erros dos outros. No entanto, algumas de nossas mais ricas experiências de aprendizado são provenientes de nossos próprios erros.

Não despreze seus erros e simplesmente passe uma borracha neles. Se você os apagar, haverá uma grande chance de cometê-los novamente.

3- Não tenha a ilusão de que sempre haverá consenso entre você e as pessoas as quais você lidera

Acho que essa é uma das coisas que mais preocupam um líder, porque a bem da verdade, todos nós — pessoas que somos — temos algum grau de dificuldade de lidar com opiniões divergentes das nossas, quer seja quando lideramos ou quando somos liderados.

A melhor coisa a fazer então é tentar compreender muito bem as opiniões das pessoas as quais você lidera e tentar chegar com elas a decisões convergentes. No entanto, quando não houver convergência de opiniões em decisões que cabe a você tomar, tome-as de acordo com o que você acredita realmente ser o melhor.

Lembre-se: você é o líder e é o responsável por suas decisões, quer partam de você ou não.

Se você é humano, gerente…

Deveria considerar esses rápidos conselhos. IMHO.

Duas propostas para o Agile Brazil 2010

Submeti hoje duas propostas de palestras para o Agile Brazil 2010, um evento bem bacana que acontece em Porto Alegre em junho. Esse ano o evento conta também com a presença de Martin Fowler, da ThoughtWorks.

Segue abaixo o resumo das minhas submissões e, se você quiser, além de poder deixar comentários aqui, também pode fazer isso no próprio site de submissões do evento.

Espero te ver lá! 🙂

Como vi Scrum ser completamente rechaçado em uma grande empresa

Ouvimos por aí muitos relatos de sucesso de implementação de métodos ágeis em empresas grandes. Nós mesmos temos alguns. Mas onde estão os relatos de derrotas?

Nesta palestra vou contar uma história real em que vi Scrum ser completamente rechaçado em uma grande empresa que trabalhei.

Essa não é uma palestra sobre apontar culpados, mas sobre identificar falhas que comprometeram completamente a adoção de métodos ágeis nesta empresa.

Princípios de Agile Coaching

O que faz um coach ágil? Quais são suas ferramentas? Em que se baseia seu trabalho?

Essa palestra é sobre alguns princípios do coach ágil e como ser eficaz nessa missão. Vou abordar temas como:

– educação
– facilitação
– feedback
– percepção
– apoio

Além de falar sobre as atitudes esperadas de um coach:

– liderança por exemplos
– equilibrio emocional
– respeito ao ritmo do time
– linguagem que vence barreiras
– deixar o time aprender com seus erros

Tchau, tchau gerente, agora sou Scrum!

Já que Scrum define apenas três papéis: Scrum Master, Product Owner e Time, onde é que fica o papel do Gerente de Desenvolvimento? Será que é hora de dizer adeus?

Contextualizando

Há pouco tempo assumi uma posição na Locaweb como gerente da equipe de desenvolvimento responsável pelos sistemas centrais da empresa. É uma equipe relativamente grande, dividida em três times de multi-talentosos desenvolvedores, um para cada domínio de negócio que lidamos: Provisionamento, Cobrança e Atendimento; além de dois sysadmins que dão suporte a estes times em tempo integral.

Os times atualmente estão organizados como times de Scrum tipicos, com os tais multi-talentosos desenvolvedores, um Scrum Master e um Product Owner — que no nosso caso, é um gerente de produtos que trabalhar fortemente conosco, extremamente comprometido com os interesses de negócio da empresa.

Desde então, comecei a buscar me interar um pouco mais sobre assuntos de gerenciamento e liderança ao melhor espírito ágil, com a preocupação de não me tornar aquele tipo de gerente que simplesmente “delarga” e vive alienado; ou pior ainda, aquele que comanda e controla o tempo todo, e queno final das contas, mais caroça e atrapalha do que ajuda.

Novo release: Gerente 2.0

Bem, além de conversar com vários amigos — muito mais experiêntes do que eu nesse papel —, também naveguei bastante pela Web e acabei chegando num artigo muito interessante de Pete Deemer, da Scrum Training Institute, que tem me ajudado bastante. Se você também tem interesse no assunto, acho que vale a pena ler.

Pete sugere no artigo, de maneira bem coerente, 14 atividades de um gerente de desenvolvimento. Vamos dar uma olhada no resumão delas:

1- Ajuda a remover impedimentos que o time não tem condições de resolver por si só

Enquanto o Scrum Master remove impedimentos hora-a-hora, dia-a-dia, coisas referentes ao projeto, o gerente precisará focar seus esforços em resolver impedimentos mais sistemátivos, mais corporativo, digamos assim.

Estes impedimentos, frequentemente, são os mais desagradáveis; e que requerem alguma influência, alguma autoridade, para lidar com eles de maneira efetiva.

2- Dá ao time conselhos e sugestões sobre dificuldades técnicas que aparecem

Gerentes deveriam estar disponíveis para dar conselhos e assitência técnica ao time sempre que solicitado.

Nota minha: é que claro que, volta e meia, o gerente vai precisar ir a reuniões estratégicas, corporativas — ou seja lá como chamemos em nossa empresa —, e não poderá atender às solicitações do time de imediato. É preciso tratar isso de maneira bem madura com o time, colocando na mesa as limitações impostas por suas outras atividades e buscando uma maneira de mitigar isso, para que nem o time fique na mão quando precisar, nem o gerente seja crucificado quando não estiver à pronta disposição.

3- Regularmente conversa com os membros do time, um por um, para dar coaching e mentoring

Gerentes deveriam gastar tempo com os membros do time, individualmente, com certa frequência (que cada um deve achar a melhor para si), para dar coaching e mentoring. Veja: não é para pedir status report; é para ensinar, ajudar, guiar, etc, menos cobrar.

Alguns gerentes gostam de fazer isso pareando e escrevendo código junto.

4- Dá sugestões sobre como fazer features melhores

Estas sugestões são endereçadas diretamente ao Product Owner, geralmente, durante a Sprint Review.

Nota minha: o ideal é que isso aconteça sempre, mantendo o máximo de proximidade possível com o Product Owner. No meu caso, por exemplo, sento de frente para o gerente de produtos de sistemas centrais e bato-papo com ele o tempo todo. Ou seja, se tenho algo a sugerir, não preciso esperar a cerimonia de revisão.

5- Mantem-se pari passu do desenvolvimento de ferramentas, tecnologias e técnicas que o time está usando

Esta é uma atividade muito importante e frequentente negligenciada pelos gerentes. Gerentes não podem ficar congelados no tempo. Mesmo porque, a atividade 2 é sobre estar apto a dar conselhos técnicos ao time.

Nota minha: não tem coisa mais irritante do que um gerente que não entende nada do trabalho que você está fazendo, dando palpites furados, e ainda querendo que você explique para ele algo que ele não tem um mínimo de base técnica e conceitual para entender.

6- Planeja treinamento e outros skills de desenvolvimento para os membros do time

Gerentes deveriam pensar cuidadosamente sobre onde o time poderia usar seu skill; e também, cláro, que capacidades o time precisará ter quando for desenvolver determinados itens do Product Backlog.

7- Mantem-se atualizado sobre as novidades e evoluções da indústria

Novamente, uma atividade importante, mas frequentemente neglienciada. Sem ela, a atividade 2 fica fortemente comprometida.

8- Antecipa ferramentas, skills e futuras necessidades

Outra atividade importante, que tem tudo a ver com a atividade 6, e que é frequentemente negligenciada. Converse com seu time a respeito, peça sugestões.

9- Planeja e gerencia orçamento e caixa

Outra vez, algo muito importante, mas muito negligenciado por diversos gerentes.

Nota minha: qual foi a última vez que você colocou no seu orçamento um din-din para cursos, eventos, livros, e outras coisas que melhoram o skill do seu time? Ou você é do tipo que não se preocupa com isso e que, pior ainda, até acha ruim que seu time vá a eventos, faça cursos ou leia livros no horário de trabalho?

10- Dá sugestões de que features o time deveria construir

Vale o mesmo comentário do item 4, não vale? Acho que sim, tem tudo a ver.

11- Faz avalição de performance e dá feedback aos membros do time

Isso é algo necessário em muitas empresas, apesar de bastante subjetivo. Mas o ponto aqui é que gerentes deveriam basear suas avaliações em suas próprias observações, bem como no feedback de outros membros de time.

12- Faz planejamento e desenvolvimento de carreira com os membros do time

Oportunidade de carreira é uma das mais significantes formas de compensar pessoas por seu trabalho. Além de din-din, é lógico!

13- Recruta, entrevista e contrata novos membros para o time

Uma das melhores (mas às vezes, aterrorizantes!) ações de gerenciamento é tomar decisões de contratação. Isso porque boas contratações dão lucro desde o primeiro dia, enquanto que más contratações são uma “taxa” invisivel na habilidade do time entregar valor de negócio.

14- Remove membros que não são capazes de fazer um bom trabalho no time

Se mesmo depois de extenso coaching um membro do time não é capaz de contribuir, de trabalhar harmoniosamente com os outros membros do time, ou de fazer seu trabalho na qualidade esperada, ele precisa ser removido do time, ou mesmo da empresa, rapidamente. Tipicamente, gerentes precisam guiar esse processo de maneira coordenada com o RH da empresa.

Nota minha: não deixe a moral do seu time e o dinheiro da sua empresa ir para o ralo. Cuidado! Há uma linha muito tênue entre “vou dar mais uma chance” e a omissão. Não tenha medo de fazer uma demissão, mesmo que tenha sido você que fez a má contratação. Contratações são quase que como loterias! Na verdade, quem fez a má contratação é o que menos importa; o que realmente importa é a performance e moral do time, que no final das contas, se traduz em mais dinheiro para a empresa.

Conclusão

O papel do gerente de desenvolvimento 2.0, como diz esse artigo de Pete Deemer, traz um mix de habilidades de liderança técnica e de gerenciamento de pessoas — pelo amor de Deus, não chame as pessoas de recursos!

A mim faz todo sentido; e está bem alinhado com as atribuições que recebi, quando contratado pela Locaweb. Aliás, acho que vale citar que, uma das coisas que Pete diz no artigo é que esse “novo” papel do gerente de desenvolviemnto precisa ter uma bênção formal do diretor de direitor TI, ou alguém com poderes equivalentes.

Mas e você, o que acha? Deixe um comentário…

Geração e build de projetos Erlang/OTP

OK. Hora do jabá…

Há alguns meses, quando comecei a mexer mais com Erlang/OTP, senti a necessidade de ter uma ferramenta que gerasse a estrutura dos projetos, bem como stubs dos módulos necessários. Não encontrei nenhuma que fosse realmente simples. O que fiz? Cocei minha própria coceira, crie o projeto otp_kickoff.

Agora, de saco cheio desconfortável de usar Make para automatizar tarefas de build, resolvi coçar minha própria coceira novamente, crie o projeto ebuilder.

Se você também está mexendo com Erlang/OTP, sugiro que dê uma olhada nestes projetos, quem sabe eles também não facilitam sua vida, ahmmm?