Identificando a complexidade

Todo código é complexo. A complexidade é uma batalha contra a qual todos nós devemos lutar diariamente.

É claro que o seu código é ótimo, não é mesmo? É o código das outras pessoas que é complexo.

Bem, não. Nem sempre. Admita.

É muito fácil escrever algo complicado.

Isso acontece quando você não está prestando atenção. Acontece quando você não planeja com antecedência suficiente. Acontece quando você começa a trabalhar em um problema “simples”, mas logo descobre tantos casos que seu algoritmo simples cresce a ponto de parecer um labirinto, pronto para aprisionar um programador desavisado.

Suponha que você tenha começado a trabalhar em um sistema vasto. E você descobre que a estrutura de classe da fera é como a imagem mostrada a seguir:

Simples

Três classes inteiras! Esse sistema é complexo ou não?

Em certo nível, ele não parece nem um pouco complicado. Há somente três partes! Como isso poderia ser difícil de entender? E o design do software tem a vantagem adicional de se parecer com o Mickey Mouse, portanto deve ser bom.

Parece ser um design maravilhosamente simples. Você poderia descrevê-lo para alguém em segundos.

É claro, porém, que cada uma dessas partes será tão grande e densa, presumivelmente com muitas interconexões e lógica macarrônica, que provavelmente será quase impossível trabalhar com elas. Portanto, é quase certo que esse seja um sistema muito complexo oculto por trás de um design simplista.

Evidentemente, uma estrutura melhor (uma que seja mais fácil de entender e de manter) consideraria essas três seções como “módulos”, subdividindo-as em outras partes: pacotes, componentes, classes ou qualquer que seja a abstração que faça sentido. Seria algo mais parecido com a imagem a seguir:

Complexo

De imediato, essa imagem parece ser melhor.

Ela parece ter vários componentes pequenos conectados em um todo mais amplo. Portanto mais fáceis de compreender e provavelmente mais simples. Nosso cérebro foi criado para dividir os problemas em hierarquias como essa e raciocinar sobre os problemas quando estiverem assim, abstraídos.

As consequências de um design como esse são:

  • Melhor compreensão e mais capacidade de modificação
  • Você pode trabalhar em uma parte da funcionalidade do sistema ao identificar a menor parte relacionada a ela
  • Em vez de arregaçar as mangas e mergulhar em uma única classe gigantesca
  • Preferimos ter classes com mais coesão, que façam bem várias tarefas pequenas - de preferência, somente uma.