Como programadores, a nossa primeira prioridade é criar código que funciona. Infelizmente, código que simplesmente “funciona” não é suficiente. Código que tem valor real e é duradouro, tem de ser “limpo”. Em “Clean Code: A Handbook of Agile Software Craftsmanship”, Robert C. Martin usa vários exemplos e casos de estudo para nos ajudar a identificar código que pode ser melhorado, e nos dá uma variedades de técnicas para fazermos essa limpeza no código, mas só um pouco e apenas quando lhe tocamos.
O que é código limpo?
No capítulo 1, o Martin, convincentemente, argumenta que código limpo não é somente desejável - é necessário. Se o código não estiver limpo, o desenvolvimento decai com o tempo. Eventualmente, chega a um tal ponto de incerteza, dor e frustração que parece ser mais fácil começar de novo e reescrever tudo do início. Obviamente que se a reescrita não for melhor que o original, o problema persiste, e em pouco tempo a equipe acaba onde tinha começado.
Cada pessoa tem uma definicão de código limpo um pouco diferente. O Martin inclui descrições de código limpo de programadores notáveis como Bjarne Stroustrup, Grady Booch, Dave Thomas, Micheal Feathers, Ron Jeffries e Ward Cunningham. Embora todos eles enfatizem diferentes aspectos de código limpo, há alguns temas emergentes: simplicidade, ausência de duplicação, facilidade de leitura, elegância. Código com estas qualidades é fácil de manter, quebra o ciclo de decaimento / reescrita e nos dá valor verdadeiro e duradouro.
O diabo está nos detalhes
Do capítulo 2 até ao capítulo 6 fala-se de decisões de baixo nível em termos de código: escolha de nomes que fazem sentido, definição de funcões elegantes e de leitura fácil, escrita de bons comentários (e como evitar os maus), formatar o código para melhorar a leitura e a clareza, e de quando se deve usar objetos inteligentes e de quando se deve usar estrutura de dados simples.
O Martin mistura, muito bem, teoria e prática, com exemplos concretos de código que ilustram os seus pontos. Estas seções que nos fazem andar para trás e para a frente contêm muita sabedoria, mas são também longas para resumir ou copiar aqui.
Espalhadas no meio dessas explicações teórico-práticas estão muitas preciosidades, que são bastante concisas e nos fazem pensar: (retirado desde o capítulo 2 até ao 4):
"O problema não está na simplicidade do código mas sim no que está implícito no código: o grau pelo qual o contexto não está explícito no próprio código."
"A primeira regra das funções é que tem de ser pequenas. A segunda regra das funções é que elas têm de ser ainda menores."
"Não tenha medo de criar um nome longo. Um nome longo e descritivo é melhor do que um nome pequeno e enigmático. Um nome longo e descritivo é melhor que um comentário longo e descritivo."
"É difícil de sobrestimar o valor de nomes bons. Lembra-te do princípio do Ward: você sabe que está trabalhando com código limpo quando cada rotina acaba por ser mais ou menos aquilo que espera. Metade da batalha... é escolher bons nomes para funções pequenas que fazem apenas uma coisa. Quanto mais pequena e focada uma função é, mais fácil se torna de escolher um nome descritivo."
"Efeitos colaterais são mentiras. A sua função promete fazer uma coisa, mas também faz outras coisas às escondidas.”
"A arte de programar é, e sempre foi, a arte de desenhar linguagens. Grandes programadores quando pensam em sistemas, pensam em histórias para serem contadas em vez de programas para serem escritos. Eles usam as ferramentas que a linguagem de programação escolhida lhes proporciona para construir uma linguagem muito mais rica e expressiva que possa ser usada para contar a história."
Estes capítulos fazem emergir uma filosofia consistente e coesiva de código limpo e dão conselhos pragmáticos necessários para se seguir, na prática, esta filosofia.
Conceitos de alto nível
Os capítulos 7 e 8 cobrem o tratamento de erros e a interação com sistemas e código externo. Eu achei o capítulo 7 (escrito por Michael Feathers) particularmente valioso. O tratamento de erros é uma daquelas áreas que raramente é bem-feita, e é normalmente encurtada pela literatura de desenho de software. O Michael Feathers nos dá uma visão prática para manter o tratamento de erros separado do fluxo normal do programa, conseguindo assim manter ambos limpos e de fácil leitura.
O capítulo 9 cobre testes unitários: O quão importante é manter os testes limpos como o código de produção limpo, e como manter os testes limpos ("Três coisas, leitura fácil, leitura fácil, leitura fácil"). Este capítulo é sucinto, mas contem muitos exemplos de bons e maus testes para ilustrar os pontos do Martin.
Os capítulos 10, 11 e 12 cobrem conceitos de desenho de alto nível: classes, sistemas e desenho emergente. O Capitulo 10 está fortemente focado no Principio de Única Responsabilidade (SRP), um conceito que vem de um trabalho anterior do Martin, Agile Software Development: Principles, Patterns, and Practices. Aqui, o tratamento não foi tão profundo mas é um bom ponto de partida. O Capitulo 11 fala de código limpo no contexto de técnicas a nível de sistema como Injeção de Dependências e Programação Orientada a Aspectos. O capítulo 12 nos lembra para dependermos dos testes e da refatoração para guiar tanto o desenho de alto nível, como as decisões de baixo nível.
O capítulo 13 cobre Concorrência. Não vai muito fundo no assunto, e parece um pouco introduzido à força, mas contem uma boa quantidade conselhos sólidos.
Os casos de estudos
Nos capítulos 14, 15 e 16. Martin junta as idéias dos capítulos anteriores. Em cada capítulo, Martin começa nos dando um exemplo de código nem muito bom, nem muito ruim e depois nos guia através do processo de refatoração que torna o código muito mais limpo.
Os exemplos de código não são triviais, mas também não são desnecessariamente complicados. São complicados o suficiente para não parecerem um "brinquedo", mas suficientemente simples de entender depois de uma leitura atenta. Eles nos dão o ambiente necessário no qual podemos desenvolver um entendimento mais profundo de como aplicar os conceitos apresentados anteriormente no livro.
Uma coisa é ler que a refatoração se deve fazer em "pequenos passos" outra coisa totalmente diferente é ver em exemplos concretos que pequenos passos um programador experiente e ágil dá. Estes capítulos acrescentam muito valor ao livro. É aqui que tudo o que se leu anteriormente começa a fazer sentido e adquire uma relevância prática. Ler estes casos de estudo me faz sentir que estou a trabalhar ao lado de um programador experiente e muito inteligente -- um testemunho da clareza de escrita do Martin.
Mau Cheiro e Descobertas
O capítulo 17 fecha o livro com uma lista de "mau cheiros no código" e descobertas. Condensa as idéias do livro num formato direto e centrado no problema - ideal para revisão. E com 29 páginas, é como uma referência boa e concisa.
Conclusão
Este livro deverá estar na estante de todos os programadores que se preocupam apaixonadamente pela qualidade e craftsmanship. Os programadores menos experientes ainda o valorizarão mais, mas também o acharão de leitura lenta - este livro está cheio de bons conselhos, sem muito “enchimento”. O Martin usa muitos exemplos e usa uma linguagem clara e concisa, que embora os programadores inexperientes acharão de acompanhamento lento, dificilmente se sentirão perdidos.
Os programadores experientes deverão lê-lo também. Porque reforça aquelas coisas que já se sabe que se deve fazer (e que nem sempre se faz), lembra-nos algumas coisas que já esquecemos e também nos ensina algumas coisas novas. Para a maioria de nós, nos dá uma nova perspectiva sobre aquelas decisões aparentemente mundanas que fazemos centenas de vezes ao dia.