Pregunta

Teniendo en cuenta los siguientes fragmentos de código, ¿hay alguna diferencia apreciable?

public boolean foo(int input) {
   if(input > 10) {
       doStuff();
       return true;
   }
   if(input == 0) {
       doOtherStuff();
       return true;
   }

   return false;
}

vs.

public boolean foo(int input) {
   if(input > 10) {
      doStuff();
      return true;
   } else if(input == 0) {
      doOtherStuff();
      return true;
   } else {
      return false;
   }
}

O sería el principio de una sola salida será mejor aquí con esta pieza de código ...

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

¿Hay alguna diferencia de rendimiento perceptible? ¿Se siente uno es más o menos mantenible / legible que los demás?

¿Fue útil?

Solución

Con el segundo ejemplo usted indica muy claramente que ambas condiciones son mutuamente excluyentes.
Con el primero, no es tan claro, y en el caso (poco probable) que se añade una asignación a input entre ambos IFS, la lógica cambiaría.
Supongamos que alguien en el futuro añade input = 0 antes de la segunda si.
Por supuesto que esto es poco probable que suceda, pero si estamos hablando de mantenimiento aquí, si otra cosa-dice claramente que no son mutuamente exclusivas condiciones, mientras que un montón de IFS no lo hacen, y no son tan dependientes entre sí como si son -else bloques.

editar:. Ahora que veo, en este ejemplo particular, el retorno cláusula fuerzas de la exclusividad mutua, pero de nuevo, estamos hablando de mantenimiento y facilidad de lectura

De todos modos, sobre la marcha, si esto está codificado en Java que debe cuidar de no cumplimiento de un par de si los bloques, si se incrusta C en un hardware muy lento, tal vez, pero ciertamente no con java.

Otros consejos

Usar cualquier forma mejor describe su intención.

No siga el principio de salida solo si las cosas son así de simple, sin embargo - sólo lo hace más confuso

.
  • En el primero:

    a alguien con el tiempo, por alguna extraña razón y cuando usted no está buscando agregará alguna declaración complemento que hará que este método falle bajo ciertas condiciones extrañas, todo el mundo (o peor, una sola persona) pasarán 4 horas. viendo el código fuente y depuración de la aplicación a fin encontró que había algo en el medio.

  • La segunda es definitivamente mejor, no sólo se evita este escenario, sino que también ayuda a establecer claramente, que este o esta otra no más.

    Si todo el código que escribimos dentro de un if donde 10 líneas de largo como máximo, esto no importaría realmente, pero lamentablemente ese no es el caso, no existe otros programadores que, por alguna razón considera que un si el cuerpo debe ser> 200 líneas de largo ... de todos modos.

  • No me gusta el tercero, me obliga a buscar la variable de retorno, y es más fácil de encontrar el return palabra clave

Sobre el rendimiento de velocidad, que son (casi) idénticos. No se preocupe por eso.

En el último ejemplo, no hacer esto:

public boolean foo(int input) {
   boolean toBeReturned = false;
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   }

   return toBeReturned;
}

pero esto (aviso el uso de Java final ):

public boolean foo(int input) {
   final boolean toBeReturned;    // no init here
   if(input > 10) {
      doStuff();
      toBeReturned = true;
   } else if(input == 0) {
      doOtherStuff();
      toBeReturned = true;
   } else {
      toBeReturned = false;
   }
   return toBeReturned;
}

De esta manera usted hace su intención clara y esto es un regalo del cielo para los entornos de desarrollo de apoyo "programación por intención" (no hay necesidad de "compilación" para ver posibles errores, incluso en un AST parcial, un IDE buena puede examinar fuente incompleta en tiempo real y le dará advertencias instantáneas).

De esta manera usted es seguro no olvidar para inicializar el valor de retorno. Esto es grande si más adelante decide que después de todo lo que necesita otra condición.

Lo hago todo el tiempo y más aún desde que empecé a usar IntelliJ IDEA (versión 4 o así, hace mucho tiempo) y esto me ha salvado tantos errores de distracción tonta ...

Algunas personas argumentan que esto es demasiado código para un caso tan simple, pero que está completamente ausente el punto: el punto es hacer que el tan clara intención de que el código se lee con facilidad y se puede ampliar fácilmente más adelante, sin olvidar accidentalmente para asignar toBeReturned y sin querer olvidarse de volver de una cláusula más tarde puede añadir.

De lo contrario, si la "concisión" era el nombre del juego, a continuación, me gustaría escribir:

public boolean foo(int a) {
  return a > 10 ? doStuff() : a == 0 ? doOtherStuff() : false; 
}

Cuando ambos hacerTarea y doOtherStuff volvería realidad.

Semánticamente - no. En cuanto al rendimiento esto depende del compilador, es decir, si se puede detectar que ambas condiciones no pueden ser verdaderas a la vez. Apostaría estándar de Sun compilador de lata. Si se debe utilizar la salida principio solo depende de los gustos. Yo personalmente odio.

Versión # 1 y # 2 tienen que ser más rápido que # 3, pero supongo que la diferencia de rendimiento es mínimo. Yo preferiría centrarse en legibilidad .

En lo personal, yo nunca utilizar la versión # 2. Entre # 1 y # 3, elegiría el que los rendimientos del código más legible para el caso en cuestión. No me gustan muchos puntos de salida en mis métodos, ya que hace que el código sea difícil de analizar. Sin embargo, hay casos en los que el flujo se vuelve más claro cuando salga inmediatamente para algunos casos especiales, y continuamos con los casos principales.

Piense en este caso cuando los dos ejemplos no serán similares:

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        }
        System.out.println("do some other intermediary stuff");
        if (input == 0) {
            // doOtherStuff();
            return true;
        }

        return false;
    }

vs.

    public boolean foo(int input) {
        if (input > 10) {
            // doStuff();
            return true;
        } 
        //System.out.println("doing some intermediary stuff... doesn't work");
        else if (input == 0) {
            // doOtherStuff();
            return true;
        } else {
            return false;
        }
        return false;
    }

El primer enfoque es probablemente más flexible , pero ambos fórmulas tienen su uso en diferentes circunstancias.

En cuanto al rendimiento, creo que las diferencias son pequeñas para ser tomada en consideración, para cualquier aplicación java regular, codificado por programadores sanos:)

.

En el caso de que el segundo si sólo se llama si la primera si no por lo que es menos importante aquí, pero si el primero si hizo algo que no retornaron, el segundo caso (que entonces siempre será falsa) seguiría siendo probado a menos que fuera en un else-IF.

En otras palabras, hay casos en que la diferencia entre if-else-if e if-si las cosas, pero esto no es uno de ellos.

Ejemplo: Prueba esto y luego probarlo después de la eliminación de la persona. Se obtienen dos salidas diferentes:

int someNumber = 1;
if(someNumber < 5)
{
    someNumber += 5;
    Console.WriteLine("First call.");
}
else if(someNumber >= 5)
{
    Console.WriteLine("Second call.");
}

Entre el primer y segundo fragmentos, no hay realmente ninguna diferencia. Sin embargo, el tercer fragmento es bastante ineficiente. Debido a que esperas para devolver el control del programa a la persona que llama hasta que la última línea de código en el método, los desechos del procesamiento de alimentación / memoria, mientras que los dos primeros fragmentos de código devuelve el control tan pronto como se determina una de las condiciones para ser verdad.

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