Antipadrões que você deve evitar em seu código

Todo desenvolvedor deseja escrever código estruturado, simplesmente planejado e bem comentado. Existe até uma miríade de padrões de design que nos fornecem regras claras a seguir e uma estrutura a ser mantida em mente.

Mas ainda podemos encontrar antipadrões em software que foi escrito há algum tempo, ou foi escrito muito rapidamente.

Um hack básico inofensivo para resolver um problema rapidamente pode abrir um precedente em sua base de código. Ele pode ser copiado em vários lugares e se transformar em um antipadrão que você precisa resolver.

Então, o que é um antipadrão?

Em software, antipadrão é um termo que descreve como NÃO resolver problemas recorrentes em seu código. Os antipadrões são considerados projetos de software ruins e geralmente são correções ineficazes ou obscuras.  

Eles geralmente também adicionam "dívida técnica" - que é o código que você precisa voltar e consertar apropriadamente mais tarde.

Os seis anti-padrões que discutirei neste artigo são Código Espaguete , Martelo Dourado , Âncora de Barco , Código Morto , Proliferação de Código e o Objeto Divino .

Código Espaguete

Spaghetti Code é o anti-padrão mais conhecido. É um código com estrutura de pouca ou zero.

Nada é modularizado. Existem arquivos aleatórios espalhados em diretórios aleatórios. Todo o fluxo é difícil de seguir e está totalmente emaranhado (como espaguete).

Normalmente, esse é um problema em que alguém não pensou cuidadosamente no fluxo de seu programa de antemão e apenas começou a codificar.

O que isso faz?! Eu não posso seguir isso

image.png

Este não é apenas um pesadelo de manutenção, mas torna quase impossível adicionar novas funcionalidades.

Você constantemente quebrará coisas, não entenderá o escopo de suas mudanças ou fornecerá estimativas precisas para seu trabalho, pois é impossível prever os incontáveis ​​problemas que surgem ao fazer tal arqueologia / suposição.

Você pode ler mais aqui sobre o antipadrão do Código de Espaguete .

Martelo dourado

"Suponho que seja tentador, se a única ferramenta que você tem é um martelo, tratar tudo como se fosse um prego." Abraham Maslow

Imagine um cenário comigo: sua equipe de desenvolvimento é muito, muito competente na nova arquitetura Hammer. Funcionou de maneira fantástica para todos os seus problemas anteriores. Você é a equipe líder mundial em arquitetura Hammer.

Mas agora, de alguma forma, tudo sempre acaba usando essa arquitetura. Um parafuso de cabeça chata? Martelo. Parafuso de cabeça Phillips? Martelo. Você precisa de uma chave Allen? Não, você não precisa, martele.

Você começa a aplicar uma abordagem arquitetônica que não se encaixa perfeitamente no que você precisa, mas dá conta do recado. Você depende demais de um padrão e precisa aprender a melhor ferramenta para o melhor trabalho.

Todo o seu programa pode acabar sofrendo um sério golpe de desempenho porque você está tentando transformar um quadrado em um círculo. Você sabe que leva o dobro do tempo para codificar e executar um programa usando a arquitetura de martelo para esse problema, mas é mais fácil e é com o que você se sente confortável.

Também não é muito previsível. Linguagens diferentes têm soluções comuns para os problemas que enfrentam e seus próprios padrões. Você não pode aplicar todas as regras que funcionaram bem para você de um idioma para o outro, sem problemas.

Não negligencie o aprendizado consistente em sua carreira. Escolha o idioma certo para o seu problema. Pense na arquitetura e expanda sua zona de conforto. Pesquise e investigue novas ferramentas e novas maneiras de abordar os problemas que você enfrenta.

Você pode ler mais aqui sobre o antipadrão Golden Hammer .

Âncora de barco

O anti-padrão Boat Anchor é onde os programadores deixam o código na base de código porque podem precisar dele mais tarde.

Eles codificaram algo ligeiramente fora das especificações e ainda não é necessário, mas eles têm certeza que farão no próximo mês. Portanto, eles não querem excluí-lo. Envie-o para produção e, mais tarde, quando necessário, eles podem colocá-lo em funcionamento rapidamente.

Mas isso causa pesadelos de manutenção na base de código que contém todo aquele código obsoleto. O grande problema é que seus colegas terão dificuldade em descobrir qual código está obsoleto e não altera o fluxo, em comparação com o código que o faz.

Imagine que você esteja em um hot fix e tentando desesperadamente descobrir o que é responsável por enviar os detalhes do cartão dos clientes à API para retirar fundos de seus bancos. Você pode perder tempo lendo e depurando códigos obsoletos, sem perceber que nem mesmo está no lugar certo na base de código.

