- 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
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
Está bueno... greppability...
Parece útil también procurar escribir la información útil, en lo posible, en una sola línea.
Está bien.
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
Sería útil que las herramientas
greptuvieran un modo de "súper insensible a mayúsculas y minúsculas"FooBar|first_namepara que coincida con todas las variantes de mayúsculas y minúsculasApoyo la idea de la grepabilidad
Al diseñar Hamilton, el objetivo era hacer que las definiciones de funciones y sus usos descendentes fueran fáciles de encontrar con grep
"greppable" no es una palabra o concepto que se use por sí solo
He visto un ejemplo complejo que usaba interpolación condicional de cadenas
Muchos estilos de programación y herramientas mantienen las constantes de cadena en una sola línea sin importar su longitud
Rust, Javascript y Lisp facilitan la búsqueda porque ponen una palabra clave antes de la definición de la función
Estoy de acuerdo con la buscabilidad del código, pero no con mantener el mismo nombre a través de límites distintos
Que el código sea fácil de buscar está bien, pero el ejemplo aumenta deliberadamente la posibilidad de errores