Hemos estado en el proceso de cambiar la forma en que nuestra aplicación AS3 se comunica con nuestro back-end y estamos en el proceso de implementar un sistema REST para reemplazar el anterior.
Lamentablemente, el desarrollador que comenzó el trabajo ahora está de baja por enfermedad a largo plazo y me lo ha entregado. He estado trabajando con él durante la última semana y entiendo el sistema, pero hay una cosa que me ha estado preocupando. Parece que se pasan muchas funciones a funciones. Por ejemplo, nuestra clase que realiza la llamada a nuestros servidores adopta una función a la que luego llamará y pasará un objeto cuando se complete el proceso y se hayan manejado los errores, etc.
Me está dando ese "mal presentimiento" donde siento que es una práctica horrible y puedo pensar en algunas razones, pero quiero una confirmación antes de proponer un nuevo trabajo en el sistema. Me preguntaba si alguien tenía alguna experiencia con este posible problema.
fuente
Respuestas:
No es un problema
Es una técnica conocida. Estas son funciones de orden superior (funciones que toman funciones como parámetros).
Este tipo de función también es un componente básico en la programación funcional y se usa ampliamente en lenguajes funcionales como Haskell .
Estas funciones no son malas ni buenas: si nunca ha encontrado la noción y la técnica, puede ser difícil de comprender al principio, pero pueden ser muy poderosas y son una buena herramienta para tener en su cinturón de herramientas.
fuente
No solo se utilizan para la programación funcional. También pueden conocerse como devoluciones de llamada :
Piensa en el código asincrónico por un segundo. Usted pasa una función que, por ejemplo, envía datos al usuario. Solo cuando el código se ha completado, invoca esta función con el resultado de la respuesta, que la función luego utiliza para enviar los datos al usuario. Es un cambio de mentalidad.
Escribí una biblioteca que recupera datos de Torrent de tu seedbox. Está utilizando un bucle de eventos sin bloqueo para ejecutar esta biblioteca y obtener datos, luego devolverlos al usuario (por ejemplo, en un contexto de websocket). Imagine que tiene 5 personas conectadas en este bucle de eventos y una de las solicitudes para obtener los puestos de datos de torrents de alguien. Eso bloqueará todo el ciclo. Por lo tanto, debe pensar de forma asíncrona y usar devoluciones de llamada: el bucle sigue ejecutándose y el "devolver los datos al usuario" solo se ejecuta cuando la función ha finalizado la ejecución, por lo que no hay que esperar. Dispara y olvida.
fuente
Esto no es algo malo. De hecho, es algo muy bueno.
Pasar funciones a funciones es tan importante para la programación que inventamos las funciones lambda como una abreviatura. Por ejemplo, uno puede usar lambdas con algoritmos de C ++ para escribir código muy compacto pero expresivo que permita a un algoritmo genérico la capacidad de usar variables locales y otros estados para hacer cosas como buscar y ordenar.
Las bibliotecas orientadas a objetos también pueden tener devoluciones de llamada que son esencialmente interfaces que especifican un pequeño número de funciones (idealmente una, pero no siempre). Entonces se puede crear una clase simple que implemente esa interfaz y pasar un objeto de esa clase a una función. Esa es una piedra angular de la programación dirigida por eventos , donde el código de nivel de marco (quizás incluso en otro hilo) necesita llamar a un objeto para cambiar el estado en respuesta a una acción del usuario. La interfaz ActionListener de Java es un buen ejemplo de esto.
Técnicamente, un functor de C ++ también es un tipo de objeto de devolución de llamada que aprovecha el azúcar sintáctico
operator()()
para hacer lo mismo.Finalmente, hay punteros de función de estilo C que solo deben usarse en C. No voy a entrar en detalles, solo los menciono para completarlos. Las otras abstracciones mencionadas anteriormente son muy superiores y deben usarse en idiomas que las tengan.
Otros han mencionado la programación funcional y cómo pasar funciones es muy natural en esos lenguajes. Las lambdas y las devoluciones de llamada son la forma en que los lenguajes de procedimiento y OOP imitan eso, y son muy potentes y útiles.
fuente
Como ya se dijo, no es una mala práctica. Es simplemente una forma de desacoplar y separar la responsabilidad. Por ejemplo, en OOP harías algo como esto:
El método genérico es delegar una tarea específica, de la que no sabe nada, a otro objeto que implemente una interfaz. El método genérico solo conoce esta interfaz. En su caso, esta interfaz sería una función a llamar.
fuente
En general, no hay nada de malo en pasar funciones a otras funciones. Si está haciendo llamadas asincrónicas y quiere hacer algo con el resultado, necesitaría algún tipo de mecanismo de devolución de llamada.
Sin embargo, existen algunos inconvenientes potenciales de las simples devoluciones de llamada:
Con servicios web simples, la forma en que lo hace funciona bien, pero se vuelve incómodo si necesita una secuencia de llamadas más compleja. Sin embargo, hay algunas alternativas. Con JavaScript, por ejemplo, ha habido un cambio hacia el uso de promesas ( ¿Qué tiene de bueno las promesas de JavaScript? ).
Todavía implican pasar funciones a otras funciones, pero las llamadas asincrónicas devuelven un valor que toma una devolución de llamada en lugar de tomar una devolución de llamada directamente. Esto proporciona más flexibilidad para componer estas llamadas juntas. Algo como esto se puede implementar con bastante facilidad en ActionScript.
fuente