** EDITAR: Hay varias opciones a continuación que funcionarían. Por favor vote/comente de acuerdo a sus puntos de vista sobre el asunto.Método Refactor con múltiples puntos de retorno
estoy trabajando en la limpieza y la adición de la funcionalidad de aC# método con la siguiente estructura básica:
public void processStuff()
{
Status returnStatus = Status.Success;
try
{
bool step1succeeded = performStep1();
if (!step1succeeded)
return Status.Error;
bool step2suceeded = performStep2();
if (!step2suceeded)
return Status.Warning;
//.. More steps, some of which could change returnStatus..//
bool step3succeeded = performStep3();
if (!step3succeeded)
return Status.Error;
}
catch (Exception ex)
{
log(ex);
returnStatus = Status.Error;
}
finally
{
//some necessary cleanup
}
return returnStatus;
}
Hay muchos pasos, y en la mayoría de los casos el paso x deben tener éxito con el fin de continuar con el paso x + 1. Ahora, necesito agregar alguna funcionalidad que siempre se ejecutará al final del método, pero que depende del valor de retorno. Estoy buscando recomendaciones sobre cómo refactorizar limpiamente esto para el efecto deseado. La elección obvia sería poner la funcionalidad que depende del valor de retorno en el código de llamada, pero no puedo modificar las llamadas.
Una opción:
public void processStuff()
{
Status returnStatus = Status.Success;
try
{
bool step1succeeded = performStep1();
if (!step1succeeded)
{
returnStatus = Status.Error;
throw new Exception("Error");
}
bool step2succeeded = performStep2();
if (!step2succeeded)
{
returnStatus = Status.Warning;
throw new Exception("Warning");
}
//.. the rest of the steps ..//
}
catch (Exception ex)
{
log(ex);
}
finally
{
//some necessary cleanup
}
FinalProcessing(returnStatus);
return returnStatus;
}
Esto parece un poco feo para mí. En cambio, podría lanzar directamente desde los métodos performStepX(). Sin embargo, esto deja el problema de establecer la variable returnStatus apropiadamente en el bloque catch de processStuff(). Como habrá notado, el valor devuelto al fallar un paso de procesamiento depende del paso que falló.
public void processStuff()
{
Status returnStatus = Status.Success;
try
{
bool step1succeeded = performStep1(); //throws on failure
bool step2succeeded = performStep2(); //throws on failure
//.. the rest of the steps ..//
}
catch (Exception ex)
{
log(ex);
returnStatus = Status.Error; //This is wrong if step 2 fails!
}
finally
{
//some necessary cleanup
}
FinalProcessing(returnStatus);
return returnStatus;
}
Agradecería cualquier sugerencia que pueda tener.
Definitivamente estoy de acuerdo con la primera mitad de su respuesta. Aquí hay algunas buenas respuestas que mejorarían la legibilidad sin violar ese principio. – jheddings
Tal como está, no se comporta como se requiere. Necesito hacer algo al final del método que depende del valor de retorno. Y, como digo, no puedo cambiar el código de llamada. – Odrade
Lo siento @Odrade Olvidé que necesitabas cambiar la funcionalidad. Vea si mi respuesta actualizada lo ayuda. –