Design Smells

Gabriel Lima
Jurassic Park Hackers
10 min readOct 15, 2017

Por que diabos eu escrevi sobre odores do código? Pra falar a verdade, eu queria ter falado sobre SOLID, era pra ser sobre SOLID, e por que então não escrevi sobre SOLID?

Estava lá eu, folheando (mentira porque era pdf) o livro Agile Principles Patterns and Practices in C# por Robert C. Martin e antes de chegar no capítulo de SOLID, passei pelo capítulo sobre Design Smells.

Código com cheiro de sovaco

No momento que eu lia, minha memória me trazia momentos que se encaixavam com o que estava escrito ali. Como é raro eu ter esses relapsos de memória, abri logo o Medium e comecei a escrever pra não deixar a lembrança ir embora.

Portanto, de um rascunho que servia apenas de memória digital, virou um texto um pouco mais organizado que decidi compartilhar.

Espero que gostem!

Para Robert C. Martin, você sabe que o software está apodrecendo quando esse começa a catingar (feder). Ele elenca 7 odores, que você pode acompanhar abaixo:

Rigidity

Com vocês Uncle Bob:

A design is rigid if a single change causes a cascade of subsequent changes in dependent modules.

Provavelmente a maioria dos desenvolvedores já presenciaram essa tal rigidez. Quem nunca teve que alterar um trecho de código e percebeu que teria que modificar várias outras classes/funções que chamavam esse trecho alterado?

Certamente você já passou por isso alguma vez. Pare agora para lembrar o seu sentimento ao dar de cara com esse problema.

Eu passei por isso e digo que é um sentimento de desencorajamento. Te faz questionar se são somente essas classes/funções que devem ser alteradas (será que não tem mais nada que deve ser alterado?).

E não para por aí, agora vem o momento chave: avaliação da Pull Request. Se você que esteve afundado por alguns dias alterando todos os lugares necessários, não tem muita segurança, imagina quem vai avaliar essa PR.

O que já vi acontecer em casos como esse:

1) Você escolhe dois cabra macho pra avaliar essa PR e o resultado é uma discussão infinita, os avaliadores questionando, e você tentando explicar o porque de mexer nesses lugares (daqueles que lembra, já que mexeu em tantos). A alteração é tanta que os avaliadores são obrigados a baixar o código em suas máquinas para acompanhar tudo que foi alterado. Certamente essa feature vai atrasar, porque essa PR vai longe! Talvez tenha um final feliz, onde com a colaboração dos avaliadores você se sente mais seguro do que alterou, já que eles compraram essa briga contigo. Ou, toda essa discussão (que vejo com bons olhos) na verdade só fez os três ficarem mais putos com o design do software, por se sentirem incapazes do que fazer diante do projeto e terem que pagar pra ver esse código em produção.

2) Você meticulosamente escolhe dois avaliadores que não são os "caras", tu sabe o que esperar deles, e sabe que bem conversadinho essa PR passa. Eu até posso imaginar porque você fez isso. Ficar por muito tempo com uma feature, ainda mais uma que de te fez passar por altos e baixos, isso cansa. Sem contar em alguns casos de ter que explicar pro time o porque da demora. Sabemos que explicar algo assim é complicado, só quem está na luta sabe o tamanho da bucha. Enfim, você passou para os dois avaliadores e sabe que eles vão se cansar logo. Eles, de tanto rolarem o scroll do mouse na PR, vão logo aprovar a PR e deixar um comentário do tipo "Segue o jogo", "Confio", "Vai com Deus". No final, para os dois avaliadores foi mais uma PR monstra, que não se tem nada a fazer a não ser aceitar. Já para você é mergear a PR pra produção e torcer para que essa bomba não estoure.

Fragility

Quando você se questiona "será que não tem mais nada que deve ser alterado?" é porque realmente você não faz ideia se existem outros lugares que não tem relacionamento forte com a sua alteração, mas que também podem quebrar. E isso meus amigos, é dito como fragilidade, novamente citando Uncle Bob:

Fragility is the tendency of a program to break in many places when a single change is made. Often, the new problems are in areas that have no conceptual relationship with the area that was changed.

Para um desenvolvedor é bem complicado ter que lidar com essa incerteza. Ainda mais quando não existem testes que indiquem que todo o restante está funcionando.

Já passei por isso, já tive que mexer em um código onde nunca havia me passado pela cabeça estourar em outro lugar. Mas fui salvo, fui salvo pelos testes. É bem raro eu rodar todos os testes na minha máquina, somente aqueles em que tenho noção que podem quebrar e foi nessas horas em que o CI quebrou, impossibilitando mergear a PR.

Immobility

Tio Bob define imobilidade (um design imóvel, preso) como:

A design is immobile when it contains parts that could be useful in other systems, but the effort and risk involved with separating those parts from the original system are too great.

