Pregunta

Algo como esto (sí, esto no se ocupa de algunos casos extremos - que no es el punto):

int CountDigits(int num) {
    int count = 1;
    while (num >= 10) {
        count++;
        num /= 10;
    }
    return count;
}

¿Cuál es su opinión sobre esto? Es decir, utilizando argumentos de la función como variables locales.
Ambos se colocan en la pila, y un rendimiento más o menos idéntica sabia, me pregunto acerca de las mejores prácticas-aspectos de este.
Me siento como un idiota cuando agrego una línea adicional y bastante redundante para que la función que consiste en int numCopy = num, sin embargo lo hace me fallo.
¿Qué piensas? Si esto se evita?

¿Fue útil?

Solución

  1. Como regla general, no me utilizar un parámetro de función como una variable de procesamiento local, es decir, parámetros de la función I tratan como de sólo lectura.

    En mi mente, de manera intuitiva código understandabie es de suma importancia para el mantenimiento y la modificación de un parámetro de función para utilizar como variable de procesamiento local tiende para ir en contra de ese objetivo. He llegado a esperar que un parámetro tendrá el mismo valor en el medio e inferior de un método como lo hace en la parte superior. Plus, una variable de procesamiento local bien llamada puede mejorar la comprensibilidad.

    Sin embargo, como dice @Stewart, esta regla es más o menos importante en función de la longitud y complejidad de la función. Para las funciones cortas y simples como el que usted muestra, simplemente usando el parámetro en sí puede ser más fácil de entender que la introducción de una nueva variable local (muy subjetiva).

    Sin embargo, si tuviera que escribir algo tan simple como countDigits(), yo tiendo a usar una variable de procesamiento local remainingBalance en lugar de modificar el parámetro num como parte del procesamiento local -. Apenas se parece más claro para mí

  2. A veces, lo haré modificar un parámetro local al principio de un método para normalizar el parámetro:

    void saveName(String name) {
      name = (name != null ? name.trim() : "");
      ...
    }
    

    racionalizo que esto está bien porque:

    a. es fácil de ver en la parte superior del método,

    b. el parámetro mantiene su intención conceptual original, y

    c. el parámetro es estable durante el resto del método

    Por otra parte, la mitad del tiempo, estoy igual de propensos a utilizar una variable local de todos modos, sólo para obtener un par de finals adicionales en allí (bueno, eso es una mala razón, pero me gusta final):

    void saveName(final String name) {
      final String normalizedName = (name != null ? name.trim() : "");
      ...
    }
    
  3. Si, 99% de las veces, las hojas código de función de los parámetros no modificados (parámetros es decir mutantes son unintuitive o inesperado para esta base de código), entonces, durante ese otro 1% del tiempo, dejar caer un pequeño comentario acerca de un mutante parámetro en la parte superior de una función a largo / complejo podría ser un gran beneficio para la comprensibilidad:

    int CountDigits(int num) {
        // num is consumed
        int count = 1;
        while (num >= 10) {
            count++;
            num /= 10;
        }
        return count;
    }
    

P.S. :-)
parámetros vs argumentos http://en.wikipedia.org/wiki/Parameter_(computer_science)#Parameters_and_arguments

Estos dos términos son a veces vagamente usa de manera intercambiable; en particular, "argumento" se utiliza a veces en lugar de "parámetro". Sin embargo, hay una diferencia. Adecuadamente, parámetros aparecen en las definiciones de procedimientos; argumentos aparecen en las llamadas a procedimiento.

Por lo tanto,

int foo(int bar)

bar es un parámetro.

int x = 5
int y = foo(x)

El valor de x es el argumento para el parámetro bar.

Otros consejos

Siempre se siente un poco raro para mí cuando hago esto, pero que en realidad no es una buena razón para evitarlo.

Una de las razones que podría potencialmente quieren evitar es para fines de depuración. Ser capaz de ver la diferencia entre las variables "scratchpad" y la entrada a la función puede ser muy útil cuando estás a mitad de camino a través de la depuración.

No se puede decir que es algo que surge muy a menudo en mi experiencia - y con frecuencia se puede encontrar que vale la pena introducir otra variable por el simple hecho de tener un nombre diferente , pero si el código que es más limpios de lo contrario extremos cambiando el valor de la variable, entonces que así sea.

