Texto

camelCase, snake_case y kebab-case: cuál va en cada lugar

Tres convenciones de nombres y una regla para elegir entre ellas: decide el contexto, no tu gusto.

El contexto elige por ti, no tu gusto. camelCase (userName) nombra variables y funciones en JavaScript, Java, Kotlin y Swift. snake_case (user_name) nombra variables y funciones en Python, Ruby y Rust, y columnas en SQL. kebab-case (user-name) va en cualquier lugar que no sea un identificador de programa — URLs, nombres de clase CSS, atributos HTML, nombres de archivo, paquetes de npm — porque en casi todos los lenguajes el guion es el operador de resta y user-name se interpreta como user menos name.

Las excepciones son pocas: la familia Lisp usa guiones para todo, C# escribe sus métodos con mayúscula inicial y Go convierte la primera letra en un modificador de acceso. Ninguna de esas es la que te cuesta tiempo. La que cuesta es el punto de contacto entre un back end en snake_case y un front end en camelCase.

¿Cómo se ve cada convención?

Tres es el número equivocado. Las dos convenciones por las que no preguntaste viven en los mismos archivos que las tres por las que sí.

ConvenciónEjemploDónde va
camelCasetotalItemCountVariables, funciones y claves JSON en JavaScript, Java, Kotlin y Swift
PascalCaseTotalItemCountClases, tipos y componentes de React en casi todas partes
snake_casetotal_item_countIdentificadores de Python, Ruby y Rust; tablas y columnas de SQL
CONSTANT_CASETOTAL_ITEM_COUNTConstantes y variables de entorno, en casi cualquier lenguaje
kebab-casetotal-item-countURLs, clases CSS, atributos HTML, nombres de archivo, nombres de paquete

¿Qué convención espera mi lenguaje?

La mayoría están escritas en algún documento, lo que significa que la discusión ya está resuelta y te la puedes ahorrar.

Cuando un repo ya tiene una convención, síguela aunque sea la que menos te gusta. Un código consistentemente pasado de moda se lee mejor que uno convertido a medias.

Las constantes son el caso casi universal

Las mayúsculas con guiones bajos para constantes valen en toda esa lista salvo en Go, que nombra las constantes en MixedCaps como todo lo demás — MaxRetries, no MAX_RETRIES. Las variables de entorno son lo más parecido a una regla absoluta: las shells, los runtimes de contenedores y todas las herramientas alrededor de los archivos .env dan por hecho mayúsculas con guiones bajos. Un nombre de variable de entorno en minúsculas normalmente funciona y aun así parece un error a quien lo vea después.

Por qué kebab-case no puede ser un nombre de variable

Porque el guion ya es el signo de menos. Escribe user-name = 5 en JavaScript y el parser lee una resta entre una variable llamada user y otra llamada name, y después se niega a asignar al resultado: Invalid left-hand side in assignment. Ponle let delante y falla un paso antes, en el guion mismo. Python responde cannot assign to expression. Java, C#, Go, Rust, PHP y SQL lo rechazan por la misma razón. Esa es toda la historia: kebab-case queda confinado a los lugares donde nada intenta evaluar una expresión.

Hay dos excepciones reales. La familia Lisp — Clojure, Scheme, Emacs Lisp — usa kebab-case para todo, que es por lo que al estilo a veces se le llama lisp-case; el reader de esos lenguajes no trata un guion suelto como un operador. Y las custom properties de CSS se escriben --brand-colour, con guiones incluidos, porque CSS tampoco está evaluando aritmética sobre identificadores.

Dónde kebab-case es la respuesta correcta

¿Qué pasa donde se encuentran dos convenciones?

Dentro de un mismo código, las convenciones son una cuestión de estilo. El costo aparece donde se encuentran dos: un servicio en Python con snake_case, un front end en JavaScript con camelCase y un payload JSON pasando entre los dos. Algo tiene que convertir, y la forma de fallar es que todo el mundo convierta un poco, en lugares distintos, hasta que la mitad de tus objetos llevan created_at y createdAt a la vez y ninguno de los dos se llena de forma confiable.

Elige una capa — el serializador, normalmente — y convierte ahí y en ningún otro lado. La guía de estilo JSON de Google recomienda camelCase para los nombres de propiedad, que es un valor por defecto razonable si no tienes otra restricción, pero la elección importa mucho menos que hacerla una sola vez.

SQL merece su propia advertencia. Los identificadores sin comillas se convierten a una sola caja — el estándar los pasa a mayúsculas, PostgreSQL los pasa a minúsculas — así que una columna que creas como createdAt en realidad se llama createdat. Ponle comillas dobles al crearla y la mayúscula sobrevive, pero entonces todas las consultas que la toquen tienen que ponerle comillas también, para siempre, y olvidarlo una vez es un error, no una errata. snake_case es la convención ahí porque sale de esa conversión sin cambios.

¿Cómo convierto un nombre de una convención a otra?

Renombrar a mano es de donde salen las erratas. Un convertidor de mayúsculas y minúsculas toma un nombre y te devuelve el mismo nombre en camelCase, PascalCase, snake_case, CONSTANT_CASE o kebab-case, que es la forma rápida de mover un identificador de un lenguaje a otro. Corre en el navegador, así que pegar ahí nombres de variables internas no los manda a ningún lado.

