SOFTWARE CRAFTMANSHIP - 004

Interfaces y sus Complementaciones

Estos son a veces un caso especial para codificaciones, Por ejemplo: digamos que estas construyendo una Factoría Abstracta (PATRON: Abstract Factory).  Esta factoría sera una interface y sera implementada por una clase concreta (Concrete Class).  Como las nombrarías? IPersonaFactoriay y PersonaFactoria? Yo preferiría dejar los nombres sin adornar.  La letra inicial I, tan común en los fajos de código viejo, es a lo poco una distracción o a lo mucho demasiado información.  Yo no quiero que mis usuarios sepan que les estoy brindando una interface.  Solo quiero que sepan que hay una PersonaFactoria.  Así que, si necesito codificar la interface o la implementación, elijo la implementación.  Llamándola PersonaFactoriaImp, o quizas CPersonaFactoria, es preferible a codificar la interface.

Evitar los Mapas Mentales

Los lectores no deberían de traducir mentalmente tus nombres a otros nombres que ellos ya conozcan.  Este problema tiene su origen al no utilizar términos del problema del dominio o términos de la solución del dominio (véase: Domain Driven Design o Diseño Orientado a Dominio).

Una diferencia entre un programador inteligente y uno profesional es que el profesional tiene por entendido que claridad es el rey.  Los profesionales usan su poder para el bien y escriben código que otros puedan entender a simple vista.

Nombres de Clases

Clases y Objetos deberían tener sustantivos o frases sustantivas como nombre, por ejemplo: Cliente, PaginaWiki, Cuenta y ParseadorDeDireccion.  Evitar palabras como: Administrador, Procesador, Data o Info en el nombre de la clase.  El nombre de una clase no debería ser nunca un verbo.

Nombre de Métodos de la Clase

Los métodos deberían tener verbos o frases verbales como nombre, por ejemplo: postPago, borrarPagina o guardar.  Accessors, mutadores (mutators) y predicados (predicates) deberian ser nombrados por su valor y llevar el prefijo get, set o es, según los acuerdos de codificación en Java.
  string nombre = empleado.getNombre();
  clientes.setNombre("Miguel");
  if (pagoCheque.esPosteado())...
Cuando usamos constructores que se sobrescriben, utiliza métodos de factoría estáticos con nombres que describen los argumentos.  Por ejemplo:
  Complex fulcrumPunto = Complex.DesdeNumeroReal(23.0);
Es preferible a:
  Complex fulcrumPunto = new Complex(23.0);
Considera también reforzar su uso haciendo que su constructor sea privado.

No seas Chabacano

Si los nombres son muy originales solo serán recordados por quienes conozcan el sentido de humor del programador que los creo.  Acaso otros sabrán lo que la función GranadaDeMano esta supuesta a hacer?  Seguro que es graciosa, pero quizás en este caso BorrarItem podría ser un mejor nombre.

Elije un Nombre por Concepto

Elije una palabra para un concepto abstracto y pégate a ella.  Por momentos es confuso el tener: traer (fecth), recuperar (retrieve), conseguir (get) como prefijos equivalentes de diferentes clases.  Como recordar que nombre de método me lleva a que clase cuando estos, significando el mismo resultado, apuntan a diferentes clases.

No juegues con las palabras

Evita utilizar la misma palabra con propósitos distintos.  Si sigues la regla de "una palabra por concepto" te aseguras de que por ejemplo un método add tenga una lista de parámetros y valores de respuesta semejantes entre varias implementaciones.

Usa Nombres de Dominio de la Solución

Recuerda que las personas que leerán tu código son programadores.  Así que adelante, puedes utilizar términos que son conocidos en el ámbito de las silencias de la computación, tales como nombres de algoritmo, nombres de patrones, términos matemáticos y así por el estilo.

Elije nombres técnicos para cosas técnicas del sistema y nombres de problema de dominio para los que conciernen a temas del conocimiento de los usuarios y procesos.

Usa Nombres del Dominio del Problema

Cuando no hay programadores para lo que haces, usa los nombres del dominio del problema.  Por lo menos el programador que mantiene el código puede preguntarle al experto del dominio que significan los conceptos que no entienda.

Crea un Contexto Significativo

Imagina que tienes variables con los siguientes nombres: primerNombre, calle, casaNumero, ciudad, provincia y codigoPostal.  Juntas es muy obvio que forman parte de una dirección, pero que pasa si solo vez provincia como la única variable de un método?  Automáticamente entenderías que es parte de una dirección?

Puedes agregar contexto utilizando prefijos como: addPrimerNombre, addApellido, addProvincia y así por el estilo.  De esta forma el lector entenderá que estas son parte de una estructura mas grande.  Claro esta, seria mucho mejor si creamos una clase Direccion, así hasta el compilador sabrá que la componen.

Considera el metodo que te mostramos a continuacion, necesitan las variables de mas significado, de mas contexto?  El nombre de la funcion provee solo una parte del contexto; el algoritmo provee el resto.  Una vez que lees toda la funcion notas que las tres variables numero, verbo y modificadorPlural son parte del mensaje "adivina las estadisticas".  Desafortunadamente, el contexto debe ser inferido.  Al mirar por primera vez el metodo el significado de las variables es opaco:
private void imprimeEstadisticasAdivinadas (char candidato, int conteo) {
  String numero;
  String verbo;
  String modificadorPlural;
  if (conteo == 0) {
    numero = "no";
    verbo = "es";
    modificadorPlural = "s";
  } else if (conteo == 1) {
    numero = "1";
    verbo = "es";
    modificadorPlural = "";
  } else {
    numero = Integer.toString(conteo);
    verbo = "son";
    modificadorPlural = "s";
  }
  String mensajeAdivina = String.format(
    "Hay %s %s %s%s", verbo, numero, candidato, modificadorPlural
  );
  print(mensajeAdivina);
}
La función es un poco larga y las variables están a todo lo largo.  Para partir la función en partes mas pequeñas necesitamos crear la clase AdivinaMensajeEstadistico y hacer de las variables sus campos. Esto provee un contexto claro para las tres variables.

La mejora en el contexto también permite que el algoritmo sea mas limpio al dividirlo en varias funciones pequeñas.
public class AdivinaMensajeEstadistico {
  private String numero;
  private String verbo;
  private String modificadorPlural;

  public String hacer (char candidato, int conteo) {
    crearPartesPluralesDependientesDelMensaje (contador);
    return String.format (
      "Hay %s %s %s%s, verbo, numero, candidato, modificadorPlural );
  }

  private void crearPartesPluralesDependientesDelMensaje (int contador) {
    if  (contador == 0) {
      noHayLetras();
    } else if (contador == 1) {
      hayUnaLetra();
    } else {
      hayVariasPalabras(contador);
    }
  }

  private void hayVariasPalabras (int contador) {
    numero = Integer.toString (contador);
    verbo = "son";
    modificadorPlural = "s";
  }

  private void hayUnaLetra() {
    numero = "1";
    verbo = "es";
    modificadorPlural = "";
  }

  private void noHayLetras() {
    numero = "no";
    verbo = "es";
    modificadorPlural = "s";
  }
}

No agregues contexto gratuito

En una aplicación imaginaria llamada "Estación de Gasolina Deluxe" es una mala idea agregar el prefijo EGD a todas y cada una de las clases que definas.  Francamente trabajas en contra de tus herramientas.  Presionas G en el auto-completar y aparece una lista de todas y cada una de las clases de tu Framework.

Es esto de sabios?, porque hacerle la tarea difícil a tu IDE (Interactive Development Environment o Ambiente de Desarrollo Interactivo) cuando lo que quiere es ayudarte a encontrar lo que buscas de forma rápida y simple.

De la misma forma, digamos que inventaste una clase DireccionDeCorreo en el modulo EGDContabilidad a la que nombraste EGDContabilidadEmail.  Mas tarde, necesitas una dirección de correos para tus clientes, usarias EGDContabilidadEmail?  Acaso esto suena a un nombre correcto? 15 de los 20 caracteres son redundantes o irrelevantes.

Nombres cortos son mejor a los nombres largos.  Los nombres direccionCuenta y direccionCliente están bien como instancias de la clase Direccion pero serian nombres pobres para una clase en si.

Conclusiones sobre nombres

La parte mas difícil de elegir buenos nombres es que estos requieren de una buena habilidad descriptiva y de una experiencia cultural compartida.  Es un tema mas de enseñanza que de tecnicismos, negocios o administración.  Como resultado muchas personas en nuestro campo no llegan a hacerlo bien.

Bueno señores aquí terminamos el capitulo 2 sobre el correcto nombramiento de los elementos de nuestros sistemas, me he tardado mas en escribir este articulo para terminar con el capitulo y poder avanzar en otros que si tocan mas a fondo temas técnicos, espero les sea de provecho, nos vemos en la próxima entrega....

Comentarios

  1. Saludos!

    Me gusto mucho este articulo ya que uno de mis principales problemas a la hora de nombrar clases y metodos es este. Cuando estamos en la universidad no nos instruyen en cuales son las mejores tecnicas a la hora de programar nuestro codigo lo cual hace que salgamos con esta deficiencias en la estructuracion y organizacion del mismo, nuestro principal temor es el de no usar Nombres y prefijos muy largo lo cual hace que terminemos abreviando los nombres jajajaja. Pero despues de leer esto empezare a aplicarlo a ver que tal va.

    Un abrazo!

    ResponderEliminar

Publicar un comentario

Entradas populares