Desenvolvimento

7 abr, 2015

Código perfeito existe sim! E tartarugas não sobem em árvores

Publicidade

Ontem eu li um artigo do Jim Bird que dizia aos programadores para não procurarem o código perfeito, por que ele não existia. Sinceramente, eu discordo. É claro que existe! Código perfeito existe sim, o problema é a definição de perfeição.

Perfeição em código não é a mesma coisa que a perfeição de uma peça usinada com espaço para erro de meio mícron. Perfeição em software é uma medida de dureza. Eu explico… Um software ruim todo mundo consegue definir. Colecionar adjetivos para classificar o ruim é fácil, por que as pessoas tendem a cooperar nesse tipo de atividade e basta que uma pessoa bem qualificada diga que o código é ruim para muita gente surgir com o mesmo conceito, mais ou menos como aquele efeito que o scrum poker tenta controlar.

Vende cerveja quente X tem cerveja muito gelada 90% do tempo?

Dizer que um software é ruim é fácil do ponto de vista da argumentação, parecemos ser equipados para ver o ruim. Coloque 10 cervejas geladas na mesa do bar e se uma delas não estiver muito gelada o bar vai ser aquele que vende cerveja quente e não aquele que tem cerveja muito gelada 90% do tempo. As pessoas se apoiam quando falam mal porque na maior parte do tempo você não precisa falar, basta soltar uma interjeição aqui e ali, um “vixiii”, um “putz” e vários “nooossaaa”.

Na maioria das vezes não é necessário argumentar sobre o porque de um software ser ruim. Isso diz muito dos profissionais que dizem “precisa reescrever tudo”.

E como dizer que um software é bom? Que características definem a perfeição de um software? Escolhi duas e você escolhe se é uma escolha subjetiva ou não.

Entrega o valor

A primeira coisa da qual um software perfeito não abre mão é realizar com sucesso a tarefa a que se propõe. Veja, o código não é perfeito, mas o software executa a tarefa e faz isso no tempo necessário, com os recursos disponíveis e de maneira estável. Logo, perfeito!

Maleável

Vou falar primeiro de rigidez, aquele software que não consegue responder a uma mudança requisitada, que exige do programador que ele lute contra seu código ao invés de construir com seu código.

Se um código é maleável, então é capaz de aderir as mudanças dentro de um tempo aceitável (racionalmente aceitável, sem subjetividade) de trabalho. A arquitetura e o código colaboram para isso e o programador encontra ferramentas para desenvolver a nova funcionalidade.

Ao invés de batalhas a cada passo do caminho, o código maleável oferece uma estalagem com cerveja amanteigada e uma erva especial do condado.

Pronto, entregar o valor e ser maleável são o suficiente para criar o cenário da perfeição. Você pode parar de ler aqui se quiser, ou pode praticar comigo o esquecido ritual da reflexão sobre as consequências de uma declaração.

Exemplo, um script de processamento de um csv entrega o valor de processar um csv e gravar no sgdb? Sim? Ele é perfeito? Sim! Mas ele não é orientado a objeto! Bem, não importa!

Pediram para esse mesmo script começar a processar arquivos csv de um formato diferente e o programador adicionou condições no código. O script continua rodando estável? Sim. O script processa os dois formatos? Sim. O script é perfeito? Sim.

Pediram para o script começar a processar mais três formatos diferentes. O programador adicionou condições no código para fazer a entrega, mas pediu um mês para isso (cada um dos formatos anteriores levou quatro horas). Esse tempo é aceitável? Não. O script continua estável? Não. O script é perfeito? Não. Ahhhh, mas por queee?! Por que ele não entrega o valor prometido e não tem um tempo de desenvolvimento aceitável para novas features.

É muito provável que o tempo de um mês seja necessário por que a essa altura já não dê para ler o código e tampouco adicionar uma condição sem quebrar outra.

O que aconteceu para transformar a perfeição em desastre em tão pouco tempo?

Partindo do início, o trabalho de um analista/programador é identificar padrões e nesse caso ele não identificou o padrão de que novos formatos de arquivo continuariam chegando. Ele não conversou com o cliente e por não ter identificado o padrão, ele não se preparou e não tomou uma decisão para controlar a complexidade crescente da tarefa, de maneira que a complexidade engoliu o tempo e o dinheiro dos envolvidos.

Proposta? Sim. Preste atenção na complexidade de uma tarefa e no ritmo com que essa complexidade cresce. Quanto maior o ritmo, mais rápido você precisa reagir coletando dados para poder direcionar seus esforços. E quando digo coletar dados, eu quero dizer tirar a bunda da cadeira, vestir a camiseta mais gasta do Ramones, pegar um copo de café e ir falar com as pessoas do escritório interessadas no produto ou código cuja complexidade você notou que está saindo do controle.

Voltando à questão da perfeição em software, e se o programador tivesse notado o padrão de novos formatos no script de processamento do csv e reagisse? Ao notar o padrão de novos arquivos, o programador ia se preparar, fornecendo um código para lidar com a seleção de formato e separar os processos de leitura de cada um deles. Ele começaria a fazer isso de uma maneira simples, extraindo funções, organizando uma estratégia, separando conceitos e administrando um débito técnico aceitável, que ele decidiu implementar somente se realmente novos formatos surgissem.

Isso manteria o código capaz de responder a mudanças num tempo aceitável e manteria a estabilidade do software.

Software perfeito mesmo com débito técnico? Sim! Ahhhh, mas por que?! Débito técnico não é uma característica ruim, desde que você tenha colocado ele lá de uma maneira consciente por que definiu postergar uma característica do algoritmo para quando ela fosse realmente necessária.

Débito técnico ruim é mais como tartarugas em cima de árvores. Todo mundo sabe que tartaruga não sobe em árvore e ninguém sabe como elas foram parar lá. Isso é problema.

Da próxima vez que você ouvir alguém falando de código perfeito, lembre-se dessas características: entrega de valor e maleabilidade. E pense nas consequências da aplicação desses dois únicos conceitos.