22 pontos por GN⁺ 2024-09-04 | 5 comentários | Compartilhar no WhatsApp
  • Ao dar manutenção em uma base de código desconhecida, gasta-se muito tempo procurando strings
  • Mesmo em projetos feitos por uma única pessoa, é preciso buscar muitas coisas, como nomes de funções, mensagens de erro e nomes de classes
  • Se a busca não funciona bem, há o risco de não encontrar referências na base de código e considerar algo como desnecessário
  • A partir disso, foram extraídas algumas regras que podem ser aplicadas para manter a Greppability da base de código

Não divida identificadores

  • Dividir identificadores ou montá-los dinamicamente não é uma boa ideia
  • Suponha que existam duas tabelas de banco de dados chamadas shipping_addresses e billing_addresses; montar dinamicamente o nome da tabela de acordo com o tipo de pedido pode parecer uma boa ideia
const getTableName = (addressType: 'shipping' | 'billing') => {  
    return `${addressType}_addresses`  
}  
  • Isso parece DRY, mas não é bom para manutenção. Alguém pode deixar passar esse trecho ao procurar pelo nome da tabela shipping_addresses na base de código
  • Hardcode dos identificadores é uma abordagem melhor
  • Código refatorado para melhorar a capacidade de busca:
const getTableName = (addressType: 'shipping' | 'billing') => {  
    if (addressType === 'shipping') {  
        return 'shipping_addresses'  
    }  
    if (addressType === 'billing') {  
        return 'billing_addresses'  
    }  
    throw new TypeError('addressType must be billing or shipping')  
}  
  • O mesmo vale para nomes de colunas, campos de objetos e nomes de métodos/funções (em JavaScript, é fácil montar dinamicamente nomes de métodos)

Use o mesmo nome em toda a stack

  • Não renomeie campos nos limites da aplicação apenas para se adequar a uma convenção de nomenclatura
  • Um exemplo típico é trazer identificadores em snake_case do PostgreSQL para o JavaScript e convertê-los para camelCase, o que não é uma boa ideia
  • Isso dificulta a busca. Para encontrar tudo, é preciso pesquisar duas strings em vez de uma
const getAddress = async (id: string) => {  
    const address = await getAddressById(id)  
    return {  
        streetName: address.street_name,  
        zipCode: address.zip_code,  
    }  
}  
  • Em vez disso, é melhor retornar o objeto diretamente
const getAddress = async (id: string) => {  
    return await getAddressById(id)  
}  

Flat é melhor do que aninhado

  • Inspirado no Zen of Python, ao lidar com namespaces, na maioria dos casos é melhor deixá-los flat do que aninhar estruturas de pastas/objetos
  • Se houver duas opções para configurar arquivos de tradução:
{  
    "auth": {  
        "login": {  
            "title": "Login",  
            "emailLabel": "Email",  
            "passwordLabel": "Password",  
        },  
        "register": {  
            "title": "Register",  
            "emailLabel": "Email",  
            "passwordLabel": "Password",  
        }  
    }  
}  
{  
    "auth.login.title": "Login",  
    "auth.login.emailLabel": "Email",   
    "auth.login.passwordLabel": "Password",  
    "auth.register.title": "Login",  
    "auth.register.emailLabel": "Email",  
    "auth.register.passwordLabel": "Password",  
}  
  • É melhor escolher a segunda opção. As chaves ficam fáceis de encontrar e podem ser referenciadas como t('auth.login.title')
  • Ao pensar na estrutura de componentes React:
./components/AttributeFilterCombobox.tsx  
./components/AttributeFilterDialog.tsx  
./components/AttributeFilterRating.tsx  
./components/AttributeFilterSelect.tsx  
  • Isso é preferível a uma estrutura como esta
./components/attribute/filter/Combobox.tsx  
./components/attribute/filter/Dialog.tsx  
./components/attribute/filter/Rating.tsx  
./components/attribute/filter/Select.tsx  
  • Do ponto de vista da busca, é possível procurar pelo componente completo com namespace, como AttributeFilterCombobox, em vez de um nome genérico como Dialog

