Olist: aprendizado técnico

[Público alvo: desenvolvedores e pessoal “relacionado”.]

Conforme mencionei previamente aqui, eu já tinha experiência trabalhando com Python antes de entrar na Olist, mas essa experiência era muito “frouxa”, ou seja: não havia, realmente, nenhum tipo de cobrança de cunho mais técnico. Cobrava-se apenas que os “produtos” fossem entregues. E, embora eu mesmo procurasse fazer sempre o melhor, é um fato da vida: nós somos extremamente complacentes conosco — e muito pouco com os outros. Por isso é muito comum um desenvolvedor olhar o próprio código e dizer “ah, assim já tá bom”, enquanto outro diria “tem muito a melhorar”. No meu caso, passei algum tempo sem ter alguém para dizer o “tem que melhorar”.

A verdade é que a realidade no meu emprego anterior era muito… peculiar. E diferente do que seria uma equipe “grande” (12 pessoas conta como “grande”?) e bem organizada de desenvolvedores realmente bons.

Code review

Mesmo que dificilmente os ânimos se exaltassem, a revisão de código na Olist é “violenta”. E isso é algo muito bom. Não que haja grosseria, mas o nível de complacência é bem próximo de zero. Implementou nova funcionalidade sem fazer os testes, por exemplo? Você será cobrado. E muito:

Mais de uma vez eu fui barrado em tentativas de “vou fazer meio errado agora, mas só pra já subir uma versão que funcione. Depois eu corrijo”. E mais de uma vez eu barrei tentativas assim. Na equipe de desenvolvimento da Olist, code review é um assunto sério.

Eu não estava acostumado a isso e admito que sofri um pouco no começo. O pessoal realmente “pegava no meu pé” por coisas que, na época, eu achava que estavam perfeitamente “okay”. Mas não estavam. E eu fico feliz com isso, porque é esse tipo de “sofrimento” que nos faz melhores profissionais. Na verdade, crescimento desse tipo eu “sofri”, antes, quase que só na Agência WX — outro lugar onde posso dizer que cresci muito profissionalmente.

“Dois joinhas”

Havia uma regra simples para o merge: só entra no “galho-mestre” (o branch master) código que recebeu aprovação de dois outros desenvolvedores. Ou seja: se você revisou e está okay, dá um “joinha” (“:+1:”). Se o pull request já tem um “joinha” e está okay, você já pode mergear.

Conversa

Code review não é apenas avaliação de código para ver se tudo está correto. Cada desenvolvedor é encorajado a tirar dúvidas a respeito do que e por que foi feito e conversar sobre alternativas. A ideia é que seja também uma oportunidade de aprendizado para todos os envolvidos. Se alguém não entendeu alguma coisa, deve perguntar.

Prioridade

Code review é prioridade e não fica relegado ao “quando eu tiver tempo”. Faz-se tempo para code review. Isso por um motivo simples: se os pull requests “andarem” rápido, o teu pull request não ficará esperando dias para ser mergeado. Todos ganham com isso.

Se, por exemplo, um desenvolvedor disser, durante a daily (reunião diária da equipe) que “passei a manhã toda fazendo code review” isso é absolutamente okay. Code review é parte, sim, do “processo produtivo”.

Github

A Olist já usava o Github desde a época em que eles cobravam por repositório. Por causa disso (já que cada API e cada serviço tem seu próprio repositório, porque é assim que deve ser), quase, quase fomos para o Bitbucket. Menos mal que o modelo de cobrança mudou justo a tempo de permanecermos no Github.

Nada contra o Bitbucket. Ele funciona. Mas o Github ainda oferece uma experiência melhor (na minha opinião e na opinião da equipe toda, na época)...

Python 3

Foi a primeira vez que lidei com Python 3 “de verdade”. E foi muito bom. Teria sido uma decisão trágica (e muito errada) ter permanecido com Python 2.

Mock

from unittest.mock import Mock

Ah, essa linha…

Eu nunca havia usado Mock, antes e, no começo, eu achava uma ferramenta meio esquisita. Não aceitava muito bem. Depois descobri que Mock é uma ferramenta fantástica.

E, depois de usar bastante, descobri que é, na verdade, uma ferramenta horrível.

Mock é horrível porque facilmente esconde erros. Eu lembro até hoje da minha surpresa ao descobrir que um conjunto inteiro de testes escritos por um dos membros mais respeitados e experientes (e que manjava bem de Mock) da equipe estava simplesmente errado do começo ao fim. Por quê? Porque faltou usar o return_value do objeto mockado. E eu acabei descobrindo isso meio que por acaso…

Alguém pode argumentar que “você não pode culpar a ferramenta pelo mau uso de terceiros”, mas entenda: se um desenvolvedor experiente comete esse tipo de erro, não é razoável dizer que é realmente muito fácil ser enganado pelo Mock?

Um dia eu ainda vou escrever um artigo completo a respeito de como eu acredito que é o uso correto do Mock. Mas, por ora, eu simplesmente recomendo não usá-lo.

py.test

Bem no comecinho chegamos a usar os testes do próprio Django, que são baseados no unittest do Python. Mas depois, como nem todo projeto era Django e quisemos padronizar tudo, acabamos indo para o “py.test”.

