JS: Funciones
Teoría: Separación de comandos y consultas
Separación de comandos y consultas (CQS) - un principio de programación inventado por Bertrand Meyer, el creador del lenguaje Eiffel. Según este principio, cada función es o un comando, que realiza una acción, o una consulta, que recupera datos, pero no ambas cosas al mismo tiempo. Un comando siempre está asociado con la ejecución de efectos secundarios, mientras que las funciones puras solo son posibles para consultas.
Comando
Según el principio de CQS, la función save() es un comando. Lo único que puede hacer es devolver (según el principio) el éxito de su ejecución, es decir, true o false (o undefined, como en el caso de console.log()). Devolver cualquier otro dato significativo con esta función se considera una violación de CQS. Sin embargo, hay situaciones en las que no es posible cumplir con este principio. Por ejemplo, al abrir un archivo para escribir, se devuelve un descriptor de archivo, que es un identificador necesario para manipular el archivo.
La separación de comandos y consultas está estrechamente relacionada con las ideas descritas en la lección sobre funciones puras. Los comandos, por definición, ejecutan código no determinista con efectos secundarios. No determinista porque llamar al comando nuevamente resulta en un error o en la repetición de la acción (aunque se pueden hacer deterministas, pero generalmente ese código oculta errores lógicos). Por lo tanto, separar la consulta (devolución de datos) del comando en una función separada ayuda a aislar el código puro del código con efectos.
Consulta
La función isAdmin() es un predicado, una consulta típica o, incluso se podría decir, una pregunta que suena así: "¿El usuario es un administrador?" Según CQS, esta función no puede cambiar el estado del sistema, como cambiar la fecha de verificación de administrador dentro del usuario o incluso convertir al usuario en administrador. Esto no solo va en contra de CQS, sino también del sentido común. A diferencia del ejemplo anterior, true y false en el caso de los predicados no representan el éxito de la ejecución de la función, sino la respuesta a la pregunta planteada.
Eche un vistazo al ejemplo de una función que cambia los datos originales:
Si se realiza otra llamada a takeChildren(users), es probable que la ejecución del código falle, ya que la estructura de la matriz original ha cambiado. Este comportamiento de una función de consulta es antinatural. CQS tiene una formulación alternativa que describe perfectamente el código anterior: "Al hacer una pregunta, no cambies la respuesta".
Las consultas también incluyen cualquier cálculo:
Este código no tiene efectos secundarios y es determinista. Se puede llamar tantas veces como se desee sin riesgo de errores o resultados incorrectos.
La falta de cambios en las consultas es un principio muy importante que siempre se debe cumplir. Incluso a nivel intuitivo, nadie espera que la verificación de isAdmin() o el cálculo del número máximo en una matriz realicen alguna acción destructiva. Por otro lado, en la práctica, a veces se encuentra código de este tipo, y ahora sabe cómo corregirlo correctamente.
¿Qué hacer en casos en los que no se puede separar un comando de una consulta? Imagínese una función que debe generar un nombre de usuario si no existe y guardarlo en una base de datos. Esta tarea se plantea en el Proyecto 4 de Códica. En este proyecto se está desarrollando un análogo de Slack. Cuando un usuario ingresa al sitio, se le asigna un nombre de usuario aleatorio.
La lógica de esta función se ve así:
Si se elimina esta lógica dentro de la función, ¿cómo debería llamarse? Eche un vistazo a esta opción:
Este nombre de función es engañoso. Parece una consulta, pero no lo es. Sin conocer el funcionamiento interno de esta función, no se puede adivinar lo que está sucediendo dentro de ella. La primera idea siempre será que es simplemente la lectura de algunos datos ya guardados.
El enfoque correcto en tales situaciones es nombrar la función como un comando. Entonces no habrá significados ocultos. Sí, seguirá violando CQS, pero aquí no estamos tratando de evitarlo. Lo más importante es mostrar la intención de manera explícita:
Completado
0 / 16