Pressione enter para ver os resultados ou esc para cancelar.

Programação eficaz

Mais de 10 anos se passaram desde que escrevi minhas primeiras linhas de código, e naquela época havia menos da metade dos recursos (hardware) que existem hoje.

Em outras palavras, hoje temos à disposição “mais de tudo”, memória RAM, espaço em disco SSD, processadores com mais de um core e isso se tornou muito comum. Basta um celular para realizar tarefas como rolar a linha do tempo do Facebook, ver fotos, videos, WhatsApp (ou Telegram) e buscas no Google e Gmail.

Dá só uma olhada nas especificações do hardware do meu celular:

Processador Quad Core de 2.5 GHz.

GPU Adreno 330, que chega a 26 frames por segundo.

Memória de 32 GB e 2 GB de RAM.

Alta Resolução de 1080 x 1920 pixels.

Velocidade de download de 150 Mbps.

Sério, acredite! É muito comparado ao que havia há 15 anos, quando eu sonhava com um desktop (PC) que tivesse um processador com mais de 300 Mhz e 1GB de memória RAM.

Você sabia que os recursos da computação aumentaram cerca de 10.000 vezes desde os primeiros computadores modernos, por volta de 1936?

 

IBM 305 RAMAC – 1956
O IBM 305 RAMAC de 1956 foi considerado um SUPER computador com 5 Megabytes de disco rígido (HDD). – Fonte: theatlantic.com

 

Eu fico imaginando, se tivéssemos uma máquina do tempo e voltássemos na época em que um processador de 100 Mhz e 512 Kb de RAM era um sonho e perguntássemos para um programador: como você imagina a programação num futuro onde os computadores são carregados no bolso com 10.000 vezes mais recursos? Bom, eu aposto que seria uma resposta descrevendo um futuro diferente do que eu vejo hoje no que diz respeito à qualidade e eficiência dos softwares que usamos e desenvolvemos.

Encaremos os fatos, já aconteceu com você, você baixa um software e para a sua surpresa não funciona como você esperava, mas mesmo assim você começa a usar e então explode um bug na sua cara. Aí você conversa com um amigo que te responde com a famosa:

Na minha máquina funciona

 

Mais tarde, você faz uma busca no Google (porque você tá ligads) e encontra alguém com exatamente o mesmo problema, e você se tranquiliza porque há uma solução. É o seu dia de sorte! Sqn…

Não funcionou

 

Provavelmente você vai continuar a tentar soluções aleatórias até que algo aconteça e o software comece a funcionar.

Por que isso acontece? Bom, talvez ninguém nunca saberá, mas provavelmente é por causa de um mau manuseio / controle do estado da aplicação.

Já aconteceu comigo, escutei essas histórias mais do que você imagina, e não apenas de usuários, isso acontece com desenvolvedores de software também.

Na minha opinião, a maioria dos softwares de hoje são complexos e caros demais, a experiência do desenvolvedor é um saco, a arquitetura é imensa e frágil, e qualquer pequena mudança no código é o bastante para tudo desmoronar.

Então eu penso… por que continuamos a desenvolver software que induzem ao erro (bugs), que são mais complexos e mais caros de manter tendo 10 mil vezes mais recursos que há poucos anos? O que estamos fazendo de errado?

Estamos acostumados com software quebrado, nos tornamos mais eficientes em tornar a programação mais complexa.

Se você concorda comigo, não está sozinho. Existem pessoas incomodadas assim como você, como Robert C. Maring (Uncle Bob) que quer fazer algo a respeito disso, porque nesse ritmo, vamos ter mais pessoas resolvendo ou criando bugs do que de fato desenvolvendo software que funciona.

 

Programação eficiente não é o caminho para o verdadeiro software de qualidade, programação eficaz é o que precisamos – Sebastian Ferrari (eu).

 

Pense a eficiência como conhecimento e eficácia como sabedoria. Eu recomendo que você tire alguns minutos e assista a esta palestra de Russell L. Ackoff sobre a importância dos sistemas e a verdadeira qualidade. Eu adoraria escrever mais sobre o porquê a chave para um bom sistema é quão bem as peças se encaixam, mas este post já está ficando grande.

 

Código com cheiro ruim

Como desenvolvedores de software nós podemos identificar rapidamente o software ruim quando o código é muito difícil de ler e de entender o que o código faz ou o que está acontecendo quando um bug aparece (debugging). Você vai gastar mais tempo lendo do que realmente escrevendo código.

Joe Armstrong é um dos desenvolvedores da linguagem de programação Erlang criada na Ericsson, e também criou os “sete pecados capitais” para uma excelente palestra na StrangeLoop (que me deu a inspiração para escrever este post) e que pode te ajudar a identificar código com mau cheiro:

  1. Código que você não entende uma semana depois que você o escreveu – sem comentários no código.
  2. Código sem especificações.
  3. Código que é entregue (deploy) assim que é executado e antes de ser bonito.
  4. Código com funcionalidades adicionais.
  5. Código que é muito muito rápido muito muito obscuro e incorreto.
  6. Código que não é bonito.
  7. Código que você escreveu sem entender o problema.