py.test é uma ferramenta muito boa, que atende bem tanto cenários bem simples quanto cenários bem complexos. No começo eu achei complicado de usar, mas, vencida a barreira do primeiro aprendizado, eu realmente gostei de ter sido apresentado a ela.

factory-boy

Excelente para criar “fábricas de objetos”. Suporta bem o Django, é simples de usar e a documentação é boa. Facilitou muito nossa vida.

VCR

O VCR é um “gravador de interações HTTP” e serve bem para testes que envolvam integração com APIs externas, por exemplo.

O VCR é um assunto polêmico. Alguns defendiam que praticamente não deveria ser usado, por exemplo. Da minha parte, me parece meramente outra fixture de testes, exceto que deveria manter-se sincronizada com o contrato estabelecido com a API externa — e essa é uma parte um tanto complicada.

O VCR foi muito útil, sim, mas nunca foi algo que os desenvolvedores viram com 100% de alegria. Taí outro exemplo de algo que merece um artigo a respeito…

Django Rest Framework

Se arrependimento matasse, a equipe toda já estaria se estrebuchando pelo chão…

O “DRF” é um projeto muito grande e que tem uma base de usuários também grande. Ele facilita muito sua vida caso você queira criar APIs REST sobre sua aplicação Django — contanto que você siga a “receitinha” do DRF. No momento que você resolver colocar a pontinha do pé para fora, ele começará a espernear, gritar e contorcer-se como uma criança mimada e você, depois de muita luta e insistência, acabará desistindo. Sério. Aconteceu comigo.

O código do DRF é feio, repleto de práticas ruins (como a loucura que são os “mixins” do projeto) e extremamente dependente de “bom comportamento” por parte do desenvolvedor que o usa.

No começo tudo parece lindo, mas depois da terceira API você começa a se questionar por que diabos é preciso escrever tanto código absolutamente igual, só mudando os nomes dos endpoints e dos modelos, se poderia simplesmente dizer o nome do endpoint e do modelo e ser feliz. E então você tenta eliminar a repetição e descobre que não, você não conseguirá vencer a batalha contra o DRF.

Okay, ele funciona, é bem testado, é um projeto bem ativo e é seguro. Não é um desastre usá-lo em um projeto. Mas, ainda assim, não recomendo você “casar” com essa ferramenta.

Idiomas do Python

Eu sou muito mais inclinado a criar generators e fazer comprehensions sempre que possível do que o Osvaldo (CTO da Olist), por exemplo. Então, embora Python pregue o “one way” de fazer as coisas, sempre há mais de uma maneira de se escrever código. O que prevaleceu foi evitar-se o estilo “muito funcional” (como o meu) e preferir-se geralmente abordagens mais “flat”. E isso, no fim das contas, é okay, pois “flat is better than nested”, anyway, e “readability counts”.

Scrum ou kanbam? Ambos!

Segurem-se nas suas cadeiras, adoradores do Scrum! Na Olist adotamos um misto entre kanbam e Scrum que deu muito certo. Nós não tínhamos “sprints”, necessariamente, pois percebemos que terminar as sprints sem entregar alguma história — algo natural, pois havia histórias que eram demoradas, mesmo — trazia uma sensação de derrota completamente desnecessária e gratuita. No entanto, mantivemos uma certa divisão das semanas, as pontuações nas histórias, as reuniões de planning, grooming, retrospectiva e a daily.

A pontuação de histórias serve para um objetivo: garantir que todos os envolvidos entenderam a história em questão. Se uma pessoa dá 2 pontos para uma história enquanto outro dá 8, é sinal que a descrição e as subtarefas não ficaram claras e precisam melhorar. Fora isso, não dávamos nenhum outro uso para a pontuação. Não calculávamos velocidade (e nem precisava, pois ela era “máxima” o tempo todo, e a empresa toda reconhecia isso), não comparávamos velocidades entre os membros da equipe, não mostrávamos números nem para o CEO da empresa. Nada.

É sempre bom tomar muito cuidado com números. Certas empresas usam os números meramente para dar a sensação ao “gerente” de que ele é útil para alguma coisa, ou para apaziguar o presidente/diretor/focal/whatever que não entende nada de tecnologia. Se você tem uma equipe comprometida e competente e um CTO que saiba o que faz e para onde leva a equipe, os números serão a última coisa com o que você precisará se preocupar.

AWS

Desde o começo foi decidido: não deveríamos “amarrar” a plataforma da Olist a nenhum “fornecedor externo”. Exceto a Amazon, porque, para nós, isso era vantagem. E foi. Essa decisão estratégica que tem se provado boa e correcta.

Além do que, a arquitetura foi projetada de tal forma que, se fosse necessário migrar de plataforma, não seria algo de se arrancar os cabelos, não…

Heroku

Ah, o Heroku... Se fosse possível, eu daria um abraço nessa plataforma incrível!

Os deploys na Olist resumiam-se, geralmente, a:

time git push heroku master

Simples assim. Fora a facilidade de se configurar bancos de dados, data-links, Redis, variáveis de ambiente, número de “dynos”, etc.

Resumo

Trabalhar com uma equipe grande e cheia de gente melhor do que eu garantiu um aprendizado bem grande durante o ano de 2016. Trabalhar sem muita cobrança é bom para o “lado preguiçoso”, mas ter que superar-se a cada dia e se obrigar a aprender mais sempre é muito melhor!