Qué es exactamente un nombre — Parte I: La búsqueda

Estamos todos de acuerdo: un buen nombre es siempre lo más importante. ¡A buscarlos!

Maximiliano Contieri
DotTech
8 min readAug 16, 2020

--

Photo by Aaron Burden on Unsplash

Todos utilizamos nombres para programar, no importa si el lenguaje es de alto o bajo nivel, o si es Imperativo, Funcional o de Objetos. Los nombres están por todos lados. Pero seguimos utilizándolos mal. En esta primera parte veremos cómo encontrarlos.

Solo hay dos cosas difíciles en informática: invalidar un caché y nombrar cosas. — Phil Karlton

¿Qué hay en una rosa, más que su nombre?

Traducción del inglés: “Una rosa, con cualquier otro nombre, olería igualmente dulce” es una referencia popular a la obra de William Shakespeare: Romeo y Julieta.

Foto por Evie Fjord en Unsplash

El Problema

El código se lee muchas más veces de lo que se escribe. Las primeras lecturas las realiza el desarrollador que elige los nombres. Posteriormente, si el código sobrevive, muchas otras personas realizarán sus propias interpretaciones a partir de las huellas dejadas por el nominador.

Los nombres pierden el sentido rápidamente

Los nombres son muy importantes. Indican el rol que une a los objetos con su correspondiente ente real en MAPPER.

A través de dicha relación biyectiva conoceremos a quién está representando en el mundo real.

Los nombres se crean por y para los seres humanos. A los compiladores les da exactamente lo mismo el nombre que le asignemos a un objeto, clase, variable, interfaz, trait etc.

Foto por Erhan Astam en Unsplash

Los nombres están ahí afuera

Una única regla rige nuestros diseños:

Siempre cumplir con la biyección de nuestro MAPPER.

Esto se replica en el caso particular de los nombres. Al buscar una responsabilidad en el mundo real obtendremos el nombre de la función que le asignaremos a nuestros objetos del modelo computable.

El contexto es rey

Modelo de Star Wars

Todos los nombres son contextuales. (¡alerta de spoilers!)

  • Darth Vader es el padre de Leia.
  • Leia es la madre de Kylo Ren.
  • Kylo Ren es el nieto de Darth Vader
starwars.php
Modelo de Dark

Una misma hija puede ser madre e hija porque son roles. (más spoilers)

dark.php
  • Para Charlotte, Elizabeth es su madre (un rol).
  • Para Elizabeth, Charlotte es su madre (un rol).
  • Para Charlotte, Charlotte es su abuela (un rol).

Existe una tendencia en la industria a poner nombres a partir del tipo (o la clase) de un objeto. Esto es una pésima decisión que genera asunciones ocultas y, por lo tanto, acoplamiento.

Estas decisiones invisibles atentan contra el principio de sustitución e impiden el polimorfismo, por haber acoplado el nombre al tipo que esperamos.

El hecho de que seamos todos seres humanos no significa que deba existir una variable $human referenciándonos.

humans.php
  • Regla 1: El rol es contextual y temporal
  • Corolario 1: No debemos asignar nombres relacionados al tipo o clase.

Para nombrar objetos hay que pensar en el rol que cumplen en el contexto en que está siendo nombrados (esencial) y ver más allá del tipo de ente físico (accidental).

Números en la biyección
  • 1 representa al número natural 1.
  • 3 representa al número natural 3.
  • 1/3 representa a la fracción 1/3.
fractions.php

Ser numerador o denominador son roles. Ser una proporción también. En ningún momento utilizamos nombres como fracción o entero (accidentales) que nos acoplan al tipo.

A este concepto también se lo denomina: intention revealing naming.

El espacio es el límite

Gran parte de los problemas actuales del desarrollo de software están vinculados a costumbres arraigadas que no tienen razón de ser en la actualidad. Muchas de ellas están asociadas a optimizaciones prematuras.

Hoy en día existen desarrolladores que nombran a las variables ahorrando espacio como en los años 60s.

El lugar ocupado por el nombre de una variable no influye en ningún aspecto de la eficiencia de los sistemas.

Bucle en ensamblador

La ciencia de la computación nació de la madre de las ciencias (la matemática). En matemática es buena costumbre asignar variables de una sola letra (i, j, x, y).

El concepto de referencia surgió a partir de la variable.

Mucha gente se preguntó por qué los matemáticos pueden trabajar con esas variables cortas y los informáticos en cambio, no podemos.

Para los matemáticos, una vez introducidas en una fórmula, las variables pierden toda semántica y se tornan indistinguibles.

Es tiempo de emanciparnos, salir del hogar materno y evolucionar.

Photo por Pablo Heimplatz en Unsplash
  • Regla 2: Elegir nombres declarativos, suficientemente largos pero minimales
  • Corolario 2: Los nombres de las variables deberán estar compuestos por la suficiente cantidad de palabras que distingan unívocamente el concepto y rol. Si al sacar una palabra se pierde la unicidad, entonces el conjunto es minimal.

Abreviar genera acoplamiento

Mi experiencia como programador comenzó en la época de Ms-Dos. Los nombres de archivo tenían formato ‘8.3’.

8 letras para el nombre, 3 para la extensión.

Codificar los nombres de archivo en épocas de espacio reducido era todo un arte. Existen heurísticas como: sacar vocales, reemplazar letras etc.

Norton Commander 5

La memoria en los programas era extremadamente escasa y la implementación de los mapas de variables, así como el código fuente, ocupaban preciado espacio de memoria.

Esto ya no es así. Sin embargo, contagiamos malos hábitos a las generaciones posteriores que se comportan como los monos rociados, conservando una pésima costumbre únicamente por inercia.

