Diminuindo a Complexidade Cognitiva na Programação

Eu dedico muito tempo e esforço para diminuir a complexidade cognitiva ao programar.

Complexidade cognitiva é o quanto se precisa pensar para realizar uma tarefa. Pequenos detalhes podem tornar uma tarefa desnecessariamente complexa.

Por exemplo, encontrar um trecho de código escondido em muitos arquivos dentro de uma grande estrutura de diretórios exige esforço. Mesmo que a estrutura seja familiar e bem projetada, o objetivo não é navegar por ela abrindo arquivos até encontrar o código para editar; o objetivo é apenas editar o código. Qualquer coisa além disso é esforço cognitivo desperdiçado.

Diminuir esse esforço é importante para mim porque agiliza meu trabalho e o torna mais agradável. Além disso, quando outras pessoas me assistem programar, nada é tão maçante quanto me ver navegando pelo código até encontrar o que procuro.

Coisas que diminuem a complexidade cognitiva para programadores:

  • Editor bem configurado: um editor com recursos como “ir para definição” e a capacidade de alternar rapidamente entre arquivos abertos. Preferencialmente, isso deve ser feito com uma tecla de atalho simples, sem precisar trocar do teclado para o mouse e clicar em abas ou menus, pois cada ação extra adiciona complexidade. No meu caso, uso o Neovim configurado para que, no modo normal, a tecla Enter salte para a definição e Backspace retorne para onde eu estava.
  • Mensagens de erro claras: adicionar o nome da função ou um código específico nos logs e mensagens de erro facilita a localização. Assim, é mais simples pesquisar pelo texto da mensagem e encontrar onde ocorreu. Isso ajuda muito, pois não preciso lembrar o nome do arquivo, indo direto ao código que precisa ser analisado.
  • Bons nomes e padronização: criar bons nomes para as várias partes do código e padronizar nomes entre os membros da equipe. Embora seja desafiador, essa prática ajuda significativamente.
  • Padronização de recursos: nomes de servidores e configurações também precisam ser padronizados. Já tive problemas para entender o que precisava ser feito porque não havíamos definido o nome de um servidor. Cada hora ele era chamado de uma forma diferente: uma vez pelo nome do projeto, outra pelo nome de um dos serviços rodando nele.

Encontrando código facilmente

Muitos programadores centralizam seu trabalho ao redor do editor de texto, seja usando uma IDE pronta como o Visual Studio Code ou equipando o Vi com vários plugins, transformando-o efetivamente em uma IDE.

Eu prefiro outra abordagem: considero o terminal como minha IDE. Ele é responsável por gerir arquivos e navegar nos diretórios, enquanto o editor cuida de editar e navegar no código já aberto. Por isso, não uso plugins que geram árvores para navegação, por exemplo.

No lugar disso, uso scripts como o seguinte:

#!/usr/bin/env bash

RG_PREFIX="rg \
    --color=always \
    --column \
    --follow \
    --glob '!{.git,node_modules}/*' \
    --hidden \
    --line-number \
    --no-heading \
    --smart-case \
    --sort=modified"
INITIAL_QUERY="${*:-}"
IFS=: read -ra selected < <(
    FZF_DEFAULT_COMMAND="$RG_PREFIX $(printf %q "$INITIAL_QUERY")" \
    fzf --ansi \
        --bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
        --delimiter : \
        --disabled \
        --preview 'bat --color=always {1} --highlight-line {2}' \
        --preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
        --query "$INITIAL_QUERY"
)
[ -n "${selected[0]}" ] && \
    $EDITOR "${selected[0]}" "+${selected[1]}" && \
    echo "${selected[0]}" "+${selected[1]}"

Código fonte

Esse script utiliza uma combinação de utilitários (fzf, rg e bat) para criar uma ferramenta que me permite inspecionar múltiplos arquivos e encontrar rapidamente o código que procuro, com a possibilidade de usar expressões regulares caso uma string não seja suficiente.

Ele permite visualizar os arquivos rapidamente sem precisar carregar o editor, evitando assim plugins desnecessários ou deixar arquivos abertos sem motivo. Quando o código é encontrado, basta pressionar Enter para abri-lo no editor.

Ao final da edição, ele deixa um log na tela mostrando qual arquivo foi editado e quais linhas, já no formato esperado como parâmetros para o Neovim. Dessa forma, tenho um registro rápido de qual arquivo e em qual linha eu estava, podendo retornar rapidamente.

Script para buscar código fonte

Também uso uma variação desse script para abrir arquivos em loop, permitindo que eu edite vários arquivos rapidamente em sequência:

#!/usr/bin/env bash

RG_PREFIX="rg \
    --color=always \
    --column \
    --follow \
    --glob '!{.git,node_modules}/*' \
    --hidden \
    --line-number \
    --no-heading \
    --smart-case \
    --sort=modified"

while true; do
  # Recebe a consulta inicial, se houver
  INITIAL_QUERY="${*:-}"
  IFS=: read -ra selected < <(
    FZF_DEFAULT_COMMAND="$RG_PREFIX $(printf %q "$INITIAL_QUERY")" \
    fzf --ansi \
        --bind "change:reload:sleep 0.1; $RG_PREFIX {q} || true" \
        --delimiter : \
        --disabled \
        --preview 'bat --color=always {1} --highlight-line {2}' \
        --preview-window 'up,60%,border-bottom,+{2}+3/3,~3' \
        --query "$INITIAL_QUERY"
  )

  # Se nenhum arquivo foi selecionado, encerra o loop
  [ -z "${selected[0]}" ] && break

  $EDITOR "${selected[0]}" "+${selected[1]}"
  echo "${selected[0]}" "+${selected[1]}"
done

Código fonte

Esse script é útil quando preciso editar vários arquivos rapidamente, como quando estou refatorando um código ou corrigindo um bug que afeta vários arquivos que podem ser localizados com a mesma expressão regular. Isso é bem comum, porque muitas vezes você não quer apenas um “localizar e substituir”, existem pequenas diferenças que precisam ser ajustadas manualmente em cada arquivo.

Tenho vários outros scripts e configurações que uso para me ajudar a diminuir a complexidade cognitiva. Vou escrever sobre eles nos próximos artigos.

Essas ideias não são exclusivamente minhas; você pode encontrar muito material sobre complexidade cognitiva, carga cognitiva, esforço cognitivo e temas relacionados.

Também é interessante ler sobre complexidade ciclomática para tornar seu código mais fácil de entender.

Cesar Gimenes

Última modificação