Pregunta

¿Existen buenas razones por las que es mejor tener una sola declaración de devolución en una función?

¿O está bien regresar de una función tan pronto como sea lógicamente correcto hacerlo, lo que significa que puede haber muchas declaraciones de retorno en la función?

¿Fue útil?

Solución

A menudo tengo varias declaraciones al comienzo de un método para regresar en situaciones "fáciles".Por ejemplo, esto:

public void DoStuff(Foo foo)
{
    if (foo != null)
    {
        ...
    }
}

...se puede hacer más legible (en mi humilde opinión) así:

public void DoStuff(Foo foo)
{
    if (foo == null) return;

    ...
}

Entonces sí, creo que está bien tener múltiples "puntos de salida" de una función/método.

Otros consejos

Nadie ha mencionado o citado Código completo así que lo haré.

17.1 regreso

Minimizar el número de devoluciones en cada rutina.Es más difícil entender una rutina si, al leerla en la parte inferior, no eres consciente de la posibilidad de que haya regresado a algún lugar superior.

Usar una devolver cuando mejora la legibilidad.En determinadas rutinas, una vez que sepa la respuesta, querrá devolverla a la rutina de llamada inmediatamente.Si la rutina está definida de tal manera que no requiere ninguna limpieza, no regresar inmediatamente significa que tendrá que escribir más código.

Yo diría que sería increíblemente imprudente decidir arbitrariamente en contra de múltiples puntos de salida, ya que he encontrado que la técnica es útil en la práctica. una y otra vez, de hecho, a menudo he código existente refactorizado a múltiples puntos de salida para mayor claridad.Podemos comparar los dos enfoques así: -

string fooBar(string s, int? i) {
  string ret = "";
  if(!string.IsNullOrEmpty(s) && i != null) {
    var res = someFunction(s, i);

    bool passed = true;
    foreach(var r in res) {
      if(!r.Passed) {
        passed = false;
        break;
      }
    }

    if(passed) {
      // Rest of code...
    }
  }

  return ret;
}

Compare esto con el código donde hay múltiples puntos de salida son permitido:-

