Conte as decisões

Prévia grátis 5 min de leitura

O refinamento é mais fácil de entender de trás para frente: olhe código pronto e conte as decisões que precisaram ser tomadas antes de ele poder existir.

O item

Imagine a linha que iniciou esta funcionalidade:

"Quando alguém do admin adiciona um parceiro, busque o logo dele no site automaticamente."

Uma frase. Razoável. É a cara de um item comum de backlog, e todo mundo na sala concordaria com ela.

O código

O app/services/partners/fetch_site_icon_service.rb, 86 linhas. Aqui está o que há nele:

MAX_BYTES = 1.megabyte
TIMEOUT = 5
ACCEPTED = %w[image/png image/jpeg image/webp image/svg+xml
              image/x-icon image/vnd.microsoft.icon image/gif].freeze
# Preference: apple-touch-icon (largest) > <link rel="icon"> (largest) > /favicon.ico
def fetch(url, limit = 3)
  return nil if limit.zero?
rescue URI::InvalidURIError, SocketError, Timeout::Error,
       OpenSSL::SSL::SSLError, Errno::ECONNREFUSED => e
  Result.new(success: false, url: nil, errors: [ e.message ])

As decisões

Lendo esses quatro fragmentos, pelo menos onze perguntas separadas foram respondidas:

# Decisão Valor no código
1 Que tamanho de arquivo aceitamos? 1 megabyte
2 Quanto esperamos? 5 segundos, abertura e leitura
3 Quais formatos de imagem? Sete, listados explicitamente
4 Qual ícone preferimos? apple-touch-icon, o maior primeiro
5 E se houver vários do mesmo tamanho? Não foi decidido: o sort_by não é estável, então um empate pode sair em qualquer ordem
6 E se a página não declara nenhum? Cai no /favicon.ico
7 Seguimos redirecionamentos? Sim, no máximo dois (três requisições no total)
8 O que acontece se o site está fora? Devolve um Result de falha, não levanta erro
9 Quais falhas capturamos? Cinco classes de exceção, nomeadas
10 Uma falha impede adicionar o parceiro? Não: o admin ainda consegue salvar
11 Nós nos identificamos? Um User-Agent nomeando a aplicação

Onze decisões, e o item não continha nenhuma delas.

flowchart TB
  T["'busque o logo automaticamente'"] --> D["11 decisões"]
  D --> G["decididas numa sessão de refinamento, juntos, em 30 minutos"]
  D --> A["decididas sozinho no teclado, em 11 interrupções"]
  D --> P["decididas pela produção, em 11 incidentes"]
  G --> R["as mesmas onze respostas, a preços diferentes"]

Os três lugares em que uma decisão é tomada

Numa sessão de refinamento. Juntos, antes de o trabalho começar. Todo mundo ouve a resposta, o raciocínio fica registrado, e discordar é barato porque nada foi construído.

Sozinho no teclado. Quem desenvolve esbarra em cada pergunta no meio do fluxo e escolhe algo razoável. Isso não é um fracasso: a maioria dessas onze são decisões perfeitamente boas e quem desenvolveu era a pessoa certa para tomá-las. O custo é que ninguém mais conhece as respostas, então o raciocínio mora numa cabeça e no git blame.

Em produção. O site de um parceiro serve um TIFF de 40MB e a requisição trava. Agora as decisões 1, 2 e 3 são tomadas, caro, por quem estiver acordado.

As mesmas onze respostas, a três preços bem diferentes. Refinamento é escolher a primeira coluna, e não uma cerimônia, para as decisões que são caras na terceira.

Quais das onze pertenciam à sessão

Não todas, e essa é a parte que separa refinamento útil de uma reunião.

A decisão 10: uma busca falha impede salvar o parceiro?: é uma decisão de produto. Ninguém além de quem é dono da funcionalidade pode respondê-la, e errar significa reconstruir o controller.

A decisão 8: devolver um Result ou levantar erro?: é uma convenção arquitetural que esta base já tem, então não precisa de discussão nenhuma.

A decisão 3: quais formatos de imagem?: é uma boa coisa de deixar para quem desenvolve. É barata de mudar, invisível ao produto, e consultar o que os navegadores aceitam é um trabalho de cinco minutos que uma reunião só piora.

Um primeiro corte da regra, refinado ao longo deste curso: refine as decisões caras de reverter ou que alguém fora do código precisa responder. Deixe o resto para quem faz o trabalho.

Uma sessão que decide todas as onze desperdiça uma hora. Uma sessão que não decide nenhuma deixa as caras para a produção.

Pontos-chave

  • Um item de uma frase produziu 86 linhas contendo pelo menos onze decisões separadas.
  • As mesmas decisões são tomadas no refinamento, no teclado, ou em produção: as respostas podem coincidir, os preços não.
  • Decidido no teclado, o raciocínio mora numa cabeça e no git blame.
  • Refine o que é caro de reverter ou o que alguém fora do código precisa responder.
  • Decidir todas as onze numa reunião desperdiça uma hora; não decidir nenhuma deixa as caras para a produção.
Aula 1 de 7 · grátis

Continue com a aula 2

O que refinamento é e não é

Separa o refinamento de outras quatro reuniões e define suas três saídas, participantes, tempo e entradas.

Com uma conta grátis você também tem os quizzes, seu progresso e suas anotações, e a discussão.

Digite para buscar...