Introducir variables locales adicionales como reemplazo de comentarios

12

¿Es un buen estilo usar variables locales adicionales, técnicamente superfluas, para describir lo que está sucediendo?

Por ejemplo:

bool easyUnderstandableIsTrue = (/* rather cryptic boolean expessions */);

if(easyUnderstandableIsTrue)
{
    // ...
}

Cuando se trata de sobrecarga técnica, espero que el compilador optimice esta línea adicional. ¿Pero se considera un código innecesario? A mis ojos, reduce el riesgo de comentarios obsoletos.

BooleanAssange
fuente
10
"¿Es un buen estilo usar variables locales adicionales, técnicamente superfluas, para describir lo que está sucediendo?". Si. No se puede decir mucho más aquí, de verdad.
David Arno
3
Encuentro que tal estilo (es decir, el uso de muchas variables intermedias con nombres descriptivos) es bastante útil cuando leo mi código más adelante. Por supuesto, puede escribir expresiones complejas y guardar algunos nombres al no introducir variables intermedias, pero ¿por qué querría hacerlo? Leer el código puede ser todo un desafío, incluso si está relativamente bien escrito, por lo que no creo que complicarlo innecesariamente sea una ruta sensata.
Mael
Creo que esto se llama Consolidar expresión condicional en el catálogo de refactorizaciones de Martin Fowler .
Brandin el

Respuestas:

16

¿Cuál es el costo de tener una variable adicional? En la mayoría de los idiomas, ninguno, tanto en lenguajes compilados como interpretados.

¿Cuál es el beneficio de esto?

  • De manera similar a extraer la expresión booleana críptica a un método separado, está disminuyendo el riesgo de código duplicado , pero un poco menos que en el caso de un método separado. Si la expresión condicional se reutiliza dentro del método en sí, podrá reutilizar la variable; Si la expresión aparece en un método diferente, no lo hará.

    Tenga en cuenta que, a menos que su lenguaje de programación le permita tener variables locales inmutables o tenga una forma de imponer, en términos de estilo, que ninguna de las variables se reasigne, dicha refactorización podría ser riesgosa a largo plazo. Si se cambia el valor de la variable, podría ser muy difícil razonar sobre el código.

  • Está reduciendo el riesgo de que la documentación no esté sincronizada con el código . Los desarrolladores tienden a actualizar los nombres de variables y métodos más fácilmente que los comentarios. Por lo tanto, no es inusual ver códigos como:

    // Find if the user is an actual author in order to allow her to edit the message.
    if (currentUser.isAdministrator || (message.author == currentUser && !message.locked))

La expresión probablemente comenzó con if (message.author == currentUser), y luego evolucionó para manejar el caso de mensajes bloqueados y administradores que no necesitan ser autores y no les importan las cosas bloqueadas; sin embargo, el comentario no ha reflejado ninguno de esos cambios.

Ambos beneficios no son particularmente importantes, pero dado el bajo costo de las variables adicionales, puede considerar usarlas.

Tenga en cuenta que si su expresión booleana se vuelve demasiado compleja: ²

  • Extraerlo a un método separado y:
  • Refactorizarlo en múltiples expresiones booleanas simples.

El ejemplo anterior se convierte en:

class Message
{
    ...
    public boolean canBeEditedBy(User user)
    {
        ...
        if (user.isAdministrator) {
            return true;
        }

        return this.author == user && !this.locked;
    }
}

...
if (message.canBeEditedBy(currentUser)) // See? Much more readable now!
{
    ...
}

¹ Fuente: mi propia observación de mis compañeros desarrollando principalmente software empresarial; YMMV. Una investigación real puede mostrar resultados diferentes. Personalmente, supongo que cuando los desarrolladores leen el código, se centran en el código y los comentarios son documentación, no código; por lo tanto, generalmente no leen comentarios, por lo que sería difícil esperar que los actualicen.

² El umbral excesivamente complejo se define con una fórmula simple: si la mitad de los desarrolladores que revisan su código expresan la intención de asesinarlo, se alcanza el umbral. La expresión booleana anterior es lo suficientemente simple como para requerir una refactorización; sin embargo, cuatro partes seguidas if ((a && b) || (c && d))lo harían potencialmente refactible. Tenga en cuenta que si la expresión es plana, el número de partes es irrelevante: if (a || b || c || d || ... || z)es lo suficientemente legible.

Arseni Mourzenko
fuente