javascript - body - title html
¿Es mala la verificación de la verdadera explicidad por diseño? (7)
¿Se considera malo verificar explícitamente si el valor booleano es verdadero? ¿Sería mejor hacer un simple if(success)
?
He visto varios chistes acerca de cómo if (someBoolean === true)
es un código horrible en un lenguaje fuertemente tipado, pero ¿también se considera malo en los idiomas tipificados?
Esto se aplicaría a cualquier lenguaje mal escrito que escriba coerción en una sentencia if.
Un ejemplo específico sería:
var onSuccess = function (JSONfromServer) {
// explicitly check for the boolean value `true`
if (JSONfromServer === true) {
// do some things
}
}
// pass it to an ajax as a callback
doSomeAjax(onSuccess);
[Editar]
En este caso particular, la variable de éxito es cualquier JSON válido devuelto por un servidor. Así que podría ser cualquier cosa. si es el verdadero booleano entonces un éxito sucedió. Si es un objeto de manejo de errores, entonces será manejado. Si es algo más, entonces probablemente será manejado en silencio.
La pregunta era si lograr que el servidor se volviera true
como JSON y buscar una buena manera de manejar el caso en el que la acción tuvo éxito.
Sin embargo, quería evitar ser específico para JavaScript y AJAX.
¿Es el olor del código o del lenguaje o un detalle de implementación o una cuestión de convención?
Realmente, depende de la situación.
Poner todos los valores falsos y todos los valores verdaderos en un cubo simplifica las cosas, hasta que las diferencias importan, ya sea un mal diseño de código o porque realmente importa por alguna razón.
En el mismo sentido, Hoare se disculpó por inventar la referencia null
, que es lo más cercano a la raíz de este problema de verdad, como veo. El diseño de JavaScript simplemente confunde el problema al agregar valores aún más veraces, lo que lleva a muchos a recomendar la comprobación explícita para evitar errores difíciles de detectar (Douglas Crockford). La comunidad de JavaScript ha aceptado el lenguaje en sí, está un poco atascado. El equipo central de Python aboga por lo contrario, ya que el diseño del lenguaje parece estar configurado para simplificar las cosas, no confundirlas, y el equipo central todavía está planeando un cambio en el idioma. Los cambios pequeños e iterativos son la esencia de las grandes mejoras a lo largo del tiempo, ya sea por convención o por diseño de idiomas.
Ambas son buenas estrategias para su situación particular. No estoy diciendo que esta sea la fuente exclusiva de mejora, pero es una fuente importante de mejora en este momento.
Por ejemplo, True
y False
son en realidad subclases de un int
en Python, 0 y 1 específicamente. Esto tiene varios beneficios de diseño. Entonces los defensores de PEP8 prefieren hacer
if a_reference:
pass
La única vez que None
realmente necesita usarse en Python es cuando se especifica un parámetro opcional.
def foo(bar=optional): # NOTE I made up this idealistic construct
"""Looks good at the surface"""
pass
def foo(bar=None):
"""But this is clear to the programmer"""
pass
JavaScript tiene implícitamente todas las variables como opcionales:
function foo(x, y, z) {
// Certainly not clear to the programmer.
}
Y los defensores de Crockford verifican explícitamente las cosas para tratar de agregar algo de claridad al lenguaje.
if (foo === undefined) {
// pass
}
Básicamente, JavaScript agregó la referencia nula # 2, conocida como undefined
. También creo que es gracioso que el lenguaje JavaScript sea tan poco considerado por la comunidad de programación que piensan que es una compensación justa agregar la complejidad de usar algo como CoffeeScript, GWT, pijamas, solo para tener un mejor lenguaje del lado del cliente. Por supuesto, no estoy de acuerdo con la complejidad agregada, pero es tristemente cierto que algunas personas pueden beneficiarse, al menos temporalmente, y hacer el trabajo más rápido, en lugar de tratar con JavaScript.
Sin embargo, creo que esta es una decisión tonta a largo plazo.
¿Qué puede ir mal? Exactamente, nada. En el mejor de los casos tu función no hace nada. Eso es aún mejor que tener algún argumento aleatorio sea aceptado como true
.
Si usa true
todo el tiempo, también debería verificarlo explícitamente.
Si bien estoy seguro a favor de if foo:
en Python, hay una gran diferencia aquí y es el hecho de que al final algún programador jQuery aleatorio puede ser largo y piensa "¡Oh! También funciona con una cadena y un new Boolean()
"y usa eso.
En cuanto a la sugerencia de Sean de usar !!
realmente depende de si solo quieres que un booleano sea aceptado o algo que sea cierto. Sin embargo, para una API limpia solo aceptaría booleanos.
Con Javascript vale la pena saber que, más allá de los valores reales y falsos, los valores pueden ser verdaderos y falsos .
Considerar:
if (false) // evaluates to false.
if (0) // evaluates to false, 0 is falsy.
if ("") // evaluates to false, empty strings are falsy.
if (null) // evaluates to false, null values are falsy.
if (undefined) // evaluates to false, undefined values are falsy.
if (NaN) // evaluates to false, NaN is falsy.
Todos los demás valores para los objetos son verdaderos.
Si los valores de verdad y falsedad conducen a errores en su lógica, debe considerar usar explícitamente los operadores ===
y !==
para asegurarse de que los objetos se comparan por tipo y valor.
En general, esperas nombres de variables booleanas como:
success, enabled, pass
Tener un valor verdadero. Asi que
if(success) //or
if(enabled) //or
if(pass) //or
if(enabled) //or
Es comprensible y lógicamente legible. Pero si tienes variables como:
result, status, port1.bit7
es mejor escribir:
if(result == true) //or
if(status == false) //or
if(port1.bit7 == true)
porque es fácil de entender de esa manera que el siguiente ejemplo:
if(result)
{
....
}
La legibilidad es la mantenibilidad.
Estoy en dos mentes sobre esto yo mismo.
En un aspecto, el ejemplo de código que has publicado es bueno, debido a la forma en que Javascript maneja el tipo de coerción. Un simple if (success)
entraría en el bloque if siempre y cuando el success
fuera verdadero , por ejemplo, una cadena no vacía haría el caso. El triple es igual a las garantías de que el success
es, de hecho, el valor booleano true
, que es una garantía más sólida que la que obtendría con la versión más corta (y probablemente una que desee).
Sin embargo, si necesita esto, es decir, no sabe si el success
será un booleano, una cadena o un entero, diría que es un olor de código en sí mismo. Independientemente de cómo realice la comparación, siempre compararía con una variable que inevitablemente será un booleano; en ese punto, no importa qué forma de comparación se use, ya que serían equivalentes. De hecho, incluso introduciría una variable "redundante" así:
var successCount = items.size(); // or some other way to get an integer
var success = successCount > 0;
if (success) {
...
}
Entonces, erm, sí. No creo que nadie realmente pueda quejarse del uso (explícito) de ===
en la comparación debido a su diferencia funcional. Pero de la misma manera, si está usando claramente indicadores de success
booleanos, entonces tampoco creo que alguien deba quejarse por el estilo corto.
(Sin embargo, con respecto a su primera oración, no creo que sea malo verificar explícitamente el valor booleano verdadero en un lenguaje de tipo dinámico, si ese valor es realmente lo que desea. Es superfluo cuando la escritura estática ya restringe la variable para que sea una variable booleano.)
He leído bastante sobre JavaScript y nunca he visto a nadie decir eso if(success)
fue una mala práctica. Yo lo haria ¿Estás seguro de que el parámetro de success
siempre será booleano? En este momento, si eso alguna vez cambiara a otra cosa, tendrías que editar la función. Pero si solo usa if(success)
, funcionaría para otros valores "de verdad" y "falso", como una cadena frente a una cadena vacía o 1 vs 0.
Si quieres convertir cualquier parámetro que sea a su valor booleano, puedes simplemente negarlo: !!success
Pero eso no es necesario dentro de un condicional como ese.
Para agregar a esta conversación, las variables sessionStorage y localStorage solo se pueden almacenar como cadenas hoy, por lo que si usa:
sessionStorage.setItem(''completed'',true);
En realidad, se convertirá en una cadena y se almacenará como "verdadero". He visto a muchas personas escribir métodos y conversiones para manipular este valor de modo que puedan usar una sentencia if utilizando un valor booleano, donde un simple
if sessionStorage.getItem(''completed'') === ''true'';
Sería suficiente y es perfectamente legible y mantenible en mi opinión.