¿Cómo tratar las salidas de funciones en una función que tiene varios puntos de salida?

Soy más un estudiante que un progtwigdor experimentado y el otro día estaba refactorizando un fragmento de código que escribí hace algún tiempo. Allí, había una función que era bastante grande en tamaño de código y tenía una estructura como esta:

if (eval) return code; ... if (different test) return another code; ... 

En total, hubo alrededor de 6 o 7 puntos de retorno, algunos de ellos con código de limpieza dentro de la twig. Algunos de ellos también respondieron a situaciones erróneas, rutas donde la función no procesaría completamente la entrada, sino que devolvería un código de error.

A pesar de que el código fue comentado y todo me pareció duro para los ojos y difícil de leer. Así que me preguntaba si existen buenas prácticas al respecto.

Leyendo el código de toda la red, encontré diferentes enfoques para este asunto. Por ejemplo uno seguiría este esquema:

 do { whole body of the function; while (false); clean up code if necessary; return code; 

Principalmente para poder utilizar el break; oraciones en diferentes evaluaciones (ya que estábamos dentro de un bucle) para salir del bucle, hacer la limpieza si es necesario y devolver el código de salida. Pero eso es lo mismo que darme a mí, con la limitación que ellos asignan para ir solo se reenviaría en código.

Otro sería similar al mío, pero solo tendría una statement de return al final de la función y tendría una variable para contener códigos de error.

Puedes usar goto para eso.

 code = firstCode; if (condition != 0) goto label; code = secondCode; if (anotherCondition != 0) goto label; label: clean_up_code_if_necessary() exit(code); // may be you should return from the function 

pero podría haber muchas otras opciones dependiendo del caso específico.

Aquí se usa frecuentemente el lenguaje del núcleo de Linux. Cuando algo falla, retrocede y se limpia después del código ejecutado anteriormente.

 if(do_a()==FAIL) goto fail_a; if(do_b()==FAIL) goto fail_c; if(do_c()==FAIL) goto fail_c; /* rest of the code goes here */ /* if it's ok then set err to 0 and jump to ok */ err = 0; goto ok; // otherwise unroll what have been done fail_c: undo_c(); fail_b: undo_b(); fail_a: undo_a(); ok: return err; 

Bueno, necesitamos diferenciar entre C y C ++, la forma de manejar las cosas es bastante diferente entre C y C ++.

En C, recomendaría usar un Enum que indique el estado actual del código, por ejemplo:

 enum {State1,State2,Invalid_Argument,Error} 

luego, cree una función que verifique lo que necesite, luego devuelva alguna constante de la enumeración anterior como valor de retorno:

 int check_statement(arg1,arg2...) 

y, por último, utilice una caja de interruptor en la función anterior:

  switch(check_statment(...)){ case state1: ... return ... case Error: ... return.. }