Si abreviamos los nombres, generamos acoplamiento con esa abreviatura (que no es biyectiva) y otro acoplamiento entre el nombre y su abreviatura.

La variable i, ¿Representa un índice?, ¿Quizá un iterador? ¿O un integer ?

La biyección se rompe con las abreviaturas

¿Qué rol cumple esta referencia? ¿en qué década fue programada?

Abreviar genera un indirección innecesaria y rompe la biyección. Una misma abreviatura podría querer referenciar a dos objetos distintos.

La decisión acerca de cuál representa está acoplada y genera efecto de onda.

  • Regla 3: Los nombres serán, por norma general, largos.

Ante la duda, un nombre sin sentido

Si todavía no tenemos la madurez en el estudio del modelo como para encontrar el nombre apropiado en la biyección, debemos ponerle un nombre realmente molesto.

Un nombre mediocre quedará para siempre hasta que un desarrollador responsable tome coraje y lo refactorice.

Un pésimo nombre pide a gritos ser reconocido como deuda técnica y reflexionar.

  • Regla 4: Ante un conocimiento incompleto poner nombres pésimos.

Los malos nombres piden una refactorización

Es sumamente difícil modificar un sistema manteniendo malos nombres.

Por ejemplo, a continuación tenemos un fragmento de código que se utiliza en entrevistas de trabajo con el objetivo de encontrar un error:

Código hanoi

El primer paso para atacar este problema es entender qué representan las variables. Luego de una buena asignación de nombres. Así, encontrar el error es mucho más sencillo.

Un pésimo nombre está ahí molestando, llamando la atención y haciéndonos reflexionar sobre un cambio necesario.

Un mal nombre nos da una falsa sensación de tener un concepto maduro. No hay peor cosa que una mala abstracción escrita en piedra.

  • Regla 5: Modificar los pésimos nombres cuando conozcamos suficientemente el dominio.

Un buen nombre es lo último que aprenderemos

La escuela de pensamiento wittgenstetiana nos enseña que los seres humanos aprendemos a generalizar a partir de unos cuantos ejemplos.

El poder del cerebro para crear abstracciones es increíble.

Los programadores solemos ir más allá e intentamos generalizar a partir de un único ejemplo. Haciendo una analogía con la biología, sería como definir mamífero des de conocer al primer león.

Los IDEs van incluso más allá y nos piden generalizar sin haber construido ningún ejemplo, al obligarnos a poner nombre a una clase sin haber conocido ninguna instancia ni haber definido sus responsabilidades.

Generalizar lleva tiempo para la observación y maduración de conceptos además de horas de vuelo.

La clasificación aristotélica se realiza luego de una detallada observación de múltiples casos, entonces…

¿Qué estamos haciendo los programadores? ¿Por qué insistimos en generalizar al principio de nuestro proceso ?

Foto Wikipedia

La razón accidental e histórica está vinculada a los primeros editores de código, que nos obligaban a definir primero los nombres para poder construir modelos.

Hoy en día tenemos poderosas herramientas de refactorización seguras.

Un anti-patrón sería conservar el mismo nombre que definimos la primera vez que elaboramos un concepto.

  • Regla 6: Jamás ponerle un nombre a una clase antes de asignar responsabilidades.

Sin comentarios

Escribir comentarios es un code smell indicando que un método, nombre, variable etc. es poco declarativo.

Si logramos escribir nombres increíblemente descriptivos, evitaremos tener que mantener comentarios “aclaratorios” que no aportan valor y quedan acoplados a decisiones accidentales.

  • Regla 7: Evitar los comentarios.

Los expertos del dominio construyen conocimiento

Como regla final y, contradiciendo estas reglas rígidas, debemos entender que un buen nombre es el producto de un conocimiento maduro del dominio del problema.

  • Regla 8: Los nombres perfectos surgen con el paso del tiempo.

El vaso medio lleno

La tecnología avanza y nos ayuda a corregir todos los vicios descritos más arriba. Hoy en día contamos con poderosos linters en casi todos los lenguajes modernos, que nos ayudan a forzar y hacer cumplir dichas reglas de diseño.

Sólo necesitamos asumir el daño ya realizado y construir mejores soluciones.

En el siguiente artículo nos enfocamos en una serie de malas prácticas actuales explicando, con argumentos, cuáles usos arraigados deberíamos modificar.

Resumen de Reglas (hasta ahora)

  • Los nombres deben ser declarativos y no implementativos.
  • Los nombres deben ser contextuales.
  • No mezclar tipo con rol.
  • Asignar responsabilidades antes de asignar nombres.
  • Ante la duda, poner pésimos nombres.
  • Evitar los comentarios.

Conclusiones

Poner buenos nombres es un arte que requiere un conocimiento profundo del dominio de problema que estamos modelando.

No debemos subestimar esta tarea. Recordemos la cita:

Siempre programar como si la persona que terminará manteniendo nuestro código fuera un psicópata violento que sabe dónde vivimos.

John Woods.

Agradecimientos

Colaboraron con la edición y aportaron ideas y correcciones: Carlos E. Ferro y Pablo Casullo.

Parte del objetivo de esta serie de artículos es generar espacios de debate y discusión sobre diseño de software.

Esperamos comentarios y sugerencias sobre este artículo. Este artículo también está disponible en inglés aquí.

También puedes escribirme en twitter.

--

--

Maximiliano Contieri
DotTech

I’m a senior software engineer specialized in declarative designs. S.O.L.I.D. and agile methodologies fan. Maximilianocontieri.com