string fooBar(string s, int? i) {
  var ret = "";
  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

Creo que esto último es considerablemente más claro.Hasta donde puedo decir, la crítica a los múltiples puntos de salida es un punto de vista bastante arcaico en estos días.

Actualmente estoy trabajando en un código base donde dos de las personas que trabajan en él se suscriben ciegamente a la teoría del "punto único de salida" y puedo decirles que, por experiencia, es una práctica horrible.Hace que el código sea extremadamente difícil de mantener y te mostraré por qué.

Con la teoría del "punto único de salida", inevitablemente terminas con un código que se parece a este:

function()
{
    HRESULT error = S_OK;

    if(SUCCEEDED(Operation1()))
    {
        if(SUCCEEDED(Operation2()))
        {
            if(SUCCEEDED(Operation3()))
            {
                if(SUCCEEDED(Operation4()))
                {
                }
                else
                {
                    error = OPERATION4FAILED;
                }
            }
            else
            {
                error = OPERATION3FAILED;
            }
        }
        else
        {
            error = OPERATION2FAILED;
        }
    }
    else
    {
        error = OPERATION1FAILED;
    }

    return error;
}

Esto no solo hace que el código sea muy difícil de seguir, sino que ahora dice que más adelante debe regresar y agregar una operación entre 1 y 2.Tienes que sangrar casi toda la maldita función, y buena suerte asegurándote de que todas las condiciones y llaves if/else coincidan correctamente.

Este método hace que el mantenimiento del código sea extremadamente difícil y propenso a errores.

Programación estructurada dice que solo deberías tener una declaración de devolución por función.Esto es para limitar la complejidad.Mucha gente, como Martin Fowler, sostiene que es más sencillo escribir funciones con múltiples declaraciones de retorno.Presenta este argumento en el clásico refactorización libro que escribió.Esto funciona bien si sigues sus otros consejos y escribes funciones pequeñas.Estoy de acuerdo con este punto de vista y sólo los puristas estrictos de la programación estructurada se adhieren a declaraciones de retorno únicas por función.

Como señala Kent Beck al hablar de las cláusulas de protección en Patrones de implementación haciendo que una rutina tenga un solo punto de entrada y salida...

"Fue para evitar la confusión posible al saltar dentro y fuera de muchos lugares en la misma rutina.Tenía sentido cuando se aplicaba a Fortran o programas de lenguaje de ensamblaje escritos con muchos datos globales donde incluso comprender qué declaraciones se ejecutaban era un trabajo duro ...con métodos pequeños y datos principalmente locales, es innecesariamente conservador".

Encuentro que una función escrita con cláusulas de protección es mucho más fácil de seguir que un largo conjunto de cláusulas anidadas. if then else declaraciones.

En una función que no tiene efectos secundarios, no hay una buena razón para tener más de un retorno y debes escribirlos en un estilo funcional.En un método con efectos secundarios, las cosas son más secuenciales (indexadas en el tiempo), por lo que se escribe en un estilo imperativo, utilizando la declaración return como comando para detener la ejecución.

En otras palabras, cuando sea posible, favorezca este estilo.

return a > 0 ?
  positively(a):
  negatively(a);

Más allá de esto

if (a > 0)
  return positively(a);
else
  return negatively(a);

Si se encuentra escribiendo varias capas de condiciones anidadas, probablemente haya una manera de refactorizarlas, utilizando la lista de predicados, por ejemplo.Si descubre que sus if y else están muy separados sintácticamente, es posible que desee dividirlos en funciones más pequeñas.Un bloque condicional que abarca más de una pantalla de texto es difícil de leer.

No existe una regla estricta que se aplique a todos los idiomas.Algo como tener una única declaración de devolución no hará que su código sea bueno.Pero un buen código tenderá a permitirle escribir sus funciones de esa manera.

Lo he visto en estándares de codificación para C++ que eran una resaca de C, como si no tuvieras RAII u otra administración automática de memoria, entonces tendrías que limpiar para cada retorno, lo que significa cortar y pegar. de la limpieza o un goto (lógicamente lo mismo que 'finalmente' en los lenguajes administrados), los cuales se consideran de mala forma.Si sus prácticas son utilizar punteros inteligentes y colecciones en C++ u otro sistema de memoria automático, entonces no hay una razón sólida para ello, y se trata de legibilidad y más bien de una decisión.

Me inclino por la idea de que las declaraciones de retorno en el medio de la función son malos.Puede usar devoluciones para crear algunas cláusulas de protección en la parte superior de la función y, por supuesto, decirle al compilador qué devolver al final de la función sin problemas, pero devuelve en el medio de la función puede ser fácil de pasar por alto y puede hacer que la función sea más difícil de interpretar.

¿Existen buenas razones por las que es mejor tener una sola declaración de devolución en una función?

, hay:

  • El único punto de salida ofrece un lugar excelente para hacer valer sus condiciones posteriores.
  • A menudo resulta útil poder poner un punto de interrupción del depurador en el retorno al final de la función.
  • Menos retornos significa menos complejidad.El código lineal es generalmente más sencillo de entender.
  • Si intentar simplificar una función a un único retorno genera complejidad, entonces eso es un incentivo para refactorizar a funciones más pequeñas, más generales y más fáciles de entender.
  • Si estás en un idioma sin destructores o si no usas RAII, entonces un solo retorno reduce la cantidad de lugares que tienes que limpiar.
  • Algunos idiomas requieren un único punto de salida (por ejemplo, Pascal y Eiffel).

La pregunta a menudo se plantea como una falsa dicotomía entre múltiples retornos o declaraciones if profundamente anidadas.Casi siempre hay una tercera solución que es muy lineal (sin anidamiento profundo) con un solo punto de salida.

Actualizar:Aparentemente Las directrices de MISRA promueven la salida única, también.

Para ser claro, no estoy diciendo que sea siempre Es incorrecto tener múltiples devoluciones.Pero dadas soluciones equivalentes, hay muchas buenas razones para preferir la que tiene un retorno único.

Tener un único punto de salida proporciona una ventaja en la depuración, porque le permite establecer un único punto de interrupción al final de una función para ver qué valor se devolverá realmente.

En general, trato de tener un solo punto de salida de una función.Sin embargo, hay ocasiones en las que hacerlo termina creando un cuerpo funcional más complejo de lo necesario, en cuyo caso es mejor tener múltiples puntos de salida.Realmente tiene que ser un "juicio" basado en la complejidad resultante, pero el objetivo debe ser el menor número posible de puntos de salida sin sacrificar la complejidad y la comprensibilidad.

No porque Ya no vivimos en la década de 1970..Si su función es lo suficientemente larga como para que múltiples devoluciones sean un problema, es demasiado larga.

(Aparte del hecho de que cualquier función de varias líneas en un idioma con excepciones tendrá múltiples puntos de salida de todos modos).

Mi preferencia sería la salida única, a menos que realmente complique las cosas.Descubrí que en algunos casos, múltiples puntos existentes pueden enmascarar otros problemas de diseño más importantes:

public void DoStuff(Foo foo)
{
    if (foo == null) return;
}

Al ver este código, inmediatamente preguntaría:

  • ¿'foo' alguna vez es nulo?
  • Si es así, ¿cuántos clientes de 'DoStuff' alguna vez llaman a la función con un 'foo' nulo?

Dependiendo de las respuestas a estas preguntas, podría ser que

  1. la verificación no tiene sentido ya que nunca es cierta (es decir,debería ser una afirmación)
  2. la verificación rara vez es cierta, por lo que puede ser mejor cambiar esas funciones específicas de la persona que llama, ya que probablemente deberían realizar alguna otra acción de todos modos.

En los dos casos anteriores, el código probablemente se pueda reelaborar con una aserción para garantizar que 'foo' nunca sea nulo y que los llamantes relevantes cambien.

Hay otras dos razones (creo que específicas del código C++) por las que existen múltiples que en realidad pueden tener un negativo afectar.Son el tamaño del código y las optimizaciones del compilador.

A un objeto que no sea POD C++ dentro del alcance a la salida de una función se le llamará a su destructor.Cuando hay varias declaraciones de retorno, puede darse el caso de que haya diferentes objetos en el alcance y, por lo tanto, la lista de destructores a llamar será diferente.Por lo tanto, el compilador necesita generar código para cada declaración de devolución:

void foo (int i, int j) {
  A a;
  if (i > 0) {
     B b;
     return ;   // Call dtor for 'b' followed by 'a'
  }
  if (i == j) {
     C c;
     B b;
     return ;   // Call dtor for 'b', 'c' and then 'a'
  }
  return 'a'    // Call dtor for 'a'
}

Si el tamaño del código es un problema, entonces puede ser algo que valga la pena evitar.

El otro problema se relaciona con la "Optimización del valor de retorno con nombre" (también conocido como Copy Elision, ISO C++ '03 12.8/15).C++ permite que una implementación omita llamar al constructor de copia si puede:

A foo () {
  A a1;
  // do something
  return a1;
}

void bar () {
  A a2 ( foo() );
}

Simplemente tomando el código tal como está, el objeto 'a1' se construye en 'foo' y luego se llamará a su construcción de copia para construir 'a2'.Sin embargo, la elisión de copia permite al compilador construir 'a1' en el mismo lugar de la pila que 'a2'.Por lo tanto, no es necesario "copiar" el objeto cuando la función regresa.

Múltiples puntos de salida complican el trabajo del compilador al intentar detectar esto, y al menos para una versión relativamente reciente de VC++ la optimización no tuvo lugar cuando el cuerpo de la función tenía múltiples retornos.Ver Optimización del valor de retorno con nombre en Visual C++ 2005 para más detalles.

Tener un único punto de salida reduce Complejidad ciclomática y por lo tanto, En teoria, reduce la probabilidad de que introduzca errores en su código cuando lo cambie.Sin embargo, la práctica tiende a sugerir que se necesita un enfoque más pragmático.Por lo tanto, tiendo a intentar tener un único punto de salida, pero permito que mi código tenga varios si es más legible.

Me obligo a usar solo uno return declaración, ya que en cierto sentido generará olor a código.Dejame explicar:

function isCorrect($param1, $param2, $param3) {
    $toret = false;
    if ($param1 != $param2) {
        if ($param1 == ($param3 * 2)) {
            if ($param2 == ($param3 / 3)) {
                $toret = true;
            } else {
                $error = 'Error 3';
            }
        } else {
            $error = 'Error 2';
        }
    } else {
        $error = 'Error 1';
    }
    return $toret;
}

(Las condiciones son arbitrarias...)

Cuantas más condiciones, más grande se vuelve la función, más difícil es de leer.Entonces, si estás en sintonía con el olor del código, te darás cuenta y querrás refactorizar el código.Dos posibles soluciones son:

  • Múltiples devoluciones
  • Refactorización en funciones separadas

Múltiples devoluciones

function isCorrect($param1, $param2, $param3) {
    if ($param1 == $param2)       { $error = 'Error 1'; return false; }
    if ($param1 != ($param3 * 2)) { $error = 'Error 2'; return false; }
    if ($param2 != ($param3 / 3)) { $error = 'Error 3'; return false; }
    return true;
}

Funciones separadas

function isEqual($param1, $param2) {
    return $param1 == $param2;
}

function isDouble($param1, $param2) {
    return $param1 == ($param2 * 2);
}

function isThird($param1, $param2) {
    return $param1 == ($param2 / 3);
}

function isCorrect($param1, $param2, $param3) {
    return !isEqual($param1, $param2)
        && isDouble($param1, $param3)
        && isThird($param2, $param3);
}

Por supuesto, es más largo y un poco complicado, pero en el proceso de refactorizar la función de esta manera, hemos

  • creó una serie de funciones reutilizables,
  • hizo que la función fuera más legible para los humanos, y
  • el foco de las funciones está en por qué los valores son correctos.

Yo diría que deberías tener tantos como sea necesario, o cualquiera que haga que el código sea más limpio (como cláusulas de guardia).

Personalmente, nunca he escuchado ni visto ninguna "mejor práctica" que diga que solo se debe tener una declaración de devolución.

En su mayor parte, tiendo a salir de una función lo antes posible según una ruta lógica (las cláusulas de protección son un excelente ejemplo de esto).

Creo que las devoluciones múltiples suelen ser buenas (en el código que escribo en C#).El estilo de retorno único es un vestigio de C.Pero probablemente no estés codificando en C.

No existe una ley que exija un solo punto de salida para un método en todos los lenguajes de programación..Algunas personas insisten en la superioridad de este estilo, y en ocasiones lo elevan a "regla" o "ley", pero esta creencia no está respaldada por ninguna evidencia o investigación.

Más de un estilo de retorno puede ser un mal hábito en el código C, donde los recursos deben desasignarse explícitamente, pero lenguajes como Java, C#, Python o JavaScript que tienen construcciones como la recolección automática de basura y try..finally bloques (y using bloques en C#), y este argumento no se aplica: en estos lenguajes, es muy poco común necesitar una desasignación manual centralizada de recursos.

Hay casos en los que una declaración única es más legible y casos en los que no lo es.Vea si reduce la cantidad de líneas de código, aclara la lógica o reduce la cantidad de llaves y sangrías o variables temporales.

Por lo tanto, utilice tantos retornos como se adapte a su sensibilidad artística, porque se trata de una cuestión de diseño y legibilidad, no técnica.

he hablado de esto con mayor detalle en mi blog.

Hay cosas buenas que decir acerca de tener un único punto de salida, del mismo modo que hay cosas malas que decir sobre lo inevitable. "flecha" programación que resulta.

Si uso múltiples puntos de salida durante la validación de entradas o la asignación de recursos, trato de colocar todas las 'salidas de error' de manera muy visible en la parte superior de la función.

Ambos Programación espartana artículo de la "SSDSLPedia" y el punto de salida de función única El artículo del "Portland Pattern Repository's Wiki" tiene algunos argumentos interesantes al respecto.Además, por supuesto, hay que considerar esta publicación.

Si realmente desea un único punto de salida (en cualquier lenguaje no habilitado para excepciones), por ejemplo, para liberar recursos en un solo lugar, considero que la aplicación cuidadosa de goto es buena;vea, por ejemplo, este ejemplo bastante artificial (comprimido para guardar el espacio en pantalla):

int f(int y) {
    int value = -1;
    void *data = NULL;

    if (y < 0)
        goto clean;

    if ((data = malloc(123)) == NULL)
        goto clean;

    /* More code */

    value = 1;
clean:
   free(data);
   return value;
}

Personalmente, en general, no me gusta la programación con flechas más que los múltiples puntos de salida, aunque ambos son útiles cuando se aplican correctamente.Lo mejor, por supuesto, es estructurar su programa para que no requiera ninguna de las dos cosas.Dividir su función en varios fragmentos suele ayudar :)

Aunque al hacerlo, encuentro que termino con múltiples puntos de salida de todos modos, como en este ejemplo, donde una función más grande se ha dividido en varias funciones más pequeñas:

int g(int y) {
  value = 0;

  if ((value = g0(y, value)) == -1)
    return -1;

  if ((value = g1(y, value)) == -1)
    return -1;

  return g2(y, value);
}

Dependiendo del proyecto o de las pautas de codificación, la mayor parte del código repetitivo podría reemplazarse por macros.Como nota al margen, dividirlo de esta manera hace que las funciones g0, g1, g2 sean muy fáciles de probar individualmente.

Obviamente, en un lenguaje OO y habilitado para excepciones, no usaría declaraciones if como esa (o ninguna, si pudiera salirme con la mía con poco esfuerzo), y el código sería mucho más sencillo.Y sin flechas.Y la mayoría de los resultados no definitivos probablemente serían excepciones.

En breve;

  • Pocos retornos son mejores que muchos retornos
  • Más de una devolución es mejor que flechas enormes, y cláusulas de guardia en general están bien.
  • Las excepciones probablemente podrían/deberían reemplazar la mayoría de las "cláusulas de protección" cuando sea posible.

Ya conoces el dicho: La belleza esta en los ojos del espectador.

Algunas personas juran por NetBean y algunos por IDEA IntelliJ, algunos por Pitón y algunos por PHP.

En algunas tiendas podrías perder tu trabajo si insistes en hacer esto:

public void hello()
{
   if (....)
   {
      ....
   }
}

La pregunta tiene que ver con la visibilidad y la mantenibilidad.

Soy adicto al uso del álgebra booleana para reducir y simplificar la lógica y el uso de máquinas de estados.Sin embargo, hubo colegas anteriores que creían que mi uso de "técnicas matemáticas" en la codificación no era adecuado, porque no sería visible ni mantenible.Y eso sería una mala práctica.Lo siento gente, las técnicas que empleo son muy visibles y fáciles de mantener para mí, porque cuando vuelvo al código seis meses después, lo entendería claramente en lugar de ver un lío de espaguetis proverbiales.

Oye amigo (como solía decir un antiguo cliente) haz lo que quieras siempre y cuando sepas cómo solucionarlo cuando necesito que lo arregles.

Recuerdo que hace 20 años despidieron a un colega mío por emplear lo que hoy se llamaría desarrollo ágil estrategia.Tenía un meticuloso plan incremental.Pero su gerente le gritaba: "¡No se pueden liberar funciones de forma incremental para los usuarios!Debes seguir con el cascada." Su respuesta al gerente fue que el desarrollo incremental sería más preciso para las necesidades del cliente.Él creía en el desarrollo para las necesidades de los clientes, pero el gerente creía en la codificación según los "requisitos del cliente".

Con frecuencia somos culpables de romper la normalización de datos, MVP y mvc límites.Alineamos en lugar de construir una función.Tomamos atajos.

Personalmente creo que PHP es una mala práctica, pero qué sé yo.Todos los argumentos teóricos se reducen a intentar cumplir un conjunto de reglas.

Calidad = Precisión, mantenimiento y rentabilidad.

Todas las demás reglas pasan a un segundo plano.Y, por supuesto, esta regla nunca desaparece:

La pereza es la virtud de un buen programador.

Me inclino por usar cláusulas de protección para regresar temprano y, de lo contrario, salir al final de un método.La regla de entrada y salida única tiene importancia histórica y fue particularmente útil cuando se trataba de código heredado que ocupaba 10 páginas A4 para un único método C++ con múltiples retornos (y muchos defectos).Más recientemente, una buena práctica aceptada es mantener los métodos pequeños, lo que hace que las salidas múltiples impidan menos la comprensión.En el siguiente ejemplo de Kronoz copiado de arriba, la pregunta es qué ocurre en //Resto del código...?:

void string fooBar(string s, int? i) {

  if(string.IsNullOrEmpty(s) || i == null) return null;

  var res = someFunction(s, i);

  foreach(var r in res) {
      if(!r.Passed) return null;
  }

  // Rest of code...

  return ret;
}

Me doy cuenta de que el ejemplo es algo artificial, pero estaría tentado a refactorizar el para cada bucle en una declaración LINQ que luego podría considerarse una cláusula de protección.Nuevamente, en un ejemplo artificial la intención del código no es evidente y alguna función() puede tener algún otro efecto secundario o el resultado puede usarse en el // Resto del código....

if (string.IsNullOrEmpty(s) || i == null) return null;
if (someFunction(s, i).Any(r => !r.Passed)) return null;

Dando la siguiente función refactorizada:

void string fooBar(string s, int? i) {

  if (string.IsNullOrEmpty(s) || i == null) return null;
  if (someFunction(s, i).Any(r => !r.Passed)) return null;

  // Rest of code...

  return ret;
}

Una buena razón que se me ocurre es el mantenimiento del código:Tienes un único punto de salida.Si desea cambiar el formato del resultado,..., es mucho más sencillo de implementar.Además, para depurar, puedes simplemente colocar un punto de interrupción allí :)

Dicho esto, una vez tuve que trabajar en una biblioteca donde los estándares de codificación imponían "una declaración de devolución por función", y lo encontré bastante difícil.Escribo muchos códigos de cálculos numéricos y, a menudo, hay "casos especiales", por lo que el código terminó siendo bastante difícil de seguir...

Múltiples puntos de salida están bien para funciones lo suficientemente pequeñas, es decir, una función que se puede ver en una pantalla en su totalidad.Si una función larga también incluye múltiples puntos de salida, es una señal de que la función se puede dividir aún más.

Dicho esto, evito las funciones de salida múltiple. a menos que sea absolutamente necesario.He sentido dolor por errores que se deben a algún retorno perdido en alguna línea oscura en funciones más complejas.

He trabajado con estándares de codificación terribles que te obligaban a tener una sola ruta de salida y el resultado casi siempre son espaguetis desestructurados si la función no es trivial: terminas con muchas pausas y continuaciones que simplemente se interponen en el camino.

El punto de salida único, en igualdad de condiciones, hace que el código sea mucho más legible.Pero hay un problema:construcción popular

resulttype res;
if if if...
return res;

es falso, "res=" no es mucho mejor que "return".Tiene una declaración de retorno única, pero múltiples puntos donde la función realmente termina.

Si tiene una función con múltiples retornos (o "res="s), suele ser una buena idea dividirla en varias funciones más pequeñas con un único punto de salida.

Mi política habitual es tener sólo una declaración de devolución al final de una función, a menos que la complejidad del código se reduzca considerablemente al agregar más.De hecho, soy bastante fanático de Eiffel, que impone la única regla de devolución al no tener una declaración de devolución (solo hay una variable de 'resultado' creada automáticamente para colocar el resultado).

Ciertamente, hay casos en los que el código puede aclararse con múltiples retornos de lo que sería la versión obvia sin ellos.Se podría argumentar que se necesita más reelaboración si tiene una función que es demasiado compleja para ser comprensible sin múltiples declaraciones de retorno, pero a veces es bueno ser pragmático en este tipo de cosas.

Si termina con más de unas pocas devoluciones, es posible que haya algún problema con su código.De lo contrario, estaría de acuerdo en que a veces es bueno poder regresar desde varios lugares en una subrutina, especialmente cuando hace que el código sea más limpio.

Perla 6:Mal ejemplo

sub Int_to_String( Int i ){
  given( i ){
    when 0 { return "zero" }
    when 1 { return "one" }
    when 2 { return "two" }
    when 3 { return "three" }
    when 4 { return "four" }
    ...
    default { return undef }
  }
}

Estaría mejor escrito así

Perla 6:Buen ejemplo

@Int_to_String = qw{
  zero
  one
  two
  three
  four
  ...
}
sub Int_to_String( Int i ){
  return undef if i < 0;
  return undef unless i < @Int_to_String.length;
  return @Int_to_String[i]
}

Tenga en cuenta que este fue solo un ejemplo rápido.

Voto por el retorno único al final como guía.Esto ayuda a un manejo de limpieza de código común ...Por ejemplo, eche un vistazo al siguiente código...

void ProcessMyFile (char *szFileName)
{
   FILE *fp = NULL;
   char *pbyBuffer = NULL:

   do {

      fp = fopen (szFileName, "r");

      if (NULL == fp) {

         break;
      }

      pbyBuffer = malloc (__SOME__SIZE___);

      if (NULL == pbyBuffer) {

         break;
      }

      /*** Do some processing with file ***/

   } while (0);

   if (pbyBuffer) {

      free (pbyBuffer);
   }

   if (fp) {

      fclose (fp);
   }
}

Esta es probablemente una perspectiva inusual, pero creo que cualquiera que crea que se deben favorecer las declaraciones de devolución múltiples nunca ha tenido que usar un depurador en un microprocesador que admita solo 4 puntos de interrupción de hardware.;-)

Si bien los problemas del "código de flecha" son completamente correctos, un problema que parece desaparecer cuando se utilizan múltiples declaraciones de devolución es la situación en la que se utiliza un depurador.No tiene una posición general conveniente para colocar un punto de interrupción que garantice que verá la salida y, por lo tanto, la condición de retorno.

Cuantas más declaraciones de retorno tenga en una función, mayor será la complejidad de ese método.Si se pregunta si tiene demasiadas declaraciones de devolución, es posible que desee preguntarse si tiene demasiadas líneas de código en esa función.

Pero no, no hay nada de malo en una o varias declaraciones de devolución.En algunos lenguajes, es una mejor práctica (C++) que en otros (C).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top