The Pragmatic Programmer - 20nd anniversary edition Este livro é considerado por muitos – eu inclusive – um dos clássicos da computação. Dave Thomas e Andy Hunt escreveram a primeira edição deste livro em 1999 para ajudar seus clientes a escrever software de melhor qualidade e redescobrir o prazer pela programação. As lições contidas no livro tem ajudado gerações de desenvolvedores a melhorar seus skills, independente de linguagem e plataforma.
|
Depois de tratar da filosofia pragmática, no primeiro capítulo, da abordagem pragmática, no segundo, e das ferramentas básicas para o programador pragmático, no terceiro, Thomas e Hunt tratam da paranóia pragmática – mitigar os impactos das falhas em um software.
No one in the brief history of computing has ever written a perfect piece of software. It’s unlikely that you will be the first. And unless you accept this as a fact, you will end up wasting time and energy chasing an impossible dream.
Dave Thomas e Andy Hunt |
A paranóia pragmática, indicada pelos autores, é o reconhecimento de que falhas não são questão de “se” , mas, sim, de “quando”.
If there is any doubt, we validate all information we’re given. We use assertions to detect bad data, and distrust data from potential attackers and trolls. We check for consistency, put constraints on database columns, and generally feel pretty good about ourselves.
Dave Thomas e Andy Hunt |
As recomendações de Thomas e Hunt são efetivas e relativamente simples de implementar. De forma sucinta, eles indicam:
- Empregar Design by Contract – conforme proposto por Bertrand Meyer;
- Usar Assert para previnir o impossível
- Fazer uso cuidadoso de recursos
- Evitar “futurologia”
Empregar Design by Contract
Uma das recomendações dos autores, que parece coerente para mim, é adotar Design by Contract – uma proposta de Bertrand Meyer enquanto projetava a linguagem Eifel.
Vale a pena investir algum tempo conhecendo “linguagens de programação clássicas”, como Eifel, para entender técnicas nem tão difundidas em linguagens mais modernas. |
Segundo DbC, para cada operação que um software executa, é possível determinar:
- pré-condições – valores de parâmetros e outros aspectos de estado da aplicação que devem ser satisfeitos antes do acionamento de um procedimento.
- pós-condições – como intervalos de valores de retorno, eventuais modificações de estado ou outros “efeitos colaterais” resultantes da execução de um procedimento.
- invariantes – condições observáveis como verdadeiras tanto antes quanto depois da conclusão da execução de uma operação (não necessariamente durante).
Um procedimento “respeita o contrato” quando, ao ser invocado adequadamente – com todas as pré-condições sendo observadas – garante que todas as pós-condições bem como as invariantes são devidamente respeitadas. Desajustes nas pré-condições, pós-condições e invariantes constitui um desrespeito ao “contrato”, logo, um bug.
A linguagem Eifel
A linguagem Eifel, projetada por Bertrand Meyer, destaca-se por diversas características interessantes. Dentre elas, a possibilidade de indicar explicitamente pré-condições, pós-condições e invariantes.
Linguagens como Clojure oferecem ótimo suporte ao conceito de contratos como proposto por Meyer permitindo, inclusive, identificar violações em tempo de compilação.
Design by Contracts no .net
.net oferecia, até pouco tempo, ferramentas específicas para implementação de DbC. Infelizmente, entretanto, a biblioteca não foi migrada para .net core.
É importante, entretanto, destacar que Design by Contract é em última instância, uma técnica de projeto que não depende de características de linguagem ou features de compiladores.
Programadores pragmáticos, em linguagens sem amplo suporte a DbC, verificam pré-condições com Assertions e pós-condições e invariantes, por exemplo, com testes de unidade. Eventualmente, algumas linguagens permitem expressar possíveis características do contrato, como pureza de funções ou aceite de parâmetros nulos, em sua sintaxe.
Invariavelmente, é possível relacionar pré-condições, pós-condições e invariantes para métodos ou procedimentos. Programadores pragmáticos utilizam recursos para tornar os elementos do contrato explícitos no código, como forma de detectar bugs mais rapidamente. |
Usar Assert para previnir o impossível
Em alinhamento com DbC, Thomas e Hunt, recomendam enfaticamente o que denominam “Assertive Programming”. Em termos simples, introduzir instruções Assert como maneira de previnir o impossível.
Whenever you find yourself thinking “but of course that could never happen”, add code to check it. The easiest way to do this is using assertions.
Dave Thomas e Andy Hunt |
Os autores destacam que algumas pessoas consideram que assertions podem induzir overhead de processamento e que, por isso, deveriam ser “ignoradas” quando testes necessários tenham sido executados antecipando a distribuição. Thomas e Hunt consideram essa uma “má prática”, visto que testes não conseguem antecipar todas as falhas e assertions podem ajudar a impedir a propagação destas.
One of the benefits of detecting problems as soon as you can is that you can crash earlier, and crashing is often the best thing you can do.
Dave Thomas e Andy Hunt |
Fazer uso cuidadoso de recursos
Dentre as recomendações de Thomas e Hunt estão a ideia de que alocações e liberações de recursos sejam controladas localmente – ou seja, o mesmo código que faz uma alocação deve executar a liberação.
Disposable em .net
Objetos que precisam ter alocação e liberação gerenciadas manualmente, em .NET, são sinalizados pela interface IDisposable
Aprenda a identificar e utilizar recursos não gerenciados e certifique-se de estar adotando os padrões de sua linguagem/framework para controlar, principalmente, alocação e liberação. Uma das falhas mais comuns em sistemas complexos é o “vazamento de recursos”. |
Evitar “passos grandes demais”
Finalmente, Thomas e Hunt recomendam “codificação prudente”. Ou seja, em pequenas etapas.
São recomendações dos autores:
- Utilizar ferramentas REPL para antecipar comportamento de trechos de código;
- Utilizar testes de unidade para verificar correção com frequência;
- Antecipar funcionalidades através de demonstrações e discussões com o negócio.
Avanços em baby steps são mais fáceis de verificar. Além disso, quando ocorrem falhas, essas costumam ser mais fáceis de corrigirl
Ser pragmático é ser, essencialmente, ágil. |
Para pensar…
Enquanto os primeiros capítulos do livro falavam sobre atitude e ferramentas, o quarto capítulo, de fato, se aproxima do código.
As práticas propostas pelos autores são simples e passíveis de implementação.
E você? Leu The Pragmatic Programmer? Tem ponderações sobre o que entendi? Algo importante que ignorei? Te convido a compartilhar suas visões nos comentários. Vamos aprender juntos!
Em breve, retomamos com ponderações sobre o capítulo 5.