Es volver temprano a partir de una función más elegante que una declaración de si?

StackOverflow https://stackoverflow.com/questions/355670

  •  21-08-2019
  •  | 
  •  

Pregunta

Yo y un colega tiene una disputa acerca de cuál de los siguientes es más elegante.No voy a decir quién es quién, así que es imparcial.Lo que es más elegante?

public function set hitZone(target:DisplayObject):void
        {
            if(_hitZone != target)
            {
                _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
                _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
                _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

                _hitZone = target;

                _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
                _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
                _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);
            }
        }

...o...

public function set hitZone(target:DisplayObject):void
        {
            if(_hitZone == target)return;

            _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
            _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
            _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

            _hitZone = target;

            _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
            _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
            _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);

        }
¿Fue útil?

Solución

Este es uno de esos casos en los que está bien romper las reglas (es decir, mejores prácticas). En general, usted quiere tener el menor número de puntos de retorno en función de lo posible. La razón práctica de esto es que simplifica la lectura del código, ya que sólo siempre se puede asumir que todos y cada función se llevará a sus argumentos, hacer su lógica, y devolver su resultado. Poner en rendimientos adicionales para diversos casos tiende a complicar la lógica y aumentar la cantidad de tiempo necesario para leer y asimilar plenamente el código. Una vez que el código llega a la etapa de mantenimiento a continuación, múltiples retornos pueden tener un gran impacto en la productividad de los nuevos programadores, ya que tratar de descifrar la lógica (especialmente su mala cuando los comentarios son escasos y el código no está claro). El problema crece exponencialmente con respecto a la longitud de la función.

Entonces, ¿por qué en este caso qué todo el mundo prefiere la opción 2? Es porque estás a configurar un contrato que hace cumplir la función a través de la validación de datos de entrada, u otros invariantes que podrían necesitar ser comprobado. La sintaxis más bonita para la construcción de la validación es la comprobación de cada condición, volviendo inmediatamente si la condición falla validez. De esa manera usted no tiene que mantener algún tipo de isValid booleano través de todos sus cheques.

Para resumir las cosas: en realidad estamos mirando cómo escribir código de validación y no la lógica general; La opción 2 es mejor para el código de validación.

Otros consejos

En la mayoría de los casos, volver temprano reduce la complejidad y hace que el código sea más legible.

Es también una de las técnicas aplicadas en Spartan programación:

Uso mínimo de Control

  1. Minimizar el uso de las oraciones condicionales mediante especializados construcciones ternarization, la herencia, y las clases, tales como la Clase Los valores predeterminados, la Clase y Clase Separador de
  2. La simplificación de las oraciones condicionales con los principios de return.
  3. Minimizar el uso de construcciones de bucle mediante la acción aplicador clases tales como Clase Independiente y Clase FileSystemVisitor.
  4. La simplificación de la lógica de la iteración con las primeras salidas (a través de return, continue y break declaraciones).

En tu ejemplo, yo elegiría la opción 2, ya que hace que el código sea más legible.Yo uso la misma técnica cuando la comprobación de los parámetros de la función.

Mientras que los primeros resultados se organizan como un bloque en la parte superior del cuerpo de la función / método, entonces creo que son mucho más legible que la adición de otra capa de anidación.

Trato de evitar los primeros resultados en la parte media del cuerpo. A veces son la mejor manera, pero la mayoría de las veces creo que complican.

También, como regla general trato de minimizar las estructuras de control de anidación. Obviamente se puede tomar esta demasiado lejos, así que hay que utilizar un poco de discreción. Convertir anidado si de un interruptor a simple / caso es mucho más claro para mí, incluso si los predicados repiten algunos sub-expresiones (y suponiendo que esto no es un bucle de rendimiento crítica en un lenguaje demasiado tonto para hacer la eliminación de subexpresiones). Particularmente me gusta la combinación de ifs anidados en los órganos de la función / método largos, ya que si usted salta en el medio del código por alguna razón se termina el desplazamiento hacia arriba y hacia abajo para reconstruir mentalmente el contexto de una línea dada.

En mi experiencia, el problema con el uso de los primeros resultados de un proyecto es que si otros en el proyecto no se usan a ellos, no van a buscarlos. Así devoluciones o temprano no -. Si hay varios programadores involucrados, asegúrese de que todo el mundo está al menos consciente de su presencia

Yo personalmente escribir código para volver tan pronto como pueda, ya que el retrasar el retorno a menudo introduce una complejidad adicional, por ejemplo tratando de salir con seguridad un grupo de bucles anidados y condiciones.

Así que cuando miro a una función desconocida, la primera cosa que hago es buscar toda la return s. Lo que realmente ayuda a que hay que configurar el coloreado de sintaxis para dar <=> un color diferente de cualquier otra cosa. (Voy para el rojo.) De esta manera, el <=> s se convierten en una herramienta útil para la determinación de lo que hace la función, en lugar de ocultos piedras de tropiezo para los incautos.