O problema final é que o código obsoleto torna seu tempo de construção mais longo e você pode confundir o código funcional com o código obsoleto. Você pode até mesmo começar a "ligá-lo" inadvertidamente na produção.

Agora você provavelmente pode ver porque é chamado de antipadrão de âncora de barco - é pesado para carregar (acrescenta problemas técnicos), mas não faz nada (literalmente, o código não serve para nada, não funciona).

Você pode ler mais aqui sobre o antipadrão de âncora de barco .

Código morto

Você já teve que olhar para um código escrito por alguém que não trabalha mais na sua empresa? Há uma função que não parece estar fazendo nada. Mas é chamado de todos os lugares! Você pergunta por aí e ninguém mais tem certeza do que ele está fazendo, mas todos estão preocupados demais para excluí-lo.

Às vezes você pode ver o que está fazendo, mas o contexto está faltando. Você consegue ler e entender o fluxo, mas por quê? Parece que não precisamos mais atingir esse endpoint. A resposta é sempre a mesma para cada usuário diferente.

This is commonly described as the Dead code anti-pattern. When you can't see what is "actual" code necessary to the flow and successful execution of your program, versus what was only needed 3 years ago, and not now.

This particular anti-pattern is more common in proof on concept or research code that ended up in production.

One time at a tech meet up I met a guy who had this exact problem. He had tons of dead code, which he knew was dead, and lots he suspected was dead. But he could not get permission from management to ever remove all the dead code.

He referred to his approach as Monkey testing, where he started to comment out and turn off things to see what blew up in production. Maybe a little too risky!

If you don't fancy Monkey testing your production app, try to frame technical debt to management as "technical risk" to better explain why you think it's so important to tidy up.

Or even write down everything your particular module/section does you want to re-write, and take an iterative approach to remove piece by piece the dead code. Checking every time you haven't broken anything.

You don't have to drop a huge rewrite with thousands of changes. But you will either understand why it's so crucial and document why it's needed, or delete the dead code as you desired.

You can read more here about the Dead code anti-pattern.

Proliferation of Code

Objects or modules regularly communicate with others. If you have a clean, modularised codebase you often will need to call into other separate modules and call new functions.

The Proliferation of Code anti-pattern is when you have objects in your codebase that only exist to invoke another more important object. Its purpose is only as a middleman.

This adds an unnecessary level of abstraction (adds something that you have to remember) and serves no purpose, other than to confuse people who need to understand the flow and execution of your codebase.

A simple fix here is to just remove it. Move the responsibility of invoking the object you really want to the calling object.

You can read more here about the Proliferation of Code anti-pattern.

God Object

If everywhere in your codebase needs access to one object, it might be a God object.

God objects do too much. They are responsible for the user id, the transaction id, the customer's first and last name, the total sum of the transaction, the item/s the user is purchasing...you get the picture.

It is sometimes called the Swiss Army Knife anti-pattern because you only really need it to cut some twine, but it also can be a nail file, saw, pair of tweezers, scissors, bottle opener and a cork screw too.

In this instance you need to separate out and modularise your code better.

Programmers often compare this problem to asking for a banana, but receiving a gorilla holding a banana. You got what you asked for, but more than what you need.

The SOLID principles explicitly discuss this in object orientated languages, to help us model our software better (if you don't know what the SOLID principles are, you can read this article).

The S in the acronym stands for Single Responsibility - every class/module/function should have responsibility over one part of the system, not multiple.

You can see this problem over and over again, how about the below interface?

interface Animal { numOfLegs: string; weight: number; engine: string; model: string; sound: string; claws: boolean; wingspan: string; customerId: string; } 

Can you see by even just briefly scanning this interface that the responsibility of this is far too broad, and needs refactoring? Whatever implements this has the potential to be a God object.

How about this?

 interface Animal { numOfLegs: string; weight: number; sound: string; claws: boolean; } interface Car { engine: string; model: string; } interface Bird { wingspan: string; } interface Transaction { customerId: string; } 

Interface segregation will keep your code clear about where the responsibilities lie, and stop forcing classes that only need wingspan to also implement the engine, customerId and model  and so on.

Você pode ler mais aqui sobre o antipadrão de objeto de Deus .

Conclusão

Em qualquer grande base de código, há um equilíbrio constante entre o gerenciamento da dívida técnica, o início do novo desenvolvimento e o gerenciamento de uma fila de bugs para seu produto.

Espero que este artigo tenha lhe dado um olho para detectar quando você pode estar descendo pela toca do coelho de um antipadrão e algumas ferramentas para resolvê-lo de forma limpa.

Compartilho minha escrita no Twitter se você gostou deste artigo e deseja ver mais.