¡Cuidado con las condiciones costosas!
Alerta Coder 2 – Prioridad en las condiciones
Kotlin nos libra de los nulos.
Los operadores booleanos nos libran de las comprobaciones innecesarias.
Pero nada nos libra de la estupidez humana.
Observa el siguiente código que aplica un descuento si la compra supera los 100 € y el cliente no tiene penalización y, además, es miembro especial:
1 2 3 4 5 6 7 8 9 10 11 12 |
private var descuentoHabilitado = /* Un boolean */ private fun calcularPrecioFinal(cesta: Cesta, usuario: Usuario) = if (esSuperiorA100(cesta.getProductos()) && noTienePenalizacion() && descuentoHabilitado && usuario.esMiembroEspecial()) { aplicarDescuento(cesta) } else { cesta.getTotal() } |
Es posible que no te huela nada mal aún, pero a ver qué piensas después de que veas la implementación de los métodos:
1 2 3 4 5 |
fun esSuperiorA100(productos: List<Producto>) = productos.fold(0) { it.precio } > 100 fun noTienePenalizacion() = obtenerPenalizacionesBaseDatos().none { it == Penalizacion.SIN_DESCUENTO } fun Usuario.esMiembroEspecial() = this.esMiembroEspecial |
Fíjate en el problema: hemos iterado sobre la lista de productos, hemos hecho una consulta a base de datos y una nueva iteración, y después de todo, es posible que uno de los dos booleanos simples (discountsEnabled
o user.isSpecialMember()
) fuera false
y tire por tierra todo lo que hemos hecho.
Claro que el compilador no nos ha dicho nada: Kotlin se hubiera quejado si algo hubiera sido nulo, y las comprobaciones condicionales se hubieran detenido en el momento en que una fuera falsa. Pero nos hemos equivocado al decidir cuál era más importante que otra.
Recuerda ordenar siempre las condiciones de la menos costosa a la más costosa, y cuando más de una tenga el mismo coste, ordénalas de la más probable que dé false
a la menos probable, con tal de que se acaben ejecutando la menor cantidad de comprobaciones posibles.