Lá vem a história: em uma bela manhã numa daily meeting eu sou informado por um dos integrantes do time que a regra de negócio que eu precisaria codar já estava pronta. Ou melhor: semi pronta. Ao saber disso, me parecia óbvio que demoraria menos tempo para entregar a tarefa, afinal de contas tá quase pronta, certo?

Errado! Ao me deparar com essa parte de código que eu poderia reutilizar, notei que na verdade eu não conseguiria tão facilmente.

Devo eu tentar mexer nesse código para torná-lo reutilizável para o meu caso?

R: Daí depende.

Depende do quê?

R: Depende de ter testes nessa joça.

Ufa, tinha testes. Pude mexer na classe adaptando-a para o que eu precisava, mas a cada mudança, rodava todos os testes e acompanhava o que quebrava.

Num mundo paralelo sem testes — tipo o de Rick and Morty — eu teria duas escolhas, que por sinal ruins.

Multiverso em Rick and Morty
  1. Entendo a regra de negócio daquilo que posso (já que não há um fu!#@ teste documentando o seu comportamento) e introduzo essa regra duplicada na minha nova classe.
  2. Simplesmente mexo nessa classe adaptando para aquilo que preciso, bato no peito e digo: "la garantía soy yo".

Vale uma ressalva para o segundo item. Nos olhos dos outros, você é um cara destemido, que de início pode até inspirar com essa atitude. Até que um dia a casa cai, toda aquela personalidade forte vai pro brejo e vai ter que lidar com bugs, com clientes internos e externos reclamando pra resolução ser pra ontem.

Viscosity

Para Robert C. Martin a viscosidade vem de duas maneiras: viscosidade do código e viscosidade do ambiente de desenvolvimento.

Digamos que você recebeu um pequeno ajuste pra fazer no sistema. Você analisa e encontra algumas maneiras para resolvê-la. Alguma dessas maneiras preservam o design do sistema, já outras não. Quando a preservação do design existente for mais difícil que as outras alternativas (mais conhecidas como gambiarras), a viscosidade do design é alta.

Gosto dessa frase do tiozão Bob:

It is easy to do the wrong thing but difficult to do the right thing.

Já a viscosidade no ambiente de desenvolvimento vem do latim: ambiente lento e ineficiente.

Participei de um projeto mobile híbrido. Acreditem, cada alteração que eu fizesse (que fosse mínima) era necessário buildar o projeto. Era lento, bem lento, ao ponto de ser possível dar um rolê numa página web, ler uma notícia, ver um video no Youtube. Além de tirar a atenção do desenvolvedor toda hora, cansa passar um dia trabalhando dessa maneira. E cansa acordar pela manhã e saber que vai precisar mexer num projeto desse.

Essa viscosidade do ambiente de desenvolvimento é muito prejudicial ao projeto e ao time. Ninguém queria acrescentar funcionalidades num projeto como esse, tanto que de tempos em tempos o time discutia sobre trocar para mobile nativo. Não que esse fosse o principal motivo (com certeza era um deles), mas o maior desejo era refazer o projeto para tornar o ambiente menos doloroso de se trabalhar.

Needless Complexity

Outrora, quando o pequeno Gabriel aqui estava engatinhando na área de programação, chega até ele um requisito. O Analista de Sistemas avaliou esse tal requisito e através de vários cálculos altamente complexos determinou que demoraria tanto tempo pra ser feito. O Programador (eu) recebeu o dito cujo requisito, compreendeu o que deveria ser feito e iniciou sua jornada do código. Mas, para espanto de todos, inclusive do Analista — O calculista, levou poucas horas para aquilo estar "pronto". O que eu fiz? Com fome de codar, berrei "próximo!", pedindo mais um requisito. Mas, o Analista foi pego de surpresa, ele não havia um próximo requisito na fila (ainda estava analisando, calculando, pensando no próximo requisito).

Foi aí que pensei: fechô então, bora deixar esse código mais robusto!

E iniciei a era da abstração, tudo era altamente abstrato, reutilizável, caso algum dia viesse ter algo parecido. Lembro da sensação, dizia pra mim mesmo: sou um gênio, simplesmente fiz uma obra de arte!

Não vivi tempo suficiente naquela empresa pra ver alguém reutilizar aquele código. Aquela obra nunca foi reutilizada, e me pergunto todos os dias — mentira, para de ser falso! — por quê, pai, por quê?

Por sorte, encontrei o caminho da luz, comecei a ler sobre a bíblia Clean Code também por Robert C. Martin (alguém me chamou de fanboy?). Percebi o erro que cometi e fui falar com uns ex-colegas dessa empresa.

O que eles me falaram: "Aquilo é o cão pra entender".

Certamente, ninguém gosta de usar uma parada que não entende como funciona. Dado que eles não faziam ideia de como funcionava, aquela "belezura" foi mofando e jamais foi tocada, além de seu criador — acidez total nessa frase.

Escuta o tio Bob, o velho sabe o que fala:

This frequently happens when developers anticipate changes to the requirements and put facilities in the software to deal with those potential changes.

Needless Repetition

Confesso que esse tópico é bem polêmico pra mim.

Aqui tu pode levantar o braço e dizer: "Professora, professora, isso aí é o DRY, né?!"

É, é! Don't Repeat Yourself, pode se dizer que sim.

Mas antes de eu falar mer#$, vamos deixar o tio Robertinho dizer o que ele acha:

When there is redundant code in the system, the job of changing the system can become arduous. Bugs found in such a repeating unit have to be fixed in every repetition. However, since each repetition is slightly different from every other, the fix is not always the same.

O que ele diz ali, eu acredito sinceramente de coração que há das melhores intenções, MAS essas olheiras na minha cara dizem para você jovem programador: tome cuidado!

Não interprete isso e saia que nem um doido extraindo código supostamente duplicado. Ou melhor, não seja um cão farejador, procurando por um singelo código duplicado, para extraí-lo e se sentir o fodão por possuir o broche: Guardião do DRY.

Sinto cheiro de código duplicado fresco

Quando o sábio tio fala pra você não repetir código, eu, mero mortal, entendo que você deveria estar atento a regras de negócio duplicadas. Mas, quando você encontra essa situação, você não deve sair codando alucinado. Converse com outros devs, converse com o time de produto ou alguém que compreende do sistema mais do que você.

Por que te digo isso? Nem sempre código esteticamente parecido é igual. Sim, isso mesmo, você não deve extrair código que se parece esteticamente igual, e sim regra de negócio IGUAL duplicada. Quando você tem a regra de negócio extraída em apenas um lugar, aí sim você ganha de brinde o: mexer em apenas um lugar e corrigir nos demais.

Opacity

Por fim, chegamos ao último fedor, chamado opacidade. Esse assunto é bem curtinho, o cara só escreveu um livro por causa dele — Clean Code.

Esse é o tópico que mudou minha carreira. Que fez de mim o que sou hoje e o que me faz desejar ser no futuro.

Não é fácil escrever algo que você entenda e que os outros entendam, para que dure o tempo que precisar durar — na alegria ou na tristeza.

Lá no começo da minha carreira, eu codava sozinho praticamente. Era raro conversar com algum colega do lado. Era só eu e a minha máquina, com um fone de ouvido, música alta e muitas teclas por segundo. Me achava produtivo. Achava que estava entregando muito para a empresa.

Mas ao contrário, não estava colaborando com o crescimento do produto/empresa, estava simplesmente entregando algo temporário. Para um breve período de tempo o software teria algo bom do que eu fiz. Mas, com o passar dos anos aquilo não seria sustentável.

É incrível como um software de apenas 1 ano de idade pode tão rapidamente ser impossível de dar manutenção/evolução. Agora imagina que você cai num projeto desse e descobre que praticamente quase todo o time que o desenvolveu foi embora.

Mas e aí, como faço pra escrever código que os outros maluco entendam?

Comigo funcionou assim: meu código começou a ficar mais legível para os olhos dos outros quando os outros começaram a ler o meu código. Mas isso não depois de já estar em produção. Isso na fase de desenvolvimento. E como que fiz isso? Parei de ser um orgulhoso, de me achar melhor que os outros, de achar que meu código é intocável.

Começar a ouvir as sugestões dos outros é o primeiro passo para você melhorar a legibilidade do seu código.

Arregace as mangas

Na prática é fazer: 1) pair programming; 2) discutir domínio de negócio; 3) ter avaliadores na PR.

