standard programa name indentación documentacion convenciones classes c# readability

c# - programa - ¿Qué código es más legible?



standard c# (21)

Supongamos que tengo dos métodos bool Foo() y bool Bar() . ¿Cuál de los siguientes es más legible?

if(Foo()) { SomeProperty = Bar(); } else { SomeProperty = false; }

o

SomeProperty = Foo() && Bar();

Por un lado, considero el cortocircuito && como una característica útil y el segundo ejemplo de código es mucho más corto. Por otro lado, no estoy seguro de que las personas estén generalmente acostumbradas a ver && fuera de un enunciado condicional, por lo que me pregunto si eso introduciría alguna disonancia cognitiva que haga que la primera muestra sea la mejor opción.

¿Qué piensas? ¿Hay otros factores que afectan la decisión? Por ejemplo, si la expresión && es más larga que una línea que puede caber en la pantalla, ¿debería preferir la anterior?

Aclaraciones posteriores a la respuesta:

Algunas cosas que debería haber incluido en la pregunta inicial que surgieron en las respuestas.

  • Bar() puede ser más costoso de ejecutar que Foo() , pero ninguno de los métodos debe tener efectos secundarios.
  • Los métodos se nombran más apropiadamente, no como en este ejemplo. Foo() reduce a algo como CurrentUserAllowedToDoX() y Bar() se parece más a, XCanBeDone()

¿De qué manera crees que las personas pueden malinterpretar el segundo? ¿Crees que olvidarán esos && shortcircuits y te preocuparán por lo que sucederá si se llama a la segunda condición cuando la primera es falsa? Si es así, no me preocuparía, estarían igualmente confundidos por:

if (x != null && x.StartsWith("foo"))

que no creo que mucha gente reescriba como la primera forma.

Básicamente, iría con el segundo. Con un nombre de variable (y condiciones) adecuadamente descriptivo, debería ser absolutamente correcto.


A menudo es útil poder marcar de forma individual cualquier llamada de función específica, y también cualquier ajuste específico de una variable a un valor particular, por lo que, quizás de forma controvertida, me inclinaría a elegir la primera opción. Esto ofrece una mayor posibilidad de permitir un punto de corte fino en todos los depuradores (que en el caso de C # no es un número muy grande).

De esta forma, un punto de interrupción puede establecerse antes de la llamada a Foo (), antes de la llamada a Bar () (y el conjunto de la variable), y cuando la variable se establece en falsa, y obviamente los mismos puntos de interrupción también podrían ser usado para atrapar los casos Foo () vs! Foo (), dependiendo de la pregunta que uno tenga en mente.

Esto no es imposible de hacer cuando todo está en una línea, pero se necesita atención que podría usarse para resolver la causa de cualquier problema que se esté investigando.

(C # se compila rápidamente, por lo que normalmente no es un gran problema reorganizar el código, pero es una distracción).


Como usa c #, elegiría la primera versión o usaría el operador ternario ?: . Usar && de esa manera no es una expresión común en c #, por lo que es más probable que se te malinterprete. En algunos otros idiomas (se me ocurre Ruby), el patrón && es más popular, y diría que es apropiado en ese contexto.


Creo que la mejor manera es utilizar SomeProperty = Foo() && Bar() , porque es mucho más corto. Creo que cualquier programador .NET normal debería saber cómo funciona && - operator.


Cuando leí el primero, no era inmediatamente obvio que SomeProperty era una propiedad booleana, ni que Bar () devolviera un valor booleano hasta que leyera la parte else de la declaración.

Mi punto de vista personal es que este enfoque debería ser una mejor práctica: cada línea de código debe ser lo más interpretable posible, con referencia a la menor cantidad de código posible .

Como la instrucción uno requiere que haga referencia a la parte else de la instrucción para interpolar que tanto SomeProperty como Bar () son de naturaleza booleana, usaría la segunda.

En el segundo, es inmediatamente obvio en una sola línea de código todos los siguientes hechos:

  • SomeProperty es booleano.
  • Foo () y Bar () devuelven valores que se pueden interpretar como booleanos.
  • SomeProperty debería establecerse en falso a menos que ambos Foo () y Bar () se interpreten como verdaderos.

Depende de lo que hagan Foo y Bar.

Por ejemplo, IsUserLoggedIn() && IsUserAdmin() definitivamente sería mejor como && , pero hay algunas otras combinaciones (no puedo pensar en ninguna improvisación) donde el if sería mejor.

En general, recomendaría && .


El cortocircuito del comportamiento Y no es estándar en todos los idiomas, por lo que tiendo a ser cauteloso al usarlo implícitamente si eso es esencial para mi código.

No confío en mí mismo para ver el cortocircuito inmediatamente después de haber cambiado de idioma por quinta vez en el día.

Entonces, si Boo () nunca debería ser llamado cuando Foo () devuelve falso, yo elegiría la versión 2, solo como técnica de programación defensiva.


El primer método es más legible, pero obtiene más líneas de códigos, el segundo es más EFECTIVO, no hay comparación, ¡solo una línea! Creo que el segundo es mejor


El primero, es mucho más depurable


En el caso donde las expresiones condicionales son cortas y sucintas, como es este caso, encuentro que el segundo es mucho más legible. Es muy claro a simple vista lo que estás tratando de hacer aquí. El primer ejemplo, sin embargo, me llevó 2 pases para entender lo que estaba sucediendo.


Escogería la versión larga porque a primera vista es claro lo que hace. En la segunda versión, debe detenerse por unos pocos segundos hasta que se dé cuenta del comportamiento de cortocircuito del operador &&. Es un código inteligente, pero no es un código legible.


Espera un minuto. Estas declaraciones ni siquiera son equivalentes, ¿verdad? Los he mirado varias veces y no evalúan lo mismo.

La abreviatura de la primera versión usaría el operador ternario, no el operador "y".

SomeProperty = foo() ? bar: false

Sin embargo, aparte del error de lógica, estoy de acuerdo con todos los demás en que la versión más corta es más legible.

Editar - Agregado

Por otra parte, si estoy equivocado y NO HAY error de lógica, entonces el segundo es mucho más legible porque es muy obvio lo que está haciendo el código.

Editar nuevamente - agregó más:

Ahora lo veo. No hay un error de lógica Sin embargo, creo que esto indica que la versión más larga es más clara para aquellos de nosotros que aún no hemos tomado nuestro café.


Estoy de acuerdo con el consenso general de que el formulario Foo () && Bar () es razonable a menos que sea el caso de que Bar () sea útil tanto por sus efectos secundarios como por su valor.

Si es el caso de que Bar () es útil tanto por sus efectos secundarios como por su valor, mi primera opción sería rediseñar Bar () para que la producción de sus efectos secundarios y el cálculo de su valor fueran métodos separados.

Si por alguna razón eso fuera imposible, entonces preferiría en gran medida la versión original. Para mí, la versión original enfatiza más claramente que la llamada a Bar () es parte de una declaración que es útil para sus efectos secundarios. Esta última forma para mí enfatiza que Bar () es útil por su valor.

Por ejemplo, dada la elección entre

if (NetworkAvailable()) success = LogUserOn(); else success = false;

y

success = NetworkAvailable() && LogUserOn();

Yo tomaría el primero; para mí, es demasiado fácil pasar por alto el efecto secundario importante en este último.

Sin embargo, si fuera una elección entre

if (NetworkAvailable()) tryWritingToNetworkStorage = UserHasAvailableDiskQuota(); else tryWritingToNetworkStorage = false;

y

tryWritingToNetworkStorage = NetworkAvailable() && UserHasAvailableDiskQuota();

Yo elegiría el último.


Me gusta esta notación taquigráfica asumiendo que tu lenguaje lo permita:

SomeProperty = Foo() ? Bar() : false;


Me gustaría ir por el segundo, pero probablemente lo escribiría como la primera vez, y luego lo cambiaría :)


Ninguno. Empezaría por renombrar SomeProperty, Foo y Bar.

Lo que quiero decir es que debes estructurar tu código para transmitir tus intenciones con claridad. Con diferentes funciones, podría usar diferentes formas. Tal como está, sin embargo, cualquiera de las formas está bien. Considerar:

IsFather = IsParent() && IsMale();

y

if (FPUAvailable()) { SomeProperty = LengthyFPUOperation(); } else { SomeProperty = false; }

Aquí, la primera forma enfatiza la relación lógica y. El segundo enfatiza el cortocircuito. Nunca escribiría el primer ejemplo en la segunda forma. Probablemente preferiría la segunda forma para el segundo ejemplo, especialmente si aspiraba a la claridad.

El punto es que es difícil responder a esta pregunta con SomeProperty y Foo () y Bar (). Hay algunas buenas respuestas genéricas que defienden && para los casos habituales, pero nunca descartaría por completo la segunda forma.


Se trata de ser intencional y claro, en mi mente.

La primera forma le deja claro al observador casual que no está ejecutando Bar () a menos que Foo () devuelva verdadero. Entiendo que la lógica de corto circuito impedirá que se llame a Bar () en el segundo ejemplo (y podría escribirlo de esa manera yo mismo), pero la primera forma es mucho más intencional a primera vista.


Si la primera versión se veía así:

if (Foo() && Bar()) { SomeProperty = true; } else { SomeProperty = false; }

o así:

if (Foo()) { if (Bar()) SomeProperty = true; else SomeProperty = false; } else { SomeProperty = false; }

Entonces al menos sería consistente . De esta manera, la lógica es mucho más difícil de seguir que el segundo caso.


Si, como usted indica, Bar () tiene efectos secundarios, preferiría la forma más explícita. De lo contrario, algunas personas podrían no darse cuenta de que tiene la intención de aprovechar el cortocircuito.

Si Bar () es autónomo, buscaría la forma más sucinta de expresar el código.


Yo diría que el código es legible si es legible para una persona sin conocimiento del lenguaje de programación real, por lo tanto, código como

if(Foo() == true and Bar() == true) then SomeProperty = true; else SomeProperty = false;

es mucho más legible que

SomeProperty = Foo() && Bar();

Si el programador se hace cargo del código después de que usted no está familiarizado con la última sintaxis, le costará 10 veces el tiempo que le toma escribir esos pocos caracteres adicionales.


SomeProperty = Foo() && Bar();

Esto es mucho más legible. No veo cómo alguien podría elegir el otro con franqueza. Si la expresión && es más larga que 1 línea, divídala en 2 líneas ...

SomeProperty = Foo() && Bar(); -or- SomeProperty = Foo() && Bar();

Eso apenas lastima la legibilidad y la comprensión en mi humilde opinión.