El segundo capítulo del libro se llama Meaninful Names, que podría traducirse como nombres con sentido (o con significado). Continuamente le estamos dando nombre a variables, funciones, argumentos, clases, paquetes, archivos, directorios,… tiene una gran importancia hacerlo de la mejor manera posible y el capítulo comienza viendo una simples regla crear buenos nombres.
Personalmente prefiero escribir los nombres en ingles, es más fácil expresar ciertas ideas y se reduce la verborrea, por lo que voy a mantener los ejemplos sin traducir. Los ejemplos de código están en java, pero creo que se pueden entender sin necesidad de traducirlos.

Usar nombres que revelen intención

Elegir buenos nombres cuesta tiempo, pero ahorra más tiempo del que cuesta.
El autor (Tim Ottinger en este capítulo) sugiere que un nombre debería decir por qué existe, que hace y como se usa. Y que si (atención que esto puede levantar ampollas) un nombre requiere un comentario, demuestra que el nombre no revela su intención:

int d; // elapsed time in days

El nombre d no revela nada. No evoca una sensación de tiempo transcurrido, ni de días. Debemos elegir un nombre que especifique que se mide y su unidad:

int elapsedTimeInDays;
int daysSinceCreation;
int daysSinceModification;
int fileAgeInDays;

¿Podrías adivinar el propósito de este código?

public List<int[]> getThem() {
  List<int[]> list1 = new ArrayList<int[]>();
  for (int[] x : theList)
    if (x[0] == 4)
      list1.add(x);
  return list1;
}

No es especialmente complejo, pero los nombres no informan del contexto. Para poderlo comprender, necesitamos algunas respuestas:

  1. ¿Qué tipo de cosas hay en theList?
  2. ¿Cuál es el significado del cero de un elemento en theList ?
  3. ¿Cuál es el significado del valor 4?
  4. ¿Cómo usaría la lista que se está devolviendo?

Suponemos que estamos ante un juego como el buscaminas, el tablero (theList) es una lista de celdas, le cambiamos el nombre a gameBoard. Cada celda es un array, donde la posición 0 es el estado y que un 4 en esa posición significa «marcado» (flagged), veamos como quedaría con estos cambios:

public List<int[]> getFlaggedCells() {
List<int[]> flaggedCells = new ArrayList<int[]>();
for (int[] cell : gameBoard)
if (cell[STATUS_VALUE] == FLAGGED)
flaggedCells.add(cell);
return flaggedCells;
}

Es exactamente igual de complejo, pero se entiende mucho mejor que hace.
Se puede ir un paso más allá, creando una clase que represente las celdas, en vez de usar un array de ints, con una función (isFlagged) que indique si es una bandera, evitando así la necesidad de tener que saber desde fuera que es cada estado (los temidos «magic numbers»):

public List getFlaggedCells() {
  List flaggedCells = new ArrayList();
  for (Cell cell : gameBoard)
    if (cell.isFlagged())
      flaggedCells.add(cell);
  return flaggedCells;
}

Aún mejor ¿no? Ahora es mucho más fácil de entender que hace el código y solo dedicándole un breve tiempo a pensar nombres. ¿Cual de los 2 códigos preferirías mantener?¿Cuanto tiempo crees que habrías perdido entendiendo que hacía el código? Me juego una cerveza a que bastante más de lo que te costaría darle nombres adecuados.

Evitar la desinformación

Otro punto a tener en cuenta es la apariencia de los nombres, ya que pueden oscurecer mucho el código dando pie a confusión:
No usar palabras muy similares: XYZControllerForEfficientHandlingOfStringsy XYZControllerForEfficientStorageOfStrings.
Usar palabras técnicas para definir algo que realmente no lo es, como accountList para algo que realmente no es una lista, mejor Usar accountGroup, bunchOfAccounts o simplemente accounts.
No usar abreviaturas que den pie a confusión: el autor pone como mal ejemplo de uso, el usar hp para nombrar una hipotenusa, pero personalmente considero que nunca es una buena decisión utilizar una abreviatura.
No usar caracteres que no se diferencien a simple vista: como O mayúscula y cero (O 0), uno, ele e i mayúscula (1 l I),… aunque si haces esto diría que es porque quieres ofuscar el código a posta.

Hacer distinciones significativas