Una situación en la que este puede venga y sea totalmente razonable es donde usted tiene un cierto valor que significa "usar el valor por defecto" (por lo general una referencia nula en un lenguaje como Java o C #). En ese caso, creo que es totalmente razonable para modificar el valor del parámetro con el valor por defecto "real". Esto es particularmente útil en C # 4 donde puede tener parámetros opcionales, pero el valor por defecto tiene que ser una constante:

Por ejemplo:

public static void WriteText(string file, string text, Encoding encoding = null)
{
    // Null means "use the default" which we would document to be UTF-8
    encoding = encoding ?? Encoding.UTF8;
    // Rest of code here
}

Acerca de C y C ++

Mi opinión es que el uso del parámetro como una variable local de la función está bien porque es una variable local ya. ¿Por qué entonces no usarlo como tal?

Me siento tonta demasiado al copiar el parámetro en una nueva variable local sólo para tener una variable modificable para trabajar.

Pero creo que esto es más o menos una opinión personal. Hacerlo a su gusto. Si se siente alféizar de copiar el parámetro sólo a causa de esto, se indica que su personalidad no le gusta y entonces no debe hacerlo.

Si no necesito una copia del valor original, yo no declarar una nueva variable.

OMI no creo que la mutación de los valores de los parámetros es una mala práctica en general,
que depende de cómo se va a utilizar en su código.

Mi equipo estándar de codificación recomienda en contra de este, ya que puede ir de las manos. A mi modo de una función como la que se muestra, no se pierde nada, porque todo el mundo puede ver lo que está pasando. El problema es que con funciones de tiempo se hacen más largos, y consiguen correcciones de errores en ellos. Tan pronto como una función más de una pantalla completa de código, esto empieza a ser confuso por lo que nuestro codificación de las prohibiciones de TI estándar.

El compilador debe ser capaz de deshacerse de la variable redundante con bastante facilidad, por lo que no tiene ningún impacto eficiencia. Es probable que sólo entre usted y su revisor de código si esto está bien o no.

I sería en general no cambiar el valor del parámetro dentro de la función. Si en algún momento más adelante en la función que necesita para hacer referencia al valor original, todavía lo tienes. en su caso sencillo, no hay ningún problema, pero si se agrega más código más tarde, se puede hacer referencia a 'num' sin darse cuenta de que se ha cambiado.

El código debe ser lo más autosuficiente posible. Lo que quiero decir con esto es que ahora tienen una dependencia de lo que se ha pasado como parte de su algoritmo. Si otro miembro de su equipo decide cambiar a un pase por referencia entonces usted podría tener grandes problemas.

La mejor práctica es, sin duda para copiar los parámetros de entrada si se espera que sean inmutables.

normalmente no modificar los parámetros de función, a menos que sean punteros, en cuyo caso podría alterar el valor de la que apuntaba.

Creo que las mejores prácticas de esto varía según el idioma. Por ejemplo, en Perl puede Localizar cualquier variable o incluso parte de una variable a un ámbito local, por lo que el cambio en ese ámbito no tendrá ningún efecto fuera de él:

sub my_function
{
    my ($arg1, $arg2) = @_;    # get the local variables off the stack

    local $arg1;    # changing $arg1 here will not be visible outside this scope
    $arg1++;

    local $arg2->{key1};   # only the key1 portion of the hashref referenced by $arg2 is localized
    $arg2->{key1}->{key2} = 'foo';   # this change is not visible outside the function

}

En ocasiones he sido mordido por el olvido para localizar una estructura de datos que se pasa por referencia a una función, que he cambiado dentro de la función. A la inversa, también he vuelto una estructura de datos como resultado de la función que se comparte entre varios sistemas y la persona que llama luego procedió a cambiar los datos por error, que afecta a estos otros sistemas en un problema difícil de traza generalmente llamado acción en una distancia . Lo mejor que puede hacer aquí sería hacer un clon de los datos antes de devolverlo *, o que sea de sólo lectura **.

* En Perl, consulte la dclone() función en la incorporada en el almacenable módulo.
** En Perl, ver lock_hash() o lock_hash_ref() en el Util incorporada Hash :: módulo).

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