A veces me encuentro con un código similar al siguiente ejemplo (lo que esta función hace exactamente está fuera del alcance de esta pregunta):
function doSomething(value) {
if (check1(value)) {
return -1;
}
else if (check2(value)) {
return value;
}
else {
return false;
}
}
Como se puede ver, if
, else if
y else
las declaraciones se utilizan en conjunción con el return
comunicado. Esto parece bastante intuitivo para un observador casual, pero creo que sería más elegante (desde la perspectiva de un desarrollador de software) eliminar los else
-s y simplificar el código de esta manera:
function doSomething(value) {
if (check1(value)) {
return -1;
}
if (check2(value)) {
return value;
}
return false;
}
Esto tiene sentido, ya que todo lo que sigue a una return
declaración (en el mismo ámbito) nunca se ejecutará, haciendo que el código anterior sea semánticamente igual al primer ejemplo.
¿Cuál de los anteriores se ajusta más a las buenas prácticas de codificación? ¿Hay algún inconveniente en cualquiera de los métodos con respecto a la legibilidad del código?
Editar: se ha hecho una sugerencia duplicada con esta pregunta como referencia. Creo que mi pregunta toca un tema diferente, ya que no estoy preguntando por evitar declaraciones duplicadas como se presenta en la otra pregunta. Ambas preguntas buscan reducir las repeticiones, aunque de maneras ligeramente diferentes.
fuente
else
es menor, el mayor problema es que obviamente está devolviendo dos tipos de datos de una sola función, lo que hace que la API de la función sea impredecible.-1
es un número,false
es un booleano yvalue
no se especifica aquí, por lo que podría ser cualquier tipo de objeto.value
que en realidad sea un número entero. Si puede ser algo, eso es aún peor.Respuestas:
Me gusta el que no tiene
else
y he aquí por qué:Porque hacer eso no rompió nada de lo que se suponía que no debía hacerlo.
Odio la interdependencia en todas sus formas (incluida la denominación de una función
check2()
). Aísle todo lo que pueda aislarse. A veces necesitaselse
pero no veo eso aquí.fuente
if
bloque de} //else
para aclarar, al leer el código, que la única ejecución prevista después delif
bloque de código es si la condición en laif
declaración era falsa. Sin algo como esto, particularmente si el código dentro delif
bloque se vuelve más complejo, puede que no esté claro para quien está manteniendo el código que la intención era nunca ejecutar más allá delif
bloque cuando laif
condición es verdadera.if
para dejar en claro que esta sección de código está hecha y la estructura está terminada. Para hacer esto, hago lo que no he hecho aquí (porque no quería distraerme del punto principal del OP haciendo otros cambios). Hago lo más simple que puedo para lograr todo eso sin distraerme. Añado una línea en blanco.Creo que depende de la semántica del código. Si sus tres casos dependen uno del otro, indíquelo explícitamente. Esto aumenta la legibilidad del código y hace que sea más fácil de entender para cualquier otra persona. Ejemplo:
Aquí depende claramente del valor de
x
en los tres casos. Si omitiera el últimoelse
, esto sería menos claro.Si sus casos no dependen directamente el uno del otro, omítalo:
Es difícil mostrar esto en un ejemplo simple sin contexto, pero espero que entiendas mi punto.
fuente
Yo prefiero la segunda opción (separar
ifs
sinelse if
y principiosreturn
) pero eso es todo el tiempo que los bloques de código son cortos .Si los bloques de código son largos, es mejor usarlo
else if
, porque de lo contrario no tendría una comprensión clara de los diversos puntos de salida que tiene el código.Por ejemplo:
En ese caso, es mejor usarlo
else if
, almacenar el código de retorno en una variable y tener solo una oración de retorno al final.Pero como uno debería esforzarse por que las funciones sean cortas, yo diría que sea breve y salga temprano como en su primer fragmento de código.
fuente
return
está dentro de 3 líneas deif
modo que no es tan diferente queelse if
incluso después de 200 líneas de código. El estilo de retorno único que presenta aquí es una tradición de c y otros lenguajes que no informan errores con excepciones. El objetivo era crear un lugar único para limpiar los recursos. Los lenguajes de excepción usan unfinally
bloque para eso. Supongo que esto también crea un lugar para poner un punto de interrupción si su depurador no le permite poner uno en las funciones de cierre de llaves.retVal
en absoluto. Si puede salir de una función de manera segura, hágalo de inmediato, sin asignar el valor seguro que se devolverá a una variable de una sola salida de la función. Cuando usa el punto de retorno único en una función realmente larga, generalmente no confío en otros programadores y termino buscando en el resto de la función también otras modificaciones del valor de retorno. Fallar rápido y regresar temprano son, entre otras, dos reglas por las que vivo.Yo uso ambos en diferentes circunstancias. En una verificación de validación, omito lo demás. En un flujo de control, uso lo demás.
vs
El primer caso se lee más como si estuviera comprobando todos los requisitos previos primero, quitándolos del camino y luego avanzando al código real que desea ejecutar. Como tal, el código jugoso que realmente desea ejecutar pertenece directamente al alcance de la función; de eso se trata realmente la función.
El segundo caso se lee más como si ambas rutas fueran un código válido para ejecutarse que son tan relevantes para la función como el otro en función de alguna condición. Como tal, pertenecen en niveles de alcance similares entre sí.
fuente
La única situación que he visto que realmente importa es un código como este:
Claramente hay algo mal aquí. El problema es que no está claro si
return
debe agregarse oArrays.asList
eliminarse. No puede solucionar esto sin una inspección más profunda de los métodos relacionados. Puede evitar esta ambigüedad utilizando siempre bloques if-else completamente exhaustivos. Esta:no se compilará (en idiomas estáticamente controlados) a menos que agregue un retorno explícito primero
if
.Algunos idiomas ni siquiera permiten el primer estilo. Intento usarlo solo en un contexto estrictamente imperativo o para condiciones previas en métodos largos:
fuente
Tener tres salidas de la función como esa es realmente confuso si está tratando de seguir el código y una mala práctica.
Si tiene un único punto de salida para la función, se requieren los otros.
De hecho, vamos aún más lejos.
Es justo que pueda argumentar por un solo retorno temprano de la validación de entrada. Simplemente evite envolver todo el volumen si su lógica en un if.
fuente
Prefiero omitir la declaración redundante else. Cada vez que lo veo (en la revisión de código o refactorización) me pregunto si el autor entendió el flujo de control y que podría haber un error en el código.
Si el autor creía que la declaración else era necesaria y, por lo tanto, no entendía las implicaciones del flujo de control de la declaración return, tal falta de comprensión es una fuente importante de errores, en esta función y en general.
fuente