22 puntos por GN⁺ 2024-09-04 | 5 comentarios | Compartir por WhatsApp
  • Al dar mantenimiento a una base de código desconocida, se invierte mucho tiempo en buscar cadenas de texto
  • Incluso en proyectos escritos por una sola persona, hay que buscar muchas cosas como nombres de funciones, mensajes de error y nombres de clases
  • Si algo no se puede buscar bien, existe el riesgo de no encontrar sus referencias en la base de código y considerarlo innecesario
  • A partir de esto, se derivan algunas reglas que pueden aplicarse para mantener la greppability de una base de código

No dividir identificadores

  • Dividir identificadores o construirlos dinámicamente no es una buena idea
  • Supongamos que hay dos tablas de base de datos llamadas shipping_addresses y billing_addresses; construir dinámicamente el nombre de la tabla según el tipo de pedido puede parecer buena idea
const getTableName = (addressType: 'shipping' | 'billing') => {  
    return `${addressType}_addresses`  
}  
  • Esto parece DRY, pero no es bueno para el mantenimiento. Si alguien busca el nombre de la tabla shipping_addresses en la base de código, podría pasar por alto esta parte
  • Es mejor hardcodear los identificadores
  • Código refactorizado para mejorar la capacidad de búsqueda:
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')  
}  
  • Lo mismo aplica a nombres de columnas, campos de objetos y nombres de métodos/funciones (en JavaScript es fácil construir nombres de métodos dinámicamente)

Usar el mismo nombre en todo el stack

  • No cambies nombres de campos en los límites de la aplicación solo para ajustarlos a una convención de nombres
  • Un ejemplo típico es tomar identificadores en snake_case al estilo PostgreSQL y convertirlos a camelCase en JavaScript, lo cual no es recomendable
  • Esto dificulta las búsquedas. Para encontrar todo, hay que buscar dos cadenas en lugar de una
const getAddress = async (id: string) => {  
    const address = await getAddressById(id)  
    return {  
        streetName: address.street_name,  
        zipCode: address.zip_code,  
    }  
}  
  • Es preferible devolver directamente el objeto
const getAddress = async (id: string) => {  
    return await getAddressById(id)  
}  

Mejor plano que anidado

  • Inspirado en el Zen de Python, al manejar espacios de nombres normalmente es mejor mantener una estructura plana que anidar carpetas u objetos
  • Si hay dos opciones para definir un archivo de traducciones:
{  
    "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",  
}  
  • Conviene elegir la segunda opción. Las claves se encuentran fácilmente y se pueden referenciar como t('auth.login.title')
  • Si pensamos en la estructura de componentes de React:
./components/AttributeFilterCombobox.tsx  
./components/AttributeFilterDialog.tsx  
./components/AttributeFilterRating.tsx  
./components/AttributeFilterSelect.tsx  
  • Se prefiere frente a una estructura como esta
./components/attribute/filter/Combobox.tsx  
./components/attribute/filter/Dialog.tsx  
./components/attribute/filter/Rating.tsx  
./components/attribute/filter/Select.tsx  
  • Desde la perspectiva de búsqueda, esto permite buscar el componente completo con su espacio de nombres, como AttributeFilterCombobox, en lugar de un nombre genérico como Dialog

Opinión de GN⁺

  • Esta entrada de blog explica bien la importancia de poder buscar identificadores al mantener una base de código
  • Construir identificadores dinámicamente o cambiar nombres en los límites de la aplicación dificulta el mantenimiento del código. Los identificadores deben ser consistentes y claros
  • En cambio, hardcodear identificadores y mantener planos los espacios de nombres es mejor desde la perspectiva de búsqueda
  • Vale la pena aplicar estos principios en los proyectos para mejorar la legibilidad y mantenibilidad del código
  • Además de las reglas propuestas por el autor, hay varias otras formas de elevar la calidad del código, como escribir Self-Documenting Code y usar comentarios significativos

5 comentarios

 
nowpark 2024-09-06

También dejo una herramienta que convierte a full path de JSON para hacerlo más fácil de buscar con grep.

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

 
botplaysdice 2024-09-05

Está bueno... greppability...

 
ahwjdekf 2024-09-04

Parece útil también procurar escribir la información útil, en lo posible, en una sola línea.

 
roxie 2024-09-09

Está bien.

 
GN⁺ 2024-09-04
Opiniones de Hacker News
  • Buscar símbolos como nombres de funciones y clases es limitado en comparación con usar herramientas que entienden la sintaxis del código

    • Con solo las funciones de "ir a la definición" y "buscar usos" ya se puede reducir mucho la necesidad de búsqueda de texto
    • Durante los últimos 10 años, principalmente solo he buscado cadenas visibles para el usuario
    • Publicaciones como esta implican que el autor debería invertir tiempo en aprender mejores herramientas adecuadas para su lenguaje
    • Un buen IDE por sí solo puede ahorrar mucho tiempo
  • Sería útil que las herramientas grep tuvieran un modo de "súper insensible a mayúsculas y minúsculas"

    • Por ejemplo, expandir una búsqueda como FooBar|first_name para que coincida con todas las variantes de mayúsculas y minúsculas
    • Es difícil imaginar una situación en la que esta función no debería ser la opción predeterminada
  • Apoyo la idea de la grepabilidad

    • En sueco realmente existen palabras como "grep-bar" o "grep-barhet"
    • "greppbar" significa "comprensible", y "greppbarhet" significa "posibilidad de ser comprendido"
  • Al diseñar Hamilton, el objetivo era hacer que las definiciones de funciones y sus usos descendentes fueran fáciles de encontrar con grep

    • En el mundo de las transformaciones de datos en Python, es fácil crear bases de código en las que grep no ayuda mucho
  • "greppable" no es una palabra o concepto que se use por sí solo

    • La he usado durante mucho tiempo como principio organizativo
    • Es una de las mejores formas de estructurar código
  • He visto un ejemplo complejo que usaba interpolación condicional de cadenas

    • Cuando me incorporé por primera vez al proyecto, tardé demasiado en encontrar en el código las tres palabras que veía en la UI
    • Después cambié todo esto a cadenas que se pudieran encontrar fácilmente con grep
  • Muchos estilos de programación y herramientas mantienen las constantes de cadena en una sola línea sin importar su longitud

    • Esto es para que puedas ver una cadena en la salida del programa y buscar esa misma cadena en el código
  • Rust, Javascript y Lisp facilitan la búsqueda porque ponen una palabra clave antes de la definición de la función

    • C no tiene esas palabras clave, así que solo se puede buscar por el nombre de la función
    • Algunas reglas de estilo de C dividen la definición en dos líneas para facilitar la búsqueda
  • Estoy de acuerdo con la buscabilidad del código, pero no con mantener el mismo nombre a través de límites distintos

    • Que un símbolo exista solo dentro de un dominio reduce la carga cognitiva
  • Que el código sea fácil de buscar está bien, pero el ejemplo aumenta deliberadamente la posibilidad de errores

    • Agregar condiciones a las cadenas introduce la posibilidad de desajustes entre la entrada y la salida
    • Aplanar diccionarios aumenta la probabilidad de errores tipográficos
    • Los errores tipográficos son comunes y, cuando se copian en múltiples bases de código, son difíciles de resolver