Opinião do GN⁺

  • Este post de blog explica bem a importância de buscar identificadores ao dar manutenção em uma base de código
  • Montar identificadores dinamicamente ou renomear itens nos limites da aplicação dificulta a manutenção do código. Os identificadores devem ser consistentes e claros
  • Em vez disso, fazer hardcode dos identificadores e manter os namespaces flat é melhor do ponto de vista da busca
  • Vale aplicar esses princípios no projeto para aumentar a legibilidade e a manutenibilidade do código
  • Além das regras propostas pelo autor, há várias outras formas de melhorar a qualidade do código, como escrever Self-Documenting Code e usar comentários significativos

5 comentários

 
nowpark 2024-09-06

Converta para o caminho completo do json; também vou deixar uma ferramenta que torna isso greppable!

https://pt.news.hada.io/topic?id=3159

 
botplaysdice 2024-09-05

Legal... greppability, hein...

 
ahwjdekf 2024-09-04

Também parece útil colocar informações úteis em uma única linha sempre que possível.

 
roxie 2024-09-09

Legal

 
GN⁺ 2024-09-04
Opiniões do Hacker News
  • Pesquisar símbolos como nomes de funções e classes é inferior a usar ferramentas que entendem a sintaxe do código

    • Só os recursos de "ir para a definição" e "encontrar usos" já podem reduzir muito a necessidade de busca por texto
    • Nos últimos 10 anos, tenho pesquisado principalmente apenas strings visíveis ao usuário
    • Postagens como esta significam que o autor deveria investir tempo em aprender ferramentas melhores para sua linguagem
    • Só um bom IDE já pode economizar muito tempo
  • Seria útil se a ferramenta grep tivesse um modo de "super insensível a maiúsculas e minúsculas"

    • Por exemplo, expandir uma busca como "FooBar|first_name" para corresponder a todas as variações de caixa
    • É difícil imaginar uma situação em que esse recurso não devesse ser o padrão
  • Apoio a ideia de greppability

    • Em sueco, palavras como "grep-bar" ou "grep-barhet" realmente existem
    • "greppbar" significa "compreensível", e "greppbarhet" significa "possibilidade de ser compreendido"
  • Ao projetar o Hamilton, o objetivo era facilitar o grep de definições de funções e seus usos descendentes

    • No mundo das transformações de dados em Python, é fácil criar codebases em que o grep não ajuda muito
  • 'greppable' não é uma palavra/conceito usado por si só

    • Tenho usado isso como princípio organizacional há muito tempo
    • É uma das melhores formas de estruturar código
  • Já vi um exemplo complexo usando interpolação condicional de strings

    • Quando entrei no projeto pela primeira vez, levei tempo demais para encontrar três palavras que vi na UI
    • Depois, mudei tudo para strings que pudessem ser facilmente encontradas com grep
  • Muitos estilos de programação e ferramentas mantêm constantes de string em uma única linha, independentemente do comprimento

    • Isso é para que você possa ver uma string na saída do programa e procurar a mesma string no código
  • Rust, Javascript e Lisp colocam uma palavra-chave antes da definição de função, o que facilita a busca

    • C não tem essas palavras-chave, então só é possível pesquisar pelo nome da função
    • Algumas regras de estilo em C dividem a definição em duas linhas para facilitar a busca
  • Concordo com greppability, mas sou contra manter o mesmo nome ao atravessar fronteiras

    • Ter um símbolo existindo apenas em um único domínio reduz a carga cognitiva
  • A possibilidade de pesquisar o código é boa, mas os exemplos aumentam deliberadamente a chance de erro

    • Adicionar condicionais em strings cria a possibilidade de inconsistência entre entrada e saída
    • Achatar dicionários aumenta a chance de erros de digitação
    • Erros de digitação são comuns e, quando copiados para vários codebases, são difíceis de corrigir