Factorizando código

En matemáticas la factorización de un polinomio se usa para descomponerlo en partes más simples. Podemos aplicar el mismo concepto al código con una mecánica un poco distinta. Y antes que nada aclaro, factorización no es refactorización (refactoring).Volviendo un poco a las matemáticas, el polinomio x2 − 4 puede convertirse en (x − 2)(x + 2) que puede resultarnos mucho más simple para operar. Pero la factorización no sólo se utiliza en polinomios sino durante muchas operaciones matemáticas. Por ejemplo, cuando se tiene una ecuación y se quieren agrupar las incógnitas de una manera determinada.

y + 2yx + yx = 1 + 3x
(1 + 2x + x) y = 1 + 3x
(1 + 3x) y = 1 + 3x
(1 + 3x) y = 1 + 3x
y = 1

Esa ecuación la resolvimos por el caso más simple de factorización, factor común.

Ahora si vayamos a lo nuestro, muchas veces mientras programamos podemos factorizar nuestro código, o sea sacar factor común entre uno o varios pedazos de código.

var nombre = window.prompt("Escriba su nombre:","");
document.getElementById("nombre").innerHTML = nombre;
var apellido = window.prompt("Escriba su apellido:","");
document.getElementById("apellido").innerHTML = apellido;
var edad = window.prompt("Escriba su apellido:","");
document.getElementById("apellido").innerHTML = edad;
var mail = window.prompt("Escriba su mail:","");
document.getElementById("apellido").innerHTML = mail;

Podemos factorizar un poco de esta manera:

function obtenerDato(dato){
	var valor = window.prompt("Escriba su " + dato + ":","");
	document.getElementById(dato).innerHTML = valor;
}

// Obtener datos
obtenerDato("nombre");
obtenerDato("apellido");
obtenerDato("edad");
obtenerDato("mail");

Esta factorización no es otra que una aplicación del principio DRY (Don’t Repeat Yourself, No te repitas), es decir que la factorización es una manera de no duplicar el código.

El juego de las diferencias

Compara el código anterior con este nuevo código:

function obtenerDato(dato){
	var valor = window.prompt("Escriba su " + dato + ":","");
	document.getElementById(dato).innerHTML = valor;
}

function obtenerDatos(){
	var datos = ["nombre", "apellido", "edad", "mail"];
	for(i in datos){
		obtenerDato(datos[i]);
	}
}

obtenerDatos();

Las diferencias son cuatro,

  1. Hay una nueva función
  2. En la función los datos están en un array
  3. El array se recorre en un for

Si dije bien cuatro, sólo escribí tres porque quiero que busqués la cuarta diferencia.
¿Ya la encontraste?¿Te das por vencido?
Bueno te la digo, lo que desapareció fue el comentario. Pero no desapareció porque me lo olvidé. En este caso sería redundate escribir:

// Obtener datos
obtenerDatos();

Estaríamos violando el principio DRY que mencionamos antes. Y es lo que podríamos hacer con todos los comentarios.
Reemplazarlos por abstracciones, ya sean funciones, procedimientos, métodos, o como quiera que se llame según el lenguaje que estes usando.

Refactoring

Refactoring es cambiar el código sin modificar su comportamiento. Como vimos la factorización es un caso de refactoring.
Veamos un ejemplo de refactoring donde tenemos un gran código y los separamos en varias abstracciones, en este caso funciones.

// Obtiene nombre completo
var nombre = document.getElementById("nombre").innerHTML;
if(document.getElementById("segundo_nombre"))
{
	nombre += " " + document.getElementById("segundo_nombre");
}
var apellido = document.getElementById("apellido").innerHTML;
var nombreCompleto = nombre + apellido;
// Obtiene la fecha de nacimiento
var fechaNacimiento = document.getElementById("fecha_nacimiento").innerHTML;
var fechaNacimiento = fechaNacimiento.split("/");
var dia = parseInt(fechaNacimiento[0]);
var mes = parseInt(fechaNacimiento[1]);
var anyo = parseInt(fechaNacimiento[2]);
// y calcula edad
var fechaHoy = new Date();
var anyoActual = fechaHoy.getFullYear();
var mesActual = fechaHoy.getMonth() + 1;
var edad = anyoActual - anyo;
if(mesActual > mes)
{
	edad--;
}else if(mesActual == mes){
	if(fechaHoy.getDate() < dia)
	{
		edad--;
	}
}
if(edad < 0) edad = 0;

Refactorizado quedaría así:

function obtenerNombreCompleto(){
	var nombre = document.getElementById("nombre").innerHTML;
	if(document.getElementById("segundo_nombre"))
	{
		nombre += " " + document.getElementById("segundo_nombre");
	}
	var apellido = document.getElementById("apellido").innerHTML;
	var nombreCompleto = nombre + apellido;
	return nombreCompleto;
}

function calcularEdad(dia, mes, anyo){
	var fechaHoy = new Date();
	var anyoActual = fechaHoy.getFullYear();
	var mesActual = fechaHoy.getMonth() + 1;
	var edad = anyoActual - anyo;
	if(mesActual > mes)
	{
		edad--;
	}else if(mesActual == mes){
		if(fechaHoy.getDate() < dia)
		{
			edad--;
		}
	}
	if(edad < 0) edad = 0;
	return edad;
}

function obtenerEdad(){
	var fechaNacimiento = document.getElementById("fecha_nacimiento").innerHTML;
	var fechaNacimiento = fechaNacimiento.split("/");
	var dia = parseInt(fechaNacimiento[0]);
	var mes = parseInt(fechaNacimiento[1]);
	var anyo = parseInt(fechaNacimiento[2]);
	return calcularEdad(dia, mes, anyo);
}

var nombreCompleto = obtenerNombreCompleto();
var edad = obtenerEdad();

Creo que este código se entiende mucho más, incluso sin tener los comentarios.

Conclusión

La factorización no es nueva. Es parte del refactoring. Y como tal va siempre acompañada del unit testing que nos da la seguridad de que el código siga funcionando como lo esperamos.
La factorización es reducir el código en la mínima expresión posible, para simplificar las cosas y no violar el principio DRY.¡Úsenla!

Leave a Reply