Creo que el dilema es claro: estamos hablando de Programación Estructurada y no de tonterías. Y si alguien está pensando "pero la programación estructurada esta superada", o bien "con la OOP el enfoque es completamente diferente", lo paro de inmediato. Aquí se habla del C, el padre (o al menos el tío) de todas los lenguajes modernos, y C es un lenguaje estructurado. Y punto. Y si pensáis que C y Programación Estructurada están superados, mejor que os toméis una pausa para la reflexión ...
¿Y entonces? Bueno, vamos a ver un ejemplo para ver si así nos aclaramos las ideas. Escribimos una función que abre un archivo, extrae la primera línea, procesa la línea de datos y sale. Como siempre, se podría escribir en varios miles de maneras diferentes, pero aislaremos las dos buenas para el ejemplo (bueno, aislamos también una tercera manera, pero solo para cerrar bonito el post). Consideremos en primer lugar el tipo Single-Exit:
int readFile( char *path) { char *line = NULL; size_t len = 0; int retcode; // abro el file en path FILE *fp; if (fp = fopen(path, "r")) { // leo el file if (getline(&line, &len, fp) != -1) { // test contenido file if (!strncmp(line, "output=", 7)) { // procesa datos // ... retcode = 0; // proc. OK: set retcode=OK } else retcode = -3; // str err: set retcode=err free(line); // libera recursos } else retcode = -2; // getline err: set retcode=err fclose(fp); // libera recursos } else retcode = -1; // fopen err: set retcode=err // salgo con el retcode seteado return retcode; }Y ahora pasamos a analizar su perfecto equivalente del tipo multiple-exit, o sea:
int readFile( char *path) { char *line = NULL; size_t len = 0; // abro el file en path FILE *fp; if ((fp = fopen(path, "r")) == NULL) { // salgo con error return -1; } // leo el file if (getline(&line, &len, fp) == -1) { // libero recursos y salgo con error fclose(fp); return -2; } // test contenido file if (strncmp(line, "output=", 7)) { // libero recursos y salgo con error fclose(fp); free(line); return -3; } // procesa datos // ... // proc. OK: libero recursos y salgo con OK fclose(fp); free(line); return 0; }¿Cuál es el mejor tipo? Bueno, para mí (y él) es el tipo Single-Exit, pero hay que decir que el partido del Multiple-Exit es grande y está formado (también) por gente muy preparada.
Entonces, ¿dónde está la verdad, tal vez en el medio? No, decir siempre que la verdad está en el medio es la excusa de los indecisos. Yo elijo la solución con el mejor estilo, la más bella y fácil de leer, y, añado, la que te da más control mientras la escribes: con el tipo Single-Exit es más difícil que te olvides de liberar recursos en el momento adecuado (pensar en un programa más complejo, no en el ejemplo). Y también el tipo Single-Exit es más fácil de leer y depurar (probarlo, pero siempre con un caso más complejo).
Se podría hacer una excepción: cuando con el tipo Single-Exit el nivel de anidamiento es demasiado alto, tal vez se podría hacer un híbrido: empezar con los test básicos (tipo "¿el parámetro pasado es nulo?") y sus respectivos return, y, luego, seguir en Single-Exit (pero, si al final el código resultante no os convence, tal vez es mejor si dividáis en dos la función).
Sin embargo, soy menos radical de lo que parece: entre el código que he escrito en mi pasado hay (basta con ver aquí) código de Multiple-Exit o híbrido. El hecho es que hay que ser un poco flexibles: programar (bien) es un arte, y demasiadas restricciones no ayudan a la expresividad.
Como preanunciado cerramos con el tercer tipo: la siguiente función también funciona, y es un equivalente perfecto de las anteriores:
int readFile( char *path) { char *line = NULL; size_t len = 0; // lo hago todo de una vez FILE *fp; if ((fp = fopen(path, "r")) && (getline(&line, &len, fp) != -1) && !strncmp(line, "output=", 7)) { // procesa datos // ... // datos procesados: libero recursos y salgo con OK fclose(fp); free(line); return 0; } else { // libero recursos y salgo con error if (fp) fclose(fp); if (line) free(line); return -1; } }Bueno, si os estáis planeando escribir una función en este modo (tal vez poniendo aun más test en el mismo if) relajaros, tomaros un descanso, leeros un buen libro y, a continuación, intentarlo nuevamente con la cabeza finalmente libre de malos pensamientos: tal vez (espero) que ya no se os ocurrirá de escribirla de esa manera.
Hasta el próximo post.
No hay comentarios:
Publicar un comentario