Pregunta

He estado haciendo una revisión masiva del código y un patrón que noto por todas partes es este:

public bool MethodName()
{
    bool returnValue = false;
    if (expression)
    {
        // do something
        returnValue = MethodCall();
    }
    else
    {
        // do something else
        returnValue = Expression;
    }

    return returnValue;
}

No es así como hubiera hecho esto, simplemente habría devuelto el valor cuando supiera de qué se trataba. ¿Cuál de estos dos patrones es más correcto?

Insisto en que la lógica siempre parece estar estructurada de tal manera que el valor de retorno se asigna en una sola tabla y no se ejecuta ningún código después de que se asigna.

¿Fue útil?

Solución

Hay una larga discusión sobre este tema aquí .

Otros consejos

Mucha gente recomienda tener solo un punto de salida de sus métodos. El patrón que describe arriba sigue esa recomendación.

La esencia principal de esa recomendación es que si tiene que limpiar alguna memoria o estado antes de regresar del método, es mejor tener ese código en un solo lugar. tener múltiples puntos de salida conduce a la duplicación del código de limpieza o problemas potenciales debido a la falta de código de limpieza en uno o más de los puntos de salida.

Por supuesto, si su método tiene un par de líneas de largo, o no necesita ninguna limpieza, podría tener múltiples retornos.

Hubiera usado ternary, para reducir las estructuras de control ...


return expression ? MethodCall() : Expression;

Sospecho que estaré en minoría pero me gusta el estilo presentado en el ejemplo. Es fácil agregar una declaración de registro y establecer un punto de interrupción, IMO. Además, cuando se usa de manera consistente, parece más fácil & "; Coincidencia de patrón &"; que tener múltiples devoluciones.

No estoy seguro de que haya un " correcto " responda a esto, sin embargo.

Algunos institutos de aprendizaje y libros abogan por la práctica del retorno único.

Si es mejor o no es subjetivo.

Eso parece parte de un mal diseño de OOP. Quizás debería ser refactorizado en el nivel más alto que dentro de un solo método.

De lo contrario, prefiero usar un operador ternario, como este:

return expression ? MethodCall() : Expression;

Es más corto y más legible.

Regrese de un método de inmediato en cualquiera de estas situaciones:

  1. Ha encontrado una condición límite y necesita devolver un valor único o centinela: if (node.next = null) return NO_VALUE_FOUND;
  2. Un valor / estado requerido es falso, por lo que el resto del método no se aplica (también conocido como cláusula de protección). Por ejemplo: if (listeners == null) return null;
  3. El propósito del método es encontrar y devolver un valor específico, por ejemplo: if (nodes[i].value == searchValue) return i;
  4. Estás en una cláusula que devuelve un valor único del método que no se usa en otra parte del método: if (userNameFromDb.equals(SUPER_USER)) return getSuperUserAccount();

De lo contrario, es útil tener una sola declaración de retorno para que sea más fácil agregar el registro de depuración, la limpieza de recursos y seguir la lógica. Intento manejar los 4 casos anteriores primero, si se aplican, luego declaro una variable llamada result(s) lo más tarde posible y le asigno valores según sea necesario.

Ambos realizan la misma tarea. Algunos dicen que un método solo debe tener una entrada y un punto de salida.

Yo también uso esto. La idea es que los recursos se pueden liberar en el flujo normal del programa. Si salta de un método en 20 lugares diferentes y necesita llamar a cleanUp () antes, deberá agregar otro método de limpieza 20 veces (o refactorizar todo)

Supongo que el codificador ha tomado el diseño de definir un objeto para Volver en la parte superior del método (por ejemplo, Lista < Foo > toReturn = new ArrayList < Foo gt; ();) y luego completarlo durante la llamada al método, y de alguna manera decidió aplicarlo a un tipo de retorno booleano, que es extraño.

También podría ser un efecto secundario de un estándar de codificación que establece que no puede regresar en el medio del cuerpo de un método, solo al final.

Incluso si no se ejecuta ningún código después de que se asigne el valor de retorno ahora, no significa que algún código no tendrá que agregarse más tarde.

No es el código más pequeño que podría usarse, pero es muy fácil de refactorizar.

Delphi fuerza este patrón creando automáticamente una variable llamada " Resultado " que será del tipo de retorno de la función. Lo que sea & Quot; Resultado & Quot; es cuando sale la función, es su valor de retorno. Entonces no hay & Quot; return & Quot; palabra clave en absoluto.

function MethodName : boolean;
begin
  Result := False;
  if Expression then begin
    //do something
    Result := MethodCall;
  end
  else begin
    //do something else
    Result := Expression;
  end;

  //possibly more code
end;

El patrón utilizado es detallado, pero también es más fácil de depurar si desea conocer el valor de retorno sin abrir la ventana Registros y verificar EAX.

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