No aporta nada añadir un número, o una palabra sin significado a un nombre para distinguirlo de otro: Si tienes una clase Product, no crees otra que se llame ProductData o ProductInfo.
Tampoco uses nombres redundantes: ¿NameString es mejor que Name? ¿Acaso llamarías Name a una variable que fuera un número?
Si encuentras 2 clases: Customer y CustomerObject, ¿que diferencias crees que habría entre ellas? ¿Desde cual tendrías acceso al historial de pagos del cliente? Ni idea, ¿no? Yo tampoco

Usar nombres pronunciables

Programar es una habilidad social, si no eres capaz de pronunciar algo no lo escribas, o tendrás problemas cuando tengas que hablar con un compañero de ese método genymdhms(generation date, year, month, day, hour, minute, and second), ¿que tal si mejor usamos generationTimestamp?

Usar nombres que se puedan buscar

Si tienes que encontrar donde se hace referencia a algo llamado max, e, a,… lo vas a pasar mal, mejor usar nombres que sean fáciles de encontrar.

Evitar codificar

Añade una capa de complejidad innecesaria y obliga a conocerla, así que mejor evitar usar Notación Hungara y prefijos para los atributos globales. En cuanto a las Interfaces e Implementaciones: si estas creando un Abstract Factory para crear Shapes(figuras), ¿cómo llamas a la interfaz y a la clase? ¿IShapeFactoy y ShapeFactory? El autor sugiere dejar la interfaz sin adornos (ShapeFactory) y codificar la clase ( ShapeFactoryImp).

Evitar mapas Mentales

Todos somos capaces de trabajar sin problemas usando i, j, k como variables, o siempre hemos usado len al principio de una variable para indicar que contiene una longitud (Name y LenName), o… pero resulta que hay quien usa NumName, o en vez de i,j,k x,y,z o a,b,c. Eso son mapas mentales y funcionan hasta que alguien usa unos diferentes, y ya no es que dejen de tener sentido, es que provocan problemas.
Ademas, ¿por que j? ¿Solo por que i ya está en uso?

Nombres de clases y métodos

Las clases deben tener nombres de sustantivos, nunca de verbos, y evitar palabras como Manager, Processor, Data, Info,…
Los métodos deben tener nombres de verbos.

Elegir una palabra por concepto

Es confuso usar varias palabras para un mismo concepto, si usamos fetch, retrieve y get indistintamente o controller, manager y driver, no sabremos que diferencias hay entre unos y otros, o cual deberíamos implementar si queremos crear un método nuevo.

Evitar usar la misma palabra para diferentes propósitos

Si hay un método addX que añade un elemento a una lista y otro addY que suma un valor al 1º elemento de la lista, sería mejor cambiar el primero por insertX. La idea es hacer nuestro código lo más fácil de entender, que no haga falta estudiar el código para entenderlo.

Usar nombres técnicos y de negocio

Tu código lo van a leer programadores, usa nuestra jerga. Y para los conceptos que no puedan ser expresados con nombres técnicos, no inventes o acabarás teniendo que usar un diccionario negocio-código (lo he sufrido y es frustrante tener que usar palabras diferentes para hablar con los programadores y con los funcionales para el mismo concepto).

Añadir contexto

Ante un grupo de variables (firstName, lastName, street, houseNumber, city, state, zipcode) es fácil adivinar que están relacionadas con un contexto en concreto (en este caso una dirección). Pero ante una única variable, es difícil saberlo (state puede ser relativo a cualquier cosa)
Se puede añadir un prefijo a las variables (addrFirstName, addrLastName, addrStreet,…) pero es un poco cutre, mejor crear una clase Addr que las contenga, así el contexto queda más claro y limpio, y se puede incluir la funcionalidad específica de la dirección en la nueva clase.

Pero no añadir contexto que no aporte

Ante una app llamada «Gas Station Deluxe» es irrelevante añadir a cada clase delante el prefijo GSD; se sobreentiende que pertenece a la gasolinera. Lo único que consigues es complicarte la vida con el autocompletado y que para acceder al mail de un cliente tengas que usar la clase GSDAccountAddress ¿de verdad te parece un nombre apropiado para que contenga el mail? mejor simplemente Address, ¿no?

 

Esto es mi resumen-destripado del segundo capítulo del Clean Code, espero que os haya sido útil y no hayáis pensado muchas veces eso de «mierda, pues esto lo hago mucho». Son reglas sencillas y de sentido común pero siempre se nos escapa algo. Ah, y que no haya miedo a refactorizar nombres, es mejor volver a aprenderlos que tener que mirar cada vez a que narices se refieren. Si total, nadie se aprende los nombres de memoria.

Categorías: libros

0 comentarios

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *