it-swarm-es.com

Código de fantasía corto comentado versus código más largo y fácil de entender sin comentar: ¿cuál es el preferido?

A veces, un algoritmo se puede escribir de dos formas:

  • La forma corta y elegante; o
  • La forma más larga y fácil de entender.

Por ejemplo, aquí hay una forma más larga y fácil de copiar una cadena source a dest en C:

*dest = *source;
while (*source != '\0') {
    source++;
    dest++;
    *dest = *source;
} (true);

Y aquí hay una forma corta y elegante.

// Copy string source to dest
while (*dest++ = *source++);

Siempre he escuchado y leído que se debe evitar el código sofisticado y suelo estar de acuerdo. Pero, ¿y si tenemos en cuenta los comentarios? Suponga que, como en los ejemplos anteriores, tenemos un código sin comentar, más largo y supuestamente más fácil de entender, y un código corto, elegante y bien comentado. ¿Todavía se prefiere el código no elegante?

EDITAR: Muchos han comentado los nombres de las variables, así que modifiqué el código de ejemplo para no convertirlo en un factor al preferir sobre el otro. Intenté eliminar la doble asignación en el primer ejemplo, pero eso solo hizo que el código fuera menos legible.

Quizás este no fue el mejor de los ejemplos porque muchos encuentran el código 'elegante' más legible y comprensible que el código más largo. La idea era tener un código más largo que fuera mucho más fácil de entender que un código muy corto pero complicado.

EDIT2: Aquí hay un nuevo ejemplo que obtuve de ENTONCES :

Versión elegante comentada:

//direct formula for xoring all numbers from 1 to N
int Sum = (N & (N % 2 ? 0 : ~0) | ( ((N & 2)>>1) ^ (N & 1) ) );

Versión larga no comentada:

int Sum = 0;
for (int i = 1; i < N; ++i)
{
   Sum ^= i; //or Sum = Sum ^ i;
}
18
gablin

En general, preferiría extraer el código elegante en su propio método.

En lugar de comentar el código elegante, el nombre del método debería ser todo lo que necesita para aclarar las cosas.

char *copy_string(char *s, const char *t) {    
    while (*s++ = *t++); 
    return s;
}
28
Mongus Pong

Estoy a favor de la versión más larga. El problema con la versión corta del código, además de ser más difícil de leer para algunos programadores, es que la mayoría de las veces es más difícil detectar errores con solo mirarlo.

Tengo un ejemplo de la vida real. En nuestro producto teníamos el siguiente fragmento de código:

if (++someCounter < MAX_VALUE) {
    // Do something that has to be done only MAX_VALUE times
}

Este código parece perfectamente razonable a primera vista, pero después de un largo período de tiempo, este contador se desborda y rompe la condición (en el escenario de la vida real aplastamos el sistema de producción de nuestro cliente con un OOM). Este código es un poco menos "sofisticado", pero está claro que hace lo que se supone que debe hacer:

if (someCounter < MAX_VALUE) {
    ++someCounter;
    // Do whatever it is we came here for
}

Y puede decir que el desarrollador que escribió este código simplemente no era lo suficientemente bueno (lo cual no es cierto, era un tipo bastante brillante), pero creo que si su técnica de codificación requiere que usted sea un programador súper hábil, DIOS en Para obtener el código correcto, está haciendo algo mal. Su código debe ser lo más infalible posible por su bien y por quien tenga que mantener este código después de usted (que puede que no sea tan inteligente como usted).

Entonces, estoy a favor de la simplicidad y la claridad.

Editar: Ah, y con respecto a los comentarios, no importa. Mucha gente no leerá los comentarios de todos modos ( http://www.javaspecialists.co.za/archive/Issue039.html ) y aquellos que no entenderán su código sin comentarios, no lo entenderán lo suficientemente bien con ellos para que puedan mantenerlo. El objetivo es ayudar a las personas a ver que cierto código es "correcto", los comentarios no pueden ayudar con eso.

10
Hila

En general, preferiría la versión más larga. Me vienen a la mente dos razones principales:

  • Es probable que más personas lo entiendan con menos esfuerzo (asumiendo que no es un ejemplo tan "estándar" como esta copia de cadena).
  • Es posible poner puntos de interrupción en declaraciones individuales y avanzar con un depurador.

Para lo mejor de ambos mundos, envuelva el código en una función, cuyo nombre hace el comentario por usted:

void copy_string(char *s, char *t)
{
    *s = *t;
    while (*t != '\0') {
        t++;
        s++;
        *s = *t;
    }
}

La única razón para no hacer esto sería si el rendimiento fuera un problema y la elaboración de perfiles mostrara realmente que la sobrecarga de la función es significativa.

6
Paul Stephenson

Lo que sea más claro. A menudo es un fragmento de código compacto y fácil de entender que no requiere un comentario ... como su segundo ejemplo.

Por lo general, los fragmentos de código más cortos son más fáciles de entender, ya que el lector tiene menos que recordar a la vez. Obviamente, hay un límite cuando el código se confunde demasiado y no me refiero a que se deba recortar el espacio en blanco que mejora la claridad.

Los comentarios nunca deben indicar algo que sea obvio por el código, que solo haga que el lector lea lo mismo dos veces. Para mí, el primer fragmento requiere una aclaración. ¿Por qué el desarrollador no ha utilizado un do...while bucle para eliminar el duplicado de *s = *t; asignación? Tengo que analizar más código para darme cuenta de que está implementando una copia de cadena. Un comentario sería más útil en este código más largo que en el código más corto.

El comentario sobre el segundo fragmento es casi redundante ya que el bucle while es prácticamente idiomático, pero dice lo que hace el código en un nivel superior que el código en sí, lo que lo convierte en un comentario útil.

4
CB Bailey

El problema es que no existe una definición clara de short fancy code Ya que depende mucho del nivel del programador. Mientras que algunas personas no tienen problemas para entender una expresión while(*s++ = *t++);, otras sí.

Personalmente, encuentro el while(*s++ = *t++); perfectamente legible y el más largo más difícil de leer. Sin embargo, es posible que otros no estén de acuerdo.

Independientemente, es solo una cuestión de usar el sentido común. La legibilidad debería ser definitivamente una prioridad, pero hay un punto en el que el código más largo se vuelve menos legible cuando se alarga. La verbosidad a menudo reduce la legibilidad de mi experiencia.

4
Wolph
Keep it simple, stupid!

Asegúrese de que cualquier otro programador pueda entender lo que hace su código, e incluso mejor si es de un vistazo (aquí es donde los buenos nombres y comentarios entran en juego).

El kung-fu elegante y el ensamblaje en línea son geniales en nombre de la optimización (quizás innecesaria y prematura), pero cuando ni siquiera usted puede entender el código que escribió cuando te encuentras con un error dos meses después ... ¿Cuál fue el punto? Te costará tiempo y esfuerzo.

A menudo me refiero al Zen de Python en estas situaciones. En particular:

Explicit is better than implicit.
Simple is better than complex.
2
Humphrey Bogart

Tengo que no estar de acuerdo con la mayoría de las otras respuestas aquí; creo que (al menos en este caso) el código más corto es mejor. Contrariamente a su afirmación, el código más largo es no "más fácil", al menos para un lector. En todo caso, parece que ha dejado de querer alargarlo, aunque hace que el código sea más difícil de entender y/o tener la seguridad de que funciona correctamente.

En particular, tener la asignación del primer byte de la cadena fuera del ciclo, separada de la asignación para los otros bytes, significa que uno tiene que ser mucho más cuidadoso al leer para estar seguro de que todos los bytes se copian correctamente. La secuencia básica de acciones en la versión más corta es mucho más fácil de verificar. Su único problema real está en el formato: cuando tiene un cuerpo de bucle vacío intencionalmente, es mejor dejarlo en claro, algo como:

while (*dest++ = *source++)
    ;

o incluso:

while (*dest++ = *source++)
    ; /* no body */

Algunas personas prefieren usar aparatos ortopédicos en su lugar:

while (*dest++ = *source++)
    {}

Independientemente del formato exacto que prefiera, se han cometido suficientes errores con cosas como:

if (x>y);
     x = z;

... que es importante estar seguro de que 1) es obvio lo que está realmente controlado por cualquier control de flujo, y 2) es obvio que el código fue escrito sabiendo qué fue controlado por él, entonces alguien leyendo no es una pérdida de tiempo tratando de averiguar si acaban de encontrar un error.

2
Jerry Coffin

Por supuesto, depende enteramente de las circunstancias. pero en general, considero que esta es una buena regla general:

La depuración es dos veces más difícil que escribir el código en primer lugar. Por lo tanto, si escribe el código de la manera más inteligente posible, por definición, no es lo suficientemente inteligente como para depurarlo.

~ Brian Kernighan

1
violet313

No escriba código sofisticado en software de producción. Sé que se siente bien poder escribir eso, y es más corto. Escribir código elegante aumenta significativamente el valor de "WTF/minuto", en otras palabras, disminuye la calidad.

alt text

1
Tamás Szelei

Empiezo a no confiar nunca en los comentarios. Con demasiada frecuencia, los comentarios no se actualizan cuando el código se actualiza y están muy desactualizados o representan reglas de clientes/administración que ya no son relevantes.

En algunos casos, ha llegado al punto en que los comentarios ni siquiera coinciden con el código que están describiendo.

Si tengo que elegir entre corto/elegante y más largo/más fácil de entender, siempre elijo lo último a menos que haya una realmente buena razón.

0
Steven Evers

La legibilidad y la facilidad de mantenimiento son clave, y su segundo ejemplo (es decir, el más largo) es mucho más de ambos. Pero, ¿por qué limitarse a dos opciones? Incluso el código más largo es demasiado complejo (en mi humilde opinión) para no anotar más. Lo pondría en un método propio con Javadoc apropiado (o lo que sea) y un nombre de método adecuado.

0
Chris Knight

En mi experiencia, la mayor ventaja en términos de código corto y elegante suele ser el uso de recursividad en lugar de iteración. También es una de las cosas más difíciles de entender de un vistazo al código, a menos que esté trabajando en el tipo de lenguaje en el que todo es recursivo de todos modos. Todavía lo preferiría por la elegancia y la velocidad de desarrollo que ofrece, pero trato de asegurarme de que tenga comentarios detallados si parece que será opaco para los futuros mantenedores o para mi futuro yo.

0
glenatron