Um caso contra o “Clean Code”
- #Arquitetura de Sistemas
Será que o paradigma do “clean code” é tão bom quanto costumam espalhar aos quatro cantos? Vamos tentar descobrir nesse artigo.
Já é máxima da programação a concepção de que “código limpo”, ou “clean code”, se preferir, como meio ótimo de se escrever código para as mais variadas situações. Em outras palavras, o paradigma que alcança os melhores resultados e que deve ser usado por todos os programadores, dos iniciantes aos veteranos.
No entanto, nem sempre é o caso, o “código limpo” pode nem sempre ser o mais interessante para determinados fins, causando perdas em performance, atrapalhando a legibilidade, por incrível que pareça, custando tempo e causando dificuldades desnecessárias, entre outros problemas.
Contudo para provar isso primeiramente precisamos decifrar exatamente o que significa “código limpo”, avaliar suas principais premissas, onde que elas são válidas, mas também onde elas falham. E se possíveis, quais alternativas temos às mesmas.
O que é “clean code” afinal?
Enquanto não existe uma definição formalizada, há diversas aproximações dadas por diferentes autores a respeito do tema. Um dos mais famosos livros, Clean Code: A Handbook of Agile Software Craftmanship[1] (também disponível em português), escrito por Robert C. Martin, conhecido informalmente pelo nickname de “Uncle Bob”.
Tal livro é um dos mais proeminentes no assunto, sendo amplamente citado, constituindo assim um bom ponto de referência e de início para a investigação do tema, sendo o próprio “Uncle Bob” um programador veterano e um dos principais proponentes e defensores do paradigma. Mas o que exatamente será que esse livro e esse autor nos apresentam?
Em resumo, “código limpo” pode ser descrito como aquele código que é facilmente compreendido, modificado, estendido e mantido e que por isso mesmo pode ser facilmente ser trabalhado por qualquer pessoa.[2]
Em suma o objetivo é o de facilitar a experiência dos desenvolvedores, especialmente num contexto de um projeto em equipe, evitando erros e bugs, re-trabalhos, e tornando a manutenção do código mais fácil.
As vezes o termo é intercambiado por “bom código”, em oposição ao dito “código ruim”, que possui atributos contrários, atrapalhando na produtividade.
É importante notar que o livro aponta, de maneira muito responsável, diversos fatores que podem causar o código de ser de baixa qualidade – pressão, tempo, orçamento, ingerência do projeto – o que causa alguns problemas recorrentes no cenário de hoje onde reinam atualizações, patches e bugfixes.
Para muitas empresas é mais efetivo de custo (cost effective) “lançar primeiro, corrigir depois”, mesmo que isso degrade a experiência do usuário e até dos programadores. Nessa enseada, o “código limpo” surge como contramedida visando ajudar a contornar os problemas que podem decorrer de um código feito sob essas circunstâncias limitantes.
O objetivo, segundo o autor em seu capítulo introdutório, em consonância com outros autores e programadores que o mesmo cita é fazer um código que seja “elegante e eficiente”, “simples e direto”, “feito por alguém que se importa” e de acordo com o mesmo, essas regras partem da sua experiência em muitos anos trabalhando com programação.
O livro parte ao longo dos seus capítulos em vários tópicos como “Nomes Significativos”, “Funções”, “Comentários”, “Formatação”, “Objetos e Estruturas de Dados”, “Tratamento de Erros”, entre outros, fazendo análises de código “ruim”, definindo regras do que fazer e o que evitar e providenciando exemplos para facilitar a compreensão destas regras.
Créditos da imagem: https://stancalau.ro/clean-code-book-review/
Por que o “clean code” pode não ser bom negócio?
Até onde pudemos ver, tudo parece ser muito bom e belo. Mas precisamos olhar mais atentamente.
É importante notar que o “código limpo”, como nós vimos, não é intrinsicamente algo ruim em suas premissas e nem nos resultados esperados. Muito pelo contrário, essencialmente ele é muito boa ideia.
Qualquer nível de organização e racionalização do processo, de modo a criar boas práticas e padrões que podem facilmente serem entendidos e aplicados, auxiliando nos processos de escrita, entendimento, refatoração, expansão, etc. é uma coisa boa para a produção, teste e manutenção do código.
Em tese, um código mais fácil de manter apresenta custos reduzidos no longo prazo e aumenta a produtividade. Um bom modelo de organização é muito melhor do que nenhuma organização.
Contudo consideremos algumas situações bem específicas:
- Em nosso primeiro caso um problema surge quando as “sugestões” de práticas do “código limpo” são tratadas como dogmas inquestionáveis, que não passam pelo nosso raciocínio crítico antes da aplicação e podem ter efeitos adversos.
- Algo mais que pode acontecer é que as práticas do “código limpo” conflitam diretamente com o objetivo de design do código que se está trabalhando, por exemplo, tornando-o mais lento ou mais prolixo desnecessariamente.
- Outra situação também bastante recorrente é que quem pode definir quais práticas de codificação diferem das adotadas pela empresa que trabalha ou as exigidas pelo cliente do projeto, que podem especificar normas que claramente vão de encontro ao que nos deparamos no livro supracitado e ao que outros autores também definem como “código limpo”.
Será que ainda assim vai ser boa ideia aplicar as técnicas do “código limpo” indiscriminadamente em alguma dessas situações? Vamos analisar em mais detalhes esses 3 cenários nas seções a seguir.
Créditos da imagem: http://c-est-quoi.com/fr/definition/critique
Principais críticas ao “clean code”
Detratores do “código limpo” se concentram em duas principais frentes, os que possuem críticas ao livro em si, e aos que possuem críticas à metodologia [3 e 4]. Iremos por questão de abrangência e relevância do assunto focar mais no segundo caso, pois lembremos que o livro supracitado não é o único no assunto (e com chance nem o melhor).
Vejamos alguns pontos:
- É importante atentarmos que as premissas do “código limpo” são, antes de mais nada, sugestões. O próprio autor enfatiza isso no livro. E que por isso mesmo não devem ser pensadas como regras absolutas ou leis imutáveis. Elas são regras específicas para fins específicos. Antes de aplicar elas, convém analisar diversos fatores.
- Não existe uma “maneira certa” de escrever um “código limpo”. Pessoas diferentes escrevem código de maneira diferente. Existem meios de tornar o código mais impessoal – e com menos de vícios de determinada autoria – tais como guidelines (linhas-guias) e manuais de boas práticas, mas não existe 100% certo e errado nesse meio.
- Por isso mesmo, o que é “código limpo” é algo puramente subjetivo: Não existem critérios concretos e objetivos pra classificar um código como “limpo”, deixando as coisas no domínio da incerteza. Se for considerar a legibilidade, por exemplo, o que pode ser um “código limpo” para uns, pode não ser para outros. É algo que vai variar de pessoa pra pessoa.
- Podemos fazer uma analogia do código com a comunicação, algo que também não é uma ciência exata; um bom código que conseguir resolver o problema de maneira razoável e que seja razoavelmente fácil de entender já é “bom o suficiente”, pois pode ser entendido por todas as partes envolvidas e executados pela máquina sem problemas.
- Excesso de ênfase nos princípios de “código limpo” pode causar ruído nessa comunicação, como excesso de floreios, tais como abstrações e ênfase na estética que podem atrapalhar o entendimento, ou ser tempo que poderia ser gasto em outros trabalhos, assim tendo efeito contrário ao que o paradigma propõe em primeiro lugar.
- Os princípios, no caso do livro, foram elaborados por programadores em determinada época, contexto e linguagens. Enquanto vários desses princípios podem ser amplamente aplicados, o uso irá variar muito do caso. Então não existe um “código limpo universal”, cada linguagem, cada aplicação, cada architectural pattern será um caso diferente.
- Um exemplo disso é o caso de dar preferência ao polimorfismo, ao invés dos if/else e when/case. Visto que este é um conceito de OOP (object oriented programming) ele se invalida se formos por uma via diferente, por exemplo, a mais moderna ECS (entity component system) que há diferente ênfase sobre onde os procedimentos e os dados devem ser armazenados.
- Há especificidades em certas linguagens que tornam inviável de seguir alguns dos princípios, como por exemplo, na formatação e organização do código: Em Python é necessário uso estrutura específica para corretamente delimitar os blocos de código, não tendo flexibilidade nessas partes pra especulação.
Esses são alguns exemplos de críticas recorrentes para nos fazer lembrar que devemos ter parcimônia na hora de usar o “código limpo”, sempre examinando caso a caso, projeto a projeto. Ele pode ser a nossa opção padrão, mas nunca como a única. Contudo todos esses casos são vagos e hipotéticos.
Mas e em casos mais concretos que ao adotar as práticas como cartilha vamos de fato estar deixando algo à mesa? É o que veremos a seguir.
Créditos da imagem: https://www.stellarinfo.com/blog/great-tips-prevent-computer-slowing/
Casos onde o “clean code” pode ser “prejudicial”
O “código limpo” prioriza fatores como simplicidade, legibilidade e manutenibilidade, isso muitas vezes em detrimento de outros fatores como escalabilidade, performance e otimização. Em outras palavras, há casos que na tentativa de tornar mais simples de se ler e entender, na verdade pode estar acarretando em perda substancial de desempenho.
E com essas perdas, tornando-o assim, efetivamente, num código “pior”, por meio de certas métricas. Essas sim bastante objetivas e fáceis de medir.
Casey Muratori, programador veterano da indústria nos mostra em um de seus vídeos intitulado ‘"Clean" Code, Horrible Performance’[5] que a simples escolha de se aderir estritamente aos princípios do “código limpo” nos faz desperdiçar performance que nos remeteria a estar usando computadores de mais de 10 anos atrás.
Assim estaríamos jogando fora todo o avanço dos computadores na última década, em troca de ter um código um pouco mais “clean”. Apesar do caso ser anedótico, as diferenças de performance podem ser da ordem de cerca de mais de 20 vezes, o que é algo difícil de se ignorar.
Enquanto em boa parte das aplicações pode ser “aceitável” a espera de determinado tempo para execução, e que a diferença da otimização pode ser negligenciável, sem perdas consideráveis na prática, não se pode negar que as ineficiências se acumulam ao longo do tempo e que todo gasto de tempo e de energia para além do necessário é sempre um desperdício.
E nos tempos atuais, onde há diversas aplicações que performam muito abaixo do que deveriam, mesmo o “código limpo” pode não ser a melhor solução para os problemas e desafios atuais, em especial o energético, que requer que pensemos em soluções mais econômicas e menos poluentes, ou em outras palavras, mais eficientes, gastando menos energia no processo.
Há também diversas outras condições e tipos de projetos que o “código limpo” não deve ser priorizado, tais como aplicações críticas de latência ou então na programação de jogos, onde cada milissegundo salvo é importante para garantir a melhor estabilidade e funcionamento das mesmas.
Nesses casos é necessário focar em metodologias que façam uso otimizado dos dados, evite processamento e perdas de ciclos desnecessárias, foquem no uso do cache e possuam otimizações para os processadores utilizados, visando conseguir sempre o máximo de desempenho.
Créditos da imagem: https://www.odysseyis.com/home/programmer-group-computers/
E se as demandas forem contrárias ao “clean code”?
Um último caso para analisarmos não está no código em si ou nos seus efeitos hipotéticos, mas no seu ambiente de trabalho.
Pode ser argumentado que o “código limpo” não adere a princípios ou metodologias de programação mais modernos ou novos padrões emergentes, asfixiando a criatividade e a inovação, ou então que as práticas podem não atender a bancos de códigos de legado e por isso não ser viável a transição para o mesmo. E é por isso mesmo que o código limpo pode não ser o mais adequado para o seu emprego atual ou futuro.
É possível até observar casos de que a mudança dos códigos seja indesejável para o trabalho em equipe mesmo que o código seja tão bom quanto ou até melhor que o código “não limpo” [6]. No fim das contas, num cenário de trabalho em equipe e de empresas, a padronização desta que deve prevalecer.
Do contrário o “código limpo” pode estar indo contra as práticas da indústria, especificidade do domínio, e priorizando outros fatores que não a legibilidade, ir de encontro à praticas históricas e de expertise e experiência das equipes, além das necessidades dos investidores ou clientes que podem dar outro rumo ao projeto.
Em competições de códigos como hackathons e code jams então, “código limpo” é uma coisa pra nem ser considerada. A situação é quem vai ditar se o uso vai ser válido ou não.
Felizmente no mundo de hoje, com o advento da inteligência artificial generativa, também é possível acelerar o entendimento de códigos tanto “limpos” quanto os “não-limpos”, e inclusive fazer a devida conversão entre eles, e a tendência com o tempo é que essas ferramentas de IA só melhorem, e tornem a vida do programador mais prática e completa.
Mas existem outras soluções.
Créditos da imagem: https:// https://school.geekwall.in/p/ifpKUoYf1
Como contornar os problemas do “clean code”?
De maneira simplificada, a melhor maneira de contornar os problemas do “código limpo” é... Não usando ele. Parece óbvio ou até besteira dizer, mas é preciso enfatizar por que não existe nenhuma “escola de pensamento” que seja necessariamente contrária ou que podemos usar como alternativa exata pra substituí-la de forma a evitar todos os seus problemas.
O que você pode fazer é adaptá-la usando seu senso crítico. Outros livros e autores partem para outras abordagens, priorizam outros pontos, aderem a outros padrões e procedimentos, mas a tendência geral é sempre procurar os mesmos resultados.
Como diria o ditado, para se fazer omelete é preciso quebrar os ovos. Não é preciso ter medo de “se sujar” um pouco no código, até por que não existe nenhum parâmetro que defina o que é um “código perfeito”.
Numa definição bem descompromissada com regras formais, um bom código é aquele que consegue efetivamente (e eficientemente) resolver o problema em questão, e também não gerar outros problemas. Ele é suficientemente bem escrito e legível, sem se ater para formalidades.
Nesse ponto é bom notar que certa parte de nossos códigos serão mexidos mais de uma vez e a depender da metodologia ou framework de desenvolvimento adotada por você ou pela equipe, teremos tempo depois para poder fazer o refinamento do mesmo.
Num primeiro momento, temos um problema em mãos e o objetivo da programação é justamente resolvê-lo. Como um código é algo dinâmico com muitas “partes móveis”, convém ver ele rodar na prática. Primeiro fazemos um “arranjo técnico” (quem nunca?) pra sanar os problemas da maneira mais rápida possível, para depois então partir para algo mais padronizado.
Apesar de isso render retrabalho, a própria natureza da programação é assim, exige que estejamos constantemente revisitando, depurando e corrigindo nossos códigos, e apenas o “código limpo” não irá garantir que escapemos sempre disso.
Créditos da imagem: https:// https://medium.com/learnfazz/mengenal-clean-code-cbbdfe771846
Refatorações para “limpar” o código devem ser feitas após se ter um código feature complete (algo como “funcionalmente completo”) pois há casos em que o mais importante é ter um código que funcione em primeiro lugar. Foco nos fins, que é o resultado do código, não no meio, que é se a escrita obedece a X ou Y.
Segundo que é sempre necessário fazer diversas considerações, ponderações e julgamentos, pesando os critérios de adequação, eficácia e eficiência.
Um “código limpo”, mas que performa pior comparado a um código “menos limpo” faz com que revejamos nossas prioridades e adotemos o segundo, já que a eficiência ganha nunca é a troco de nada, ela é sempre algo que irá agregar ainda mais valor ao seu produto ou serviço, nesse caso, o código.
Por fim, se estiver na etapa de otimização e pra isso ter que efetivamente “sujá-lo” para tornar ele mais performante, não custa nada documentar essas mudanças e apresentar os códigos equivalente feitos da maneira “limpa” para podermos entender o que está se passando naquele trecho.
Talvez até seja apresentar quais ganhos de performance e os motivos que levam àquela escolha. Nada impede que seja argumentada qual a melhor solução, desde que relevante e devidamente justificada, a fim de mostrar por qual motivo as convenções de “código limpo” tiveram que ser quebradas.
Tudo vai depender muito do tipo e da escala do projeto, da equipe que tiver trabalhando e de diversos outros fatores, tais como os já citados orçamento, tempo de desenvolvimento e das práticas adotadas na sua empresa, se for o caso.
No fim das contas o melhor dos códigos é aquele que funciona bem pra você e pra sua equipe, independente de ficar procurando “receita de bolo” dizendo o que você deve fazer ou não fazer. Se você sentir que o “código limpo” mais atrapalha do que ajuda no momento, pode abandoná-lo sem medo.
Importante apenas as boas práticas e bom senso para não se emaranhar nos seus códigos depois. Nesse caso boa documentação sempre vem a calhar, pois podem diminuir atritos e melhorar o entendimento de determinada parte do código e tornar a vida da equipe mais fácil também.
A beleza da programação é justamente que não existe um – e apenas um – jeito certo de se resolver os problemas. Há várias abordagens, todas com os seus prós e contras, e cabe ao programador sempre julgar quais as melhores para a situação naquele momento.
Créditos da imagem: https://blog.bydrec.com/what-is-the-difference-between-software-development-vs.-programming
Para concluir
Em resumo, o “código limpo” é algo bom? Geralmente sim, mas com algumas observações. Depende do caso de uso. Certamente é um paradigma importante que deve ser estudado, praticado e entendido a fundo, para que então quando necessário improvisar por fora das linhas-guia, que seja com o devido conhecimento de causa.
Enquanto o “código limpo” pode apresentar boas diretrizes e ser a linha-guia para quem estiver programando, ela pode não ser necessariamente a melhor para a situação. Vimos que em empresas, na programação de jogos ou aplicações críticas onde cada milissegundo conta, outras práticas devem ser priorizadas, mesmo se essas forem de encontro ao paradigma.
O objetivo não é manchar o uso da prática, mas sim enaltecê-la, nos fazer pensar criticamente ao invés de a seguir à risca. Não advogar o uso de “código sujo” ou práticas ruins, muito pelo contrário. É um convite a entender o “código limpo” para além da superficialidade e das “receitas prontas”, criticá-lo quando necessário e melhorá-lo cada vez mais.
No fim ele é apenas uma ferramenta como qualquer outra, e seu uso só será tão bom quanto a pessoa que a está usando. Num campo tão dinâmico como a programação, na qual paradigmas novos surgem a todo momento, uns caem em desuso e outros são redescobertos, não se pode dar uma resposta em definitivo, sob o risco de a resposta ficar rapidamente ultrapassada.
Mas assim como um bom código, o uso da prática de “código limpo” pode ser refinado várias vezes e estar sempre em processo de constante evolução, assim como também sempre devemos estar.
Referências e Material Adicional
- Martin, R. C. (2008). Clean Code: A Handbook of Agile Software Craftsmanship. Prentice Hall.
- Lukaszuk, W. (2011). Summary of ‘Clean code’ by Robert C. Martin. Gist. Disponível em: <https://gist.github.com/wojteklu/73c6914cc446146b8b533c0988cf8d29>. Acesso em: 24 out. 2023.
- qntm. (2020, jun. 28). It’s probably time to stop recommending Clean Code. qntm. Disponível em: <https://qntm.org/clean>. Acesso em: 24 out. 2023.
- Vários Autores. (2020, jun. 28). Discussão de ‘It’s probably time to stop recommending Clean Code’ no Reddit. Reddit. Disponível em: <https://www.reddit.com/r/programming/comments/hhlvqq/its_probably_time_to_stop_recommending_clean_code/>. Acesso em: 24 out. 2023.
- Muratori, C. (2019, fev. 7). “Clean” Code, Horrible Performance [vídeo]. YouTube. Disponível em: <https://www.youtube.com/watch?v=tD5NrevFtbU>. Acesso em: 24 out. 2023.
- Abramov, D. (2022, jan. 12). Goodbye, Clean Code. Overreacted. Disponível em: <https://overreacted.io/goodbye-clean-code/>. Acesso em: 24 out. 2023.