Pregunta ¿Es una mala práctica usar el retorno dentro de un método vacío?


Imagine el siguiente código:

void DoThis()
{
    if (!isValid) return;

    DoThat();
}

void DoThat() {
    Console.WriteLine("DoThat()");
}

¿Está bien usar un retorno dentro de un método vacío? ¿Tiene alguna penalización de rendimiento? O sería mejor escribir un código como este:

void DoThis()
{
    if (isValid)
    {
        DoThat();
    }
}

75
2017-08-16 02:05


origen


Respuestas:


Un retorno en un método de vacío no es malo, es una práctica común para invertir if declaraciones para reducir la anidación.

Y tener menos anidamiento en sus métodos mejora la capacidad de lectura y mantenimiento del código.

En realidad, si tiene un método nulo sin ninguna declaración de retorno, el compilador siempre generará un instrucción ret al final de eso.


153
2017-08-16 02:11



Existe otra gran razón para usar guardias (a diferencia del código anidado): si otro programador agrega código a su función, están trabajando en un entorno más seguro.

Considerar:

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }
}

versus:

void MyFunc(object obj)
{
    if (obj == null)
        return;

    obj.DoSomething();
}

Ahora, imagine que otro programador agrega la línea: obj.DoSomethingElse ();

void MyFunc(object obj)
{
    if (obj != null)
    {
        obj.DoSomething();
    }

    obj.DoSomethingElse();
}

void MyFunc(object obj)
{
    if (obj == null)
        return;

    obj.DoSomething();
    obj.DoSomethingElse();
}

Obviamente, este es un caso simplista, pero el programador ha agregado un bloqueo al programa en la primera instancia (código anidado). En el segundo ejemplo (salida temprana con guardias), una vez que pasa el guardia, su código está a salvo del uso involuntario de una referencia nula.

Claro, un gran programador no comete errores como este (a menudo). Pero es mejor prevenir que curar; podemos escribir el código de una manera que elimine por completo esta fuente potencial de errores. El anidamiento agrega complejidad, por lo que las mejores prácticas recomiendan el código de refactorización para reducir la anidación.


26
2017-08-16 06:52



¿¿¿Mala práctica??? De ninguna manera. De hecho, siempre es mejor manejar validaciones volviendo del método lo antes posible si las validaciones fallan. De lo contrario, resultaría en una gran cantidad de ifs y más anidados. Terminar temprano mejora la legibilidad del código.

También verifique las respuestas en una pregunta similar: ¿Debo usar return / continue statement en lugar de if-else?


17
2017-08-16 03:36



No es una mala práctica (por todos los motivos ya mencionados). Sin embargo, cuantas más vueltas tengas en un método, es más probable que se divida en métodos lógicos más pequeños.


6
2017-08-16 04:35



El primer ejemplo es usar una declaración de guardia. De Wikipedia:

En la programación de computadoras, un guardia es un   expresión booleana que debe evaluar   verdadero si la ejecución del programa es   continuar en la rama en cuestión.

Creo que tener un grupo de guardias en la cima de un método es una forma perfectamente comprensible de programar. Básicamente dice "no ejecutes este método si alguno de estos es verdadero".

Entonces, en general, le gustaría esto:

void DoThis()
{
  if (guard1) return;
  if (guard2) return;
  ...
  if (guardN) return;

  DoThat();
}

Creo que eso es mucho más legible entonces:

void DoThis()
{
  if (guard1 && guard2 && guard3)
  {
    DoThat();
  }
}

4
2017-08-16 06:07



No hay una penalización de rendimiento, sin embargo, la segunda parte del código es más legible y, por lo tanto, más fácil de mantener.


2
2017-08-16 02:08



Está perfectamente bien y no hay 'penalización por rendimiento', pero nunca escriba una declaración 'si' sin corchetes.

Siempre

if( foo ){
    return;
}

Es mucho más legible; y nunca asumirá accidentalmente que algunas partes del código están dentro de esa declaración cuando no lo están.


2
2017-08-16 02:16