OK, entonces el título es un poco clickbaity, pero en serio he estado diciendo, no pidas patada por un tiempo. Me gusta cómo fomenta que los métodos se utilicen como mensajes de manera orientada a objetos. Pero esto tiene un problema persistente que ha estado dando vueltas en mi cabeza.
He llegado a sospechar que un código bien escrito puede seguir los principios OO y los principios funcionales al mismo tiempo. Estoy intentando conciliar estas ideas y el gran escollo que he aterrizado en es return
.
Una función pura tiene dos cualidades:
Llamarlo repetidamente con las mismas entradas siempre da el mismo resultado. Esto implica que es inmutable. Su estado se establece solo una vez.
No produce efectos secundarios. El único cambio causado al llamarlo es producir el resultado.
Entonces, ¿cómo hace uno para ser puramente funcional si usted ha renunciado a utilizar return
como su forma de comunicar los resultados?
La idea tell, no ask funciona usando lo que algunos considerarían un efecto secundario. Cuando trato con un objeto no le pregunto sobre su estado interno. Le digo lo que debo hacer y utiliza su estado interno para averiguar qué hacer con lo que le dije que hiciera. Una vez que lo cuento, no pregunto qué hizo. Solo espero que haya hecho algo sobre lo que le dijeron que hiciera.
Pienso en Tell, Don't Ask como algo más que un nombre diferente para la encapsulación. Cuando uso return
no tengo idea de lo que me llamó. No puedo hablar de su protocolo, tengo que obligarlo a tratar con mi protocolo. Que en muchos casos se expresa como el estado interno. Incluso si lo que está expuesto no es exactamente el estado, generalmente es solo un cálculo realizado en el estado y los argumentos de entrada. Tener una interfaz para responder ofrece la oportunidad de combinar los resultados en algo más significativo que el estado interno o los cálculos. Ese es el mensaje que pasa . Ver este ejemplo .
En el pasado, cuando las unidades de disco en realidad tenían discos y una unidad de memoria USB era lo que hacía en el automóvil cuando la rueda estaba demasiado fría para tocarla con los dedos, me enseñaron cómo las personas molestas consideran las funciones que no tienen parámetros. void swap(int *first, int *second)
Parecía muy útil, pero nos animaron a escribir funciones que devolvieran los resultados. Entonces tomé esto en serio por fe y comencé a seguirlo.
Pero ahora veo personas que construyen arquitecturas donde los objetos permiten que la forma en que fueron construidas controlen dónde envían sus resultados. Aquí hay un ejemplo de implementación . Inyectar el objeto del puerto de salida parece un poco como la idea del parámetro out nuevamente. Pero así es como los objetos tell-don't-ask le dicen a otros objetos lo que han hecho.
Cuando supe por primera vez acerca de los efectos secundarios, pensé que era el parámetro de salida. Nos dijeron que no sorprendiéramos a las personas al hacer que parte del trabajo se llevara a cabo de una manera sorprendente, es decir, al no seguir la return result
convención. Ahora claro, sé que hay una pila de problemas de subprocesos asincrónicos paralelos con los que los efectos secundarios se resuelven, pero el retorno es realmente solo una convención que hace que dejes el resultado en la pila para que lo que llames puedas sacarlo más tarde. Eso es todo lo que realmente es.
Lo que realmente estoy tratando de preguntar:
¿Es return
la única manera de evitar toda la miseria de los efectos secundarios y obtener seguridad para el hilo sin bloqueos, etc. O puedo seguir diciéndole, no pregunte de una manera puramente funcional?