Agora, te garanto que não será tão simples no começo. Isso tudo é uma prática, e como a palavra já diz, isso precisará ser feito sempre, como uma evolução contínua.

No começo você e o seu pair vão discutir pra caramba, vão discordar, vão ficar puto um com outro — porque cada um tem um jeito de pensar.

Depois você vai querer discutir domínio de negócio e vai ver que você não conhecia quase nada do sistema. Vai ver que poderia ter chamado aquela variável de outro nome, pois faz mais sentido. Vai discutir com o time de produto ao ponto de pedir mais informações sobre o perfil do cliente, sobre o porque de fazer isso ou fazer aquilo.

E pra acabar, vai levar muita bocha (porrada) na PR, mas tanta porrada, que vai achar que não sabia programar antes disso.

Mas tudo isso será um grande aprendizado que irá te transformar num dev bem melhor. Melhor pra empresa e principalmente melhor para sua carreira.

Vai por mim, vai valer a pena o esforço

Se chegou até aqui, espero que pelo menos tenha se divertido.

Tive o privilégio em trabalhar com um time muito bala na agulha e lá tínhamos a cultura: free style bocha — ou seja, liberdade total em descer o cac$#, ops, em dar sua opinião sem ser reprimido/julgado. Portanto, deixe um comentário dizendo o que achou.

Meus sinceros agradecimentos a minha revisora particular Scarlett — minha esposa amada. E claro, aos meus amigos que contribuíram lendo: Hudolf, Modesto e Israel.

--

--

Gabriel Lima
Jurassic Park Hackers

desenvolvedor de software, gosta mais do back, mas consegue dar um tapa no front