Ah el guardián.

En mi humilde opinión, sí - la lógica de que es más claro porque el retorno es explícita y justo al lado de la condición, y puede ser muy bien agrupado con estructuras similares. Esto es aún más aplicable cuando "retorno" se sustituye por "throw new Exception".

Como se dijo antes, pronto retorno es más fácil de leer, especialmente si el cuerpo de una función es largo, es posible que la eliminación de un} por error en una función 3 página (wich en sí mismo no es muy elegante) y tratando de recopilar puede tardar varios minutos de depuración no automatizables.

También hace que el código sea más declarativa, porque esa es la forma en que lo describiría a otro ser humano, por lo que, probablemente, un desarrollador es suficiente para un cierre de entenderlo.

Si la complejidad de los aumentos de función más tarde, y que tiene buenas pruebas, sólo tiene que envolver cada alternativa en una nueva función, y llamarlos en caso de ramas, de esa manera Mantenemos el estilo declarativo.

En este caso (una prueba, sin cláusula else) me gusta la prueba y vuelta. Se deja claro que en ese caso, no hay nada que hacer, sin tener que leer el resto de la función.

Sin embargo, esto es dividir el mejor de los pelos. Estoy seguro de que debe tener asuntos más importantes de las que preocuparse:)

La opción 2 es más fácil de leer, pero la capacidad de administración del código falla cuando una persona se puede requerir que se añade.

Así que si está seguro, no hay otra cosa vaya por la opción 2, pero si podría existir la posibilidad de una condición más, entonces yo preferiría la opción 1

La opción 1 es mejor, ya que debe tener un número mínimo de puntos de retorno en el procedimiento. Hay excepciones como

  if (a) {
    return x;
  }
  return y;

debido a la forma en que un lenguaje funciona, pero en general es mejor tener el menor número de puntos de salida, ya que es factible.

Yo prefiero evitar un retorno inmediato al comienzo de una función, y siempre que sea posible poner la lógica de clasificación para evitar la entrada al método antes de que sea llamado. Por supuesto, esto varía dependiendo de la finalidad del método.

Sin embargo, no me importa volver en el medio del método, siempre que el método es corto y fácil de leer. En el caso de que el método es grande, en mi opinión, ya no es muy legible, por lo que o bien será reprogramado para múltiples funciones con retornos en línea, o se romperá explícitamente de la estructura de control con una sola vuelta al final.

Me siento tentado a cerrarla como duplicado exacto, ya que vi algunos temas similares ya, incluyendo Invertir‘if’para reducir la anidación que tiene buenas respuestas.

dejaré que viven por ahora ... ^ _ ^

Para hacer que una respuesta, yo soy un creyente de que el regreso pronto como la cláusula de protección es mejor que pasaría profundamente anidados.

He visto a ambos tipos de códigos y prefiero primero, ya que se ve fácilmente legible y comprensible para mí, pero he leído muchos lugares que existen temprana es el mejor camino a seguir.

Hay al menos otra alternativa. Separar los detalles del trabajo real de la decisión sobre si se debe realizar el trabajo. Algo parecido a lo siguiente:

public function setHitZone(target:DisplayObject):void
    {
        if(_hitZone != target)
            setHitZoneUnconditionally(target);

    }

public function setHitZoneUnconditionally(target:DisplayObject):void
    {
        _hitZone.removeEventListener(MouseEvent.ROLL_OVER, onBtOver);
        _hitZone.removeEventListener(MouseEvent.ROLL_OUT, onBtOut);
        _hitZone.removeEventListener(MouseEvent.MOUSE_DOWN, onBtDown);

        _hitZone = target;

        _hitZone.addEventListener(MouseEvent.ROLL_OVER, onBtOver, false, 0, true);
        _hitZone.addEventListener(MouseEvent.ROLL_OUT, onBtOut, false, 0, true);
        _hitZone.addEventListener(MouseEvent.MOUSE_DOWN, onBtDown, false, 0, true);

    }

Cualquiera de estos tres (dos más que su tercer arriba) son razonables para casos tan pequeños como este. Sin embargo, sería una mala cosa tener una función de cientos de líneas de largo con múltiples "puntos de rescate financiero" salpicado en todas partes.

He tenido este debate con mi propio código largo de los años. Empecé a favorecer a una vida de retorno y poco a poco han caducado.

En este caso, prefiero la opción 2 (una vuelta), simplemente porque sólo estamos hablando de 7 líneas de código envueltos por un caso de () sin ninguna otra complejidad. Es mucho más fácil de leer y funciones similares. Fluye arriba a abajo. Usted sabe que se inicia en la parte superior y al final en la parte inferior.

Dicho esto, como otros han dicho, si había más guardias al principio o mayor complejidad o si la función crece, entonces yo preferiría la opción 1:. Regresar inmediatamente al comienzo de una validación sencilla

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