Se alguns alertas de discordância estiverem soando na sua cabeça, tem uma ótima discussão sobre “pecados” no Reddit que vale a pena dar uma lida antes de concluir seu pensamento polêmico 😉

 

O seu código tem um ou dois destes problemas?

  1. Efeitos colaterais: resultados imprevisíveis.
  2. Mudanças no estado da aplicação conforme o tempo com assignment statements fora do controle.
  3. Objetos de estado completo.
  4. Vazamento de memória.
  5. Coupling: interdependência entre módulos de software.
  6. Falta de capacidade para criar testes unitários: métodos ou funções fazem mais de uma coisa.
  7. Encapsulamento exagerado.

Antes de entrar em mais detalhes técnicos, vamos falar sobre qualidade.

 

Qualidade

Eu me considero um otimista, então eu acredito num feliz balanço entre tempo de entrega e qualidade de software, o que pode ser conquistado com uma mentalidade enxuta (Lean) e boas técnicas de programação que te incentivam a construir um bom software de fácil manutenção que os usuários vão amar. Aqui está um dos meus princípios favoritos:

Qualidade na construção
Encontre e corrija defeitos no momento em que eles ocorrem.

Processo à prova de erro

Pense em testes como especificações. Use-os para estabelecer confiança na correção do sistema a qualquer momento durante o desenvolvimento, em todos os níveis do sistema.


Integre Cedo e Frequentemente

Cada processo de desenvolvimento já inventado teve como objetivo principal encontrar e corrigir defeitos o mais cedo possível no processo de desenvolvimento.


Não Tolere Defeitos

Se você espera encontrar defeitos durante uma revisão final, seu processo de desenvolvimento é defeituoso.

Voltando ao que estávamos discutindo no começo, lembra do programador do passado sonhando sobre como seria brilhante o futuro da computação? Bom, como Joe Armstrong disse, algo deu errado, porque eu não sinto que nós estamos indo pelo caminho certo. Talvez nós devêssemos aprender algo com o passado para podermos voltar aos trilhos.

Algo como Programação Funcional e seus amigos:

  1. Funções puras.
  2. Funções de ordem superior (High order functions).
  3. Funções recursivas
  4. Programação Reativa.
  5. Imutabilidade.
  6. Composição de objetos vs. Herança de classes.
  7. Tipagem forte.
  8. e outros como Map and Reduce

Talvez você esteja se perguntando, por que esses velhos paradigmas não são comumente usados se eles criavam software de qualidade?

Aqui vai minha teoria: antigamente, hardware era um grande obstáculo para a programação, processadores lentos, memórias RAM pequenas, minúsculo espaço de armazenamento e que ocupavam um grande espaço físico. Totalmente contrário aos computadores de hoje.

A programação teve que mudar para se adaptar a essas restrições, e  as grandes empresas, no geral buscavam eficientes formas de programar, então perfomance era um grande problema, lembre-se que recursos como memória não eram baratos como hoje, então paradigmas como Imutabilidade não poderiam estar disponíveis numa escala mainstream.

E então a indústria decolou e nós nos acostumamos às Classes, state-full objects e outras formas de programar software acoplado / complexo. O código legado nasceu e a computação distribuída está agora por todos os lugares, tornando as coisas ainda mais imprevisíveis (threads).

Estamos viciados em IDE’s a fim de desenvolver software, apenas porque sem eles é quase impossível lidar com toda a complexidade do código que nós mesmos estamos produzindo.

O que aconteceu com o poder da simplicidade?
Eu acho que Alan Key explica muito bem nesta talk no evento SAP.

 

Acorde! Não temos mais essas limitações de recursos, podemos fazer melhor!

Por que estamos programando como se fosse nos velhos tempos? Nós não temos mais essas restrições. Lembre-se que você tem no seu bolso um computador com múltiplos cores e muita memória RAM.

Hoje temos recursos que abrem portas para novos e velhos paradigmas que incentivam você a programar de modo mais flexível, previsível e, mais importante, um software sustentável que PELO MENOS REALMENTE FUNCIONE!

Há anos estamos programando da mesma forma, vamos mudar esse cenário, vamos aprender outros paradigmas além de OOP com heranças de classe ou MVC e vamos dominar o estado das nossas aplicações.

Você está interessado? Porque se estiver, eu vou escrever meu próximo post sobre imutabilidade, que na minha opinião é um paradigma essencial para entender porque é tão importante controlar o estado de nossas aplicações. Eu irei explicar porque você escutou “funciona na minha máquina” por tantas e tantas vezes.

 

Declaro:
Programação funcional e seus amigos não são bala de prata, mas não existe tal coisa, e é por isso que nós precisamos continuar evoluindo e criando formas mais eficazes de programar.