En defensa del GOTO

El uso de la instrucción GOTO ha sido tema de muchos debates y hoy en día es común que un programador iniciante frunza el ceño al preguntarle su opinión sobre ello, muchos lo consideran más un “salto antinatural” que un “ir a”. Incluso yo llegué a atribuir el GOTO directamente con las malas prácticas y el código espagueti, riendome de cualquier código que llegase a usarlo, pero no podia estar mas equivocado.

Polarización en el desarrollo de software

Esta polémica se debe en parte a un problema de polarización, y aprovecho el uso del GOTO para tratar este tema, si bien en décadas pasadas la polarización y los extremismos no eran tan graves, el surgimiento de nuevas tecnologías y el crecimiento de comunidades de nuevos desarrolladores han agravado todo esto.

En los últimos años, lenguajes como Javascript, PHP y Python han tomado protagonismo y con ello, cientos de librerías, frameworks y utilidades. Existen miles de debates sobre qué tan malo es PHP como lenguaje, las inconsistencias internas de Javascript, VueJS vs Angular vs React vs..., y sobre si Ruby es tan buen lenguaje como lo pintan sus más acérrimos fanáticos.

Muchas de las declaraciones que se dicen en estos debates se van a los extremos, el simple hecho de que PHP o Javascript tengan problemas internos o de inconsistencias puede hacer que muchas personas no piensen usarlos nunca más en su vida, menos aún en un entorno productivo.

La realidad es muy diferente, y es que en el mundo del desarrollo hay que saber elegir la herramienta adecuada para la tarea adecuada, me sería muy utópico decir que un solo lenguaje puede servir para solventar todo tipo de tarea de manera conveniente (los miro a ustedes, extremistas de Ruby y Rust), pero ojo, no por eso significa que no puedan desarrollarse mejores alternativas a futuro.

A nivel personal, admito que no me gusta Javascript, pero no puedo negar las ventajas que tiene a la hora de manipular fácilmente el DOM y los beneficios puntuales de usar entornos como NodeJS.

Si llega el día en el que Javascript me simplificará más el trabajo que usar un lenguaje de mi preferencia, lo aceptaré y lo usaré, y creo que los demás deberían de hacer lo mismo, todo se resume en tener un sentido crítico, o al menos sentido común, imagínate hacer un sistema operativo en Ruby o un framework web en Haskell y esperar a que otros lo usen seriamente.

Volviendo al GOTO

La historia de la instrucción o palabra reservada GOTO es extensa, se originó en los primeros lenguajes de programación, se encuentra hasta en todo tipo de ensambladores. Alrededor de los años 70 llegaría el boom de la programación estructurada para cambiar el destino de la programación, poco a poco se iría usando cada vez menos esta instrucción por una simple razón: Facilita mucho el escribir el famoso "código espagueti".

UPS... Atacado solo por usar un pequeño GOTO.

Incluso el mismo Dijkstra alertó sobre los peligros de esta instrucción, y favoreció en su lugar el uso de las estructuras de control que aparecieron en los lenguajes de esa epoca.

Hay que aclarar que no tiene sentido abusar del GOTO, y mucho menos usarlo para cosas como ciclos cuando se puede escribir un while o for que son más expresivos, pero esto no significa que se deba de satanizar esta instrucción e ignorar la posibilidad de usarla por completo.

Claramente, en lenguajes de más alto nivel como Javascript, Python o Ruby su uso no tiene mucha utilidad debido a la naturaleza del lenguaje o porque directamente no existe (aunque se puede emular), pero aun es una instrucción importante en lenguajes de más bajo nivel como C o C++ donde puede ser beneficioso, por ejemplo, tener un único punto de salida de una función.

void func(void)
{
	struct user *user;
	char *str1, *str2, *str3;
	bool cond = false;
		
	//codigo que modifica las variables
		
	if (cond) {
		free(user);
		free(str1);
		free(str2);
		free(str3);
		return;
	}
		
	//mas codigo
		
	free(user);
	free(str1);
	free(str2);
	free(str3);
}

El mismo ejemplo pero sacando provecho del GOTO:

void func(void)
{
	struct user *user;
    char *str1, *str2, *str3;
	bool cond = false;
		
	//codigo que modifica las variables
		
	if (cond) {
		goto end;
	}
		
	//mas codigo
		
	end:
		free(user);
		free(str1);
		free(str2);
		free(str3);
}

En lenguajes como C el uso de esta instrucción es algo beneficioso, ya que ahí es comun tener que llevar un control de la memoria y en muchos casos se debe de "limpiar", por ejemplo, antes de salir de un scope porque luego ya no se tendrá acceso a las variables.

Al programar en C aprovecho esta instrucción solo para reducir el código repetido y el tamaño de una función como en el ejemplo mostrado previamente, pero logré entender que no es algo que debería estar prohibido.

Como dije anteriormente, todo se resume en tener un sentido crítico a la hora de escoger las herramientas y elementos a usar para programar.