Abstração exagerada é pior que duplicação de código

Duplicação de código é ruim, porém existem coisas piores, como macarronese e abastração exagerada...

engenharia de software

Nesse artigo vou explicar porque evitar duplicação de código a todo custo pode te levar a um problema ainda mais grave: Abstração exagerada.

Um problema ainda maior

Se tem uma habilidade que ainda não aprendemos é prever o futuro, usamos estatística, sexto sentido, achismo, tarô, scrum e uma variedade de técnicas para tentar prever o futuro. Lembramos muito bem quando acertamos mas esquecemos quando erramos, acho que isso causa aquela sensação de que somos bons em prever o futuro, mas não somos!

Quando estamos escrevendo um novo módulo, componente, classe, normalmente tentamos prever o futuro: Será que vamos usar isso em outro lugar? E se mais alguém da minha equipe quiser usar algo parecido? Nesse momento a pessoa, muito bem intensionada, resolve abstrair aquele módulo, isto é, abandonar o caso de uso no qual aquele módulo deve tratar e tratar outros possíveis casos de uso. Spoiler! Não vai rolar!

Abstração exagerada

Abstração exagerada ou over-engineering é quando você resolve um problema que não existe!

Um módulo que devia tratar um caso de uso passa a tratar vários casos, imagináveis. O resultado disso é um módulo cheio de abstração desnecessária e complexo. Com o tempo aquele módulo começa a ganhar mais responsabilidades (casos de uso), em classes você vê aumentando a quantidade de funções que não interagem com propriedades, em componentes React você vê a quantidade de props opcionais aumentando.

Em pouco tempo aquele módulo deixa de ser reutilizável (se é que um dia foi) para se tornar algo complexo e específico, algo que ninguém que mexer porque não entende muito bem como ele funciona e quais os casos de uso que ele resolve. Resultado: Vão criar outro módulo parecido, mas menos prepotente, que trata apenas um caso de uso, algumas vezes inclusive até mesmo o caso de uso inicial.

Já ví isso acontecer muitas vezes, a intenção é boa, deixar o código limpo sem duplicação, porém o resultado é desastroso, excesso de complexidade, manutenção custosa e medo na equipe. Até que alguém vai criar um módulo similar menos prepotente. Por fim irão coexistir a versão simples, que provavelmente será reutilizada e a versão legada que ninguém vai ter coragem de meter a mão.

Não tente prever o futuro

Software que se adapta as necessidades é melhor do que software que tenta prever o futuro. Quando escrevo um módulo penso apenas naquele caso de uso específico, quero que meu módulo resolva bem um único problema, mantenho em mente os motivos de mudança daquele módulo (SRP), quero que minhas funções internas usem boa parte das suas propriedades, mantendo alta coesão.

Se eu sei que aquele módulo pode ser reutilizável avalio como vou fazer isso (OCP), em React posso usar children props, aplicar State Reducer Pattern, Component Composition ou crio um componente "Wrapper" que admite configurações e renderiza componentes mais fechados.

Muitas vezes não estamos escrevendo um framework ou uma lib para diversos casos de uso, estamos escrevendo módulos que serão usados em um software para um tipo de cliente. Por exemplo em React, escrevemos um componente de sidebar para o software X do cliente Z, e não um componente sidebar para para todos os softwares da empresa.

No geral tenho em mente uma regrinha do livro Refatoração (Martin Fowler):

Escrevo a primeira vez, escrevo a segunda torçendo o nariz, na terceira eu refatoro.

Como evitar

Estamos sempre querendo prever o futuro, acrescente boas intenções e uma pitada de sofisticação técnica e temos o tempero ideal para criarmos soluções para problemas que não existem.

Pelo que notei isso ocorre com frequência em pessoas que estão entre o junior e o pleno, geralmente elas querem mostrar que estão a frente tecnicamente.

Outro terreno fértil é excesso de tempo, quanto mais tempo tivermos mais iremos labidar nosso código, tão importante quanto saber refatorar é saber a hora de parar.

Por fim isso também ocorre com pessoas que simplesmente não querem ler o código que já existe, você consegue identificar claramente a pessoa que sempre está escrevendo algo do zero.

Não faça isso! O seu eu do futuro e a sua equipe irão de agradecer por manter o código simples.