Vale la pena conocer dos límites antes de confiar en el resultado. Los acrónimos lo derrotan, y derrotan a todos los conversores de propósito general por la misma razón: la separación depende de una letra minúscula seguida de una mayúscula, y HTTPResponse no tiene ese límite. Te da httpresponse, no http_response; parseXMLFile se convierte en parse_xmlfile. Si tus nombres llevan acrónimos, lee el resultado antes de pegarlo de vuelta.

Las convenciones de programación tratan toda la caja de texto como un solo identificador. Mayúsculas, minúsculas, Title Case y Sentence case funcionan sobre un párrafo, pero camelCase, snake_case y kebab-case colapsan todo lo que pegues — saltos de línea incluidos — en un único nombre. A esos dales un identificador por vez.

¿Cómo renombro una convención en todo un proyecto?

La tentación es un buscar y reemplazar general, y el peligro no es el que la gente espera. La coincidencia de palabra completa evita que userName coincida dentro de userNames. Lo que no evita es que el reemplazo caiga dentro de un string literal, un comentario, una consulta SQL o la clave de un payload de API — así que un renombrado que iba a ser cosmético cambia en silencio el formato de los datos que viajan. Pasar por un reemplazo que lista cada coincidencia con su número de línea antes de comprometerte hace visibles esos casos mientras todavía son baratos.

Ese funciona sobre un bloque de texto que pegas, y lista las primeras cien coincidencias. Sirve para un solo archivo que vas a pegar de vuelta, no para una pasada sobre cien archivos. Para eso quieres sed o la búsqueda en todo el proyecto de tu editor — la misma disciplina: lee las coincidencias antes de reemplazarlas.

Después, lee el diff en vez de la salida de los tests. Comparar el antes y el después lado a lado detecta las tres líneas que no querías tocar más rápido que una suite de tests que solo cubre los caminos en los que pensaste.

¿Importa algo de esto?

Para la corrección no, y para el rendimiento tampoco. Importa para el grep: nombres consistentes significan que una sola búsqueda encuentra todas las apariciones, mientras que los inconsistentes significan que encuentras casi todas y el resto te muerde después. Hay trabajos académicos que comparan qué tan rápido lee la gente snake_case y camelCase, y no zanjan nada: los estudios son pequeños y sus resultados se contradicen entre sí, así que no es una base sólida para decidir. La consistencia es el beneficio que sí puedes observar. Todo lo demás es preferencia disfrazada de principio.

Para la parte mecánica — un nombre, cinco convenciones, nada de tipear — el convertidor de mayúsculas y minúsculas lo resuelve en el navegador, incluidos los modos Title Case y Sentence case que no tienen nada que ver con código. Solo recuerda que colapsa todo lo que pegues en un único identificador cuando eliges una de las convenciones de programación.

Si estás aquí porque una convención tiene que cambiar en todo un proyecto, el renombrado en sí es la parte riesgosa. Los errores que convierten un buscar y reemplazar en una hora de limpieza cubre lo que sale mal dentro de strings, comentarios y coincidencias parciales, que es exactamente donde un renombrado de convención hace su daño.

Preguntas frecuentes

¿Cuál es la diferencia entre camelCase y snake_case?

camelCase une las palabras poniendo en mayúscula cada una menos la primera, como en userName. snake_case las une con guiones bajos y deja todo en minúsculas, como en user_name. Ninguna es mejor; marcan a qué comunidad de lenguaje pertenece el código, con camelCase como estándar en JavaScript, Java y Swift, y snake_case como estándar en Python, Ruby y Rust.

¿Puedo usar kebab-case para un nombre de variable?

En la mayoría de los lenguajes, no. El guion es el operador de resta, así que user-name se interpreta como user menos name y la línea no compila. Las excepciones son la familia Lisp, incluidos Clojure y Scheme, donde kebab-case es el estilo normal, y las custom properties de CSS como --brand-colour.

¿Qué convención debo usar para las URLs?

kebab-case en minúsculas. Google trata los guiones de una URL como separadores de palabras y lleva años recomendándolos por encima de los guiones bajos. Las minúsculas además evitan problemas de contenido duplicado en servidores que tratan las rutas distinguiendo mayúsculas de minúsculas.

¿Las claves JSON deben ir en camelCase o en snake_case?

Cualquiera de las dos funciona, y la consistencia importa más que la elección. La guía de estilo JSON de Google recomienda camelCase, que es un valor por defecto sensato para una API que se consume desde JavaScript. Si tu API es la cara pública de un servicio en Python o Ruby, las claves en snake_case coincidirán con el resto de tu documentación y te ahorrarán una capa de conversión.

¿Cómo convierto camelCase a snake_case?

Separa el nombre en cada punto donde una letra minúscula va seguida de una mayúscula, pasa todo a minúsculas y únelo con guiones bajos. Las herramientas automáticas lo hacen de forma confiable salvo con los acrónimos: HTTPResponse no tiene ese límite, así que se convierte en httpresponse y no en http_response. Revisa a mano cualquier nombre que contenga un acrónimo.

¿Es más legible snake_case o camelCase?

Hay investigación sobre esto y no llega a una respuesta clara; los estudios son pequeños y sus resultados se contradicen. En la práctica la legibilidad viene de la consistencia dentro de un proyecto y de nombres que describan la cosa, no del separador. Usa lo que ya usan el lenguaje y el código existente.

Última actualización 19 de septiembre de 2026