El próximo año es bisiesto. ¿Cómo podemos saber si un año es bisiesto? Es una simple regla: el año debe ser divisible por cuatro. Esta regla, como todas, tiene sus excepciones: Si el año es divisible por 100, no es bisiesto, a menos que sea divisible por 400 también. Para saber más detalles pueden revisar la Wikipedia.
Veamos unos ejemplos:
Es un ejercicio sencillo de programar, pero me resultó muy interesante.
Por lo general, mi manera de resolver los problemas es buscar una solución que funcione y después refactorizar mi código por una solución más elegante y/o con mejor rendimiento.
Esta fue mi solución inicial:
export const isLeap = (year) => {
if (year % 4 === 0) {
if (year % 100 === 0) {
if (year % 400 === 0) {
return true;
}
return false;
}
return true;
}
return false;
};
Fue simplemente traducir literalmente las reglas explicadas anteriormente a Javascript. Resuelve el problema, pero se puede mejorar.
Mi primera idea fue eliminar los if
anidados con las cláusulas de guarda. Aquí está el código:
export const isLeap = (year) => {
if (year % 400 === 0) {
return true;
}
if (year % 100 === 0) {
return false;
}
return year % 4 === 0;
};
El código verifica las condiciones más específicas primero y después las más genéricas. De esta manera evitamos hacer comparaciones redundantes.
no es bisiesto, porque en este punto ya sabemos que no es divisible por 400.
return
final ya sabemos que el año no es divisible por 400 nipor 100, entonces solo aplica la regla más genérica: es bisiesto si es divisible por 4.
Para saber más acerca de las cláusulas de guarda les recomiendo ver la definición aquí Refactoring: Guard Clauses y ver este video de la serie RigorTalks de Carlos Buenosvinos que explica muy bien como funcionan.
Esta solución es mucho mejor en mi opinión que la inicial, pero todavía es un poco verbosa. ¿Se podrá reducir más?
if
Francesco Cirillo, creador de la Técnica pomodoro,
es el creador tambien de una campaña muy curiosa: Campaña Anti-if.
¿Es posible crear una solución sin el uso de if
para este problema? Veamos:
Eliminamos el if más anidado y retornamos directamente el resultado de year % 400 === 0
export const isLeap = (year) => {
if (year % 4 === 0) {
if (year % 100 === 0) {
return year % 400 === 0
}
return true;
}
return false;
};
Continuando con la misma idea, eliminamos el if
anidado, pero en este caso hay que combinarlo con
el valor de retorno anterior y modificar ligeramente la condición.
Si el año no es divisible por 100 (year % 100 !== 0
) o (||
) si el año es divisible por 400
(year % 400 === 0
) entonces es bisiesto. Esto se traduce a year % 100 !== 0 || year % 400 === 0
en código Javascript.
export const isLeap = (year) => {
if (year % 4 === 0) {
return year % 100 !== 0 || year % 400 === 0;
}
return false;
};
Ahora es el turno de eliminar el último if
. Para garantizar que el año es bisiesto se tiene que
cumplir la condición del if
(year % 4 === 0
) y (&&
) la condición del return
(year % 100 !== 0 || year % 400 === 0
). Eso se traduce al siguiente código Javascript:
export const isLeap = (year) => {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
};
De esta manera hemos eliminado todos los if
y reducido nuestro código a una sola línea.
Incluso cuando nos sentimos contento con nuestras soluciones, creo que es muy buena idea ver las de otros porque de seguro que aprenderemos algo nuevo. Una que me resultó muy interesante fue la de lainjiang. Es una línea igualmente pero las condiciones son distintas.