Por qué el naming importa más de lo que creés
Una función llamada handle() no dice nada. ¿Qué maneja? ¿Errores? ¿Clicks? ¿Datos? El nombre es documentación inline. Si necesitás leer el cuerpo de la función para entender qué hace, el nombre falló. processPayment() es claro: procesa un pago. doStuff() es basura cognitiva.
Los verbos importan. Queries (lectura) usan get, find, fetch, query. Mutations (escritura) usan create, update, delete, add, remove. Validaciones retornan boolean: isValid, hasPermission, canEdit. Esta consistencia no es capricho, es comunicación de contrato.
El contexto del dominio define el verbo. En e-commerce, placeOrder() es más preciso que createOrder() porque comunica la acción del usuario. En sistemas de inventario, reserveStock() dice más que updateInventory(). El naming revela el modelo mental del negocio. Código legible es código que habla el idioma del problema que resuelve.
Convenciones que tu equipo debe respetar
Funciones booleanas empiezan con is, has, can, should. isActive(), hasPermission(), canEdit(). Nunca checkActive() o verifyPermission() que retornan boolean—esos verbos implican side effects. La convención previene sorpresas: si empieza con is, sabés que retorna boolean puro sin modificar estado.
Prefijos get vs fetch: get es sincrónico, acceso directo (ej: getProperty()). fetch implica operación asincrónica, red o I/O (ej: fetchUserData()). Esta distinción ayuda a anticipar si la función es costosa o instantánea. getUserName() devuelve string del objeto; fetchUserName() hace request HTTP.
Evitá sufijos redundantes: getUserData() es redundante si la función ya dice que retorna datos. Mejor getUser(). Misma lógica con sendEmailNotification()—sendEmail() alcanza si el contexto es claro. Menos palabras = más legibilidad, siempre que no sacrifiques claridad. El balance es difícil pero se logra iterando en code reviews.
Errores que delatan código junior
Funciones genéricas tipo handleData(), processInfo(), manageStuff(). Son banderas rojas. Si no podés ponerle nombre específico, la función probablemente hace demasiadas cosas. Refactoreá en funciones más pequeñas con responsabilidad clara. handleData() debería ser validateUserInput() + saveToDatabase() + sendConfirmationEmail(). Tres nombres claros, tres funciones unitarias.
Abreviaciones crípticas: updUsrPrf(). Esto no es código ensamblador de los 80. Los caracteres no cuestan dinero. updateUserProfile() es perfectamente legible. La única excepción: abreviaciones de dominio universales (HTML, URL, ID). Pero usr, prf, mgr son pereza que impacta mantenibilidad.
Inconsistencia: en un archivo usás getUserById(), en otro findUserById(), en otro retrieveUserById(). Tres verbos diferentes para la misma acción. Elegí uno y usalo en toda la codebase. Herramientas como ESLint con reglas custom pueden forzar convenciones. El naming debe ser aburrido y predecible, no creativo. Guardá la creatividad para arquitectura, no para sinónimos de 'obtener'.
Naming en contextos específicos de TypeScript
Funciones factory retornan objetos nuevos: createUser(), buildQuery(), makeRequest(). Nunca modifiquen argumentos. Si modificás, el nombre debe reflejarlo: addItemToCart(cart, item) sugiere mutación; withItemAdded(cart, item) sugiere inmutabilidad (retorna nuevo cart). El naming comunica si tu función es pura o tiene side effects.
Handlers de eventos: handleClick(), onSubmit(), processInput(). El prefijo handle u on indica que es callback. Callbacks de React hooks usan handle: handleChange, handleSubmit. Props que reciben callbacks usan on: onClick, onValueChange. Consistencia entre componentes evita confusión.
Funciones async siempre deberían sugerir asincronía en el nombre si no es obvio por contexto: fetchData() (obvio), loadConfig() (obvio). Pero getUser() sincrónico vs getUser() async causa bugs. Si la versión async existe junto a la sync, nombralas distinto: getUserSync() y fetchUser(), o getUser() sync y loadUser() async. El compilador no te salva de retornar Promise<User> cuando esperabas User si los nombres son idénticos.