martes, 13 de febrero de 2018

Código Elegante

Por Iván Vázquez. 

Conozco personas que dirán que las matemáticas son la base de la programación o requisito fundamental para ser un buen programador. Otros dirán que no es imprescindible, aun así, nadie podría negar la estrecha relación que existe entre las ecuaciones matemáticas y los algoritmos lógicos.

La manera de abordar y abstraer una solución a un problema puede ser diversa y aún así llegar a un resultado correcto. Sin embargo, puede existir un algoritmo mejor que otro, si se compara algunos de los siguientes puntos: estabilidad, ejecución, mantenimiento, funcionalidad, legibilidad, compatibilidad entre otros muchos más. Está claro que para algunos casos tendrá más importancia cierto factor sobre otro.

Por ejemplo, en algunos dispositivos con recursos limitados podría tener más importancia la velocidad de ejecución sobre la compatibilidad del programa. O por el contrario, el desarrollo multi plataforma que brinda gran compatibilidad, pero podría aumentar la complejidad del código y requerir dependencias.

En cualquiera que sea el caso se pueden aplicar algunas reglas para mejorar la lógica, crear código limpio y tener buenas prácticas de programación. Por eso me gustaría compartir algunos consejos que me han ayudado y que podrían ser útiles.

1-. No copiar y pegar código.
Esto ayuda a razonar y comprender nuestro programa, también evita que dupliquemos código o que se tome código innecesario.

2-. No escribir comentarios.
Podría parecer raro pero el exceso de comentarios en el código es indicador de que el código no es muy fácil de entender. Se puede evitar escribir comentarios representando las entidades, propiedades, métodos y variables con nombres intuitivos.

Por ejemplo:
No es necesario comentar los siguientes métodos, debido a su fácil lectura.

//Código fácil de leer
User::getBy($id);
User::is($root);

3-. No indentar más de 4 llaves.
Generalmente los tabuladores surgen a partir de disyunciones en el flujo del proceso, para los humanos es más fácil seguir un flujo lineal que uno intercalado.

Ejemplo:

//Código complejo y difícil de leer
if ($condicion === true){
  if ($segunda_condicion === true){
    $result = 'A';
  }
  elseif ($segunda_condicion === false){
    $result = 'B';
  }
}else{
  $result = 'C';
}
return $resul;

//Mismo resultado con código fácil de leer
if(!$condicion){
    return 'C';
}
return $segunda_condicion ? 'A' : 'C';

Ambos segmentos de código llegan al mismo resultado, pero uno resulta más complejo que otro debido a las llaves. La intención es escribir un código "bonito", que sea más fácil de leer por humanos y de procesar por ordenadores.

4-. Evitar el Switch
En algunos casos es más difícil reemplazar un switch por un arreglo, pero siempre es más eficiente un arreglo o diccionario que la estructura de control switch ya que internamente funciona como un conjunto de ifs.

Mostraré un caso común;

//Código complejo y difícil de leer
 switch(status)
 {
  case 'new':
    $('.item').addClass('blue');
  brack;
  case 'updated':
    $('.item').addClass('green');
  brack;
  case 'canceled':
    $('.item').addClass('yellow');
  brack;
  case 'deleted':
    $('.item').addClass('red');
  brack;
 }

 // Mismo resultado con código optimizado.
 var colors={"new":"blue","updated":"green","canceled":"yellow","deleted": "red"};
 $('.item').addClass(color.status);
En ambos casos se cumple el objetivo, pero es más eficiente usando un arreglo.

5-. Evitar en php comillas dobles ""
En php las comillas dobles hacen referencia a un string que podría contener variables, esto obliga al intérprete de php a buscar intensivamente variables contenidas en su interior. Mientras que con comillas simples es reconocido como un simple string.

  $world = 'mundo';
  echo "Hola $mundo";
  echo "Hola".$mundo;
  echo 'Hola '.$mundo; // <-- Mejor resultado en tiempo de ejecución.

6-. Evitar el uso de excesivo de loops.
El hecho de intentar resolver algo común sin un ciclo, ayuda a pensar una solución mejor. Debemos evitar al máximo el uso de loops mágicos como FOR IN o EACH que son más lentos.

7-. Utilizar índices en las bases de datos.
En los gestores de bases de datos no existe un límite de registros establecido, el límite es el espacio disponible en el disco duro. De igual forma, la velocidad de lectura y escritura de registros termina siendo controlado por el sistema operativo y los mismos componentes electrónicos, el uso correcto de índices en las tablas permite trabajar con 200 o 300 millones de registros sin problemas. Típicamente se colocan los índices en los campos relacionados con otras tablas o en campos que se utilizan para filtrar.

8-. No hacer consultas con subqueries.
Al contrario que los índices, los subqueries son internamente un loop interno que afecta el performance gravemente. Esto se debe a que ejecuta un query por cada row consultado en el select principal, si se agregan 2 o 3 podría ser muy lento, incluso desbordar la memoria en tablas de pocos rows. Se debe resolver con joins, o ejecutar consultas separadas.

9-. Nivel ensamblador
Es conveniente tomar en cuenta factores de bajo nivel, el programa en lenguajes de alto nivel como Java o PHP termina traduciéndose a ensamblador y, por último, en lenguaje binario en nuestro procesador o memoria ram. Por ejemplo, una variable global requerirá memoria, mientras algún objeto haga referencia a ella. Esto debido al contexto y alcance (scope) de las funciones y objetos. 

En resumen…
Abstraer el problema y razonarlo de la manera más inteligente posible te permite crear código legible, óptimo y elegante.


Te recomendamos