Estamos mudando a maneira como nosso aplicativo AS3 se comunica com nosso back-end e estamos implementando um sistema REST para substituir o antigo.
Infelizmente, o desenvolvedor que iniciou o trabalho está agora de licença médica de longo prazo e foi entregue a mim. Estou trabalhando com ele há uma semana ou mais e entendo o sistema, mas há uma coisa que me preocupa. Parece haver muita passagem de funções para funções. Por exemplo, nossa classe que faz a chamada para nossos servidores assume uma função para a qual chamará e passará um objeto para quando o processo estiver concluído e os erros forem tratados etc.
Está me dando esse "mau pressentimento", onde eu sinto que é uma prática horrível e posso pensar em algumas razões, mas quero alguma confirmação antes de propor um novo trabalho no sistema. Fiquei me perguntando se alguém tinha alguma experiência com este possível problema?
fonte
Respostas:
Não é um problema.
É uma técnica conhecida. Essas são funções de ordem superior (funções que assumem funções como parâmetros).
Esse tipo de função também é um componente básico da programação funcional e é amplamente utilizado em linguagens funcionais como Haskell .
Tais funções não são boas ou ruins - se você nunca encontrou a noção e a técnica, elas podem ser difíceis de entender a princípio, mas podem ser muito poderosas e são uma boa ferramenta para se ter no cinto de ferramentas.
fonte
Eles não são usados apenas para programação funcional. Eles também podem ser conhecidos como retornos de chamada :
Pense em código assíncrono por um segundo. Você passa uma função que, por exemplo, envia dados ao usuário. Somente quando o código for concluído, você invoca esta função com o resultado da resposta, que a função usa para enviar os dados de volta ao usuário. É uma mudança de mentalidade.
Eu escrevi uma biblioteca que recupera dados de Torrent do seu seedbox. Você está usando um loop de eventos sem bloqueio para executar esta biblioteca e obter dados e depois devolvê-los ao usuário (por exemplo, em um contexto de websocket). Imagine que você tem 5 pessoas conectadas nesse loop de eventos e uma das solicitações para obter os dados de torrent de alguém. Isso irá bloquear todo o loop. Então, você precisa pensar de forma assíncrona e usar retornos de chamada - o loop continua em execução e o "devolver os dados ao usuário" é executado apenas quando a função termina a execução, portanto, não há como esperar. Fogo e esqueça.
fonte
Isso não é uma coisa ruim. De fato, é uma coisa muito boa.
Passar funções para funções é tão importante para a programação que inventamos as funções lambda como uma abreviação. Por exemplo, pode-se usar lambdas com algoritmos C ++ para escrever código muito compacto, mas expressivo, que permite a um algoritmo genérico a capacidade de usar variáveis locais e outro estado para fazer coisas como pesquisar e classificar.
As bibliotecas orientadas a objetos também podem ter retornos de chamada que são essencialmente interfaces que especificam um pequeno número de funções (idealmente uma, mas nem sempre). Pode-se criar uma classe simples que implementa essa interface e passar um objeto dessa classe para uma função. Essa é uma pedra angular da programação orientada a eventos , em que o código no nível da estrutura (talvez até em outro encadeamento) precisa chamar um objeto para alterar o estado em resposta a uma ação do usuário. A interface ActionListener do Java é um bom exemplo disso.
Tecnicamente, um functor C ++ também é um tipo de objeto de retorno de chamada que aproveita o açúcar sintático
operator()()
, para fazer a mesma coisa.Por fim, existem ponteiros de função no estilo C que devem ser usados apenas em C. Não entrarei em detalhes, apenas os mencionei por completude. As outras abstrações mencionadas acima são muito superiores e devem ser usadas nos idiomas que as possuem.
Outros mencionaram programação funcional e como a passagem de funções é muito natural nessas linguagens. Lambdas e retornos de chamada são a maneira como as linguagens processuais e OOP imitam isso, e são muito poderosas e úteis.
fonte
Como já foi dito, não é uma prática ruim. É apenas uma maneira de dissociar e separar responsabilidades. Por exemplo, no OOP, você faria algo assim:
O método genérico está delegando uma tarefa específica - sobre a qual nada sabe - para outro objeto que implementa uma interface. O método genérico conhece apenas essa interface. No seu caso, essa interface seria uma função a ser chamada.
fonte
Em geral, não há nada errado em passar funções para outras funções. Se você estiver fazendo chamadas assíncronas e quiser fazer alguma coisa com o resultado, precisará de algum tipo de mecanismo de retorno de chamada.
Existem algumas desvantagens em potencial de simples retornos de chamada:
Com serviços web simples, a maneira como você está fazendo isso funciona bem, mas fica estranho se você precisar de um seqüenciamento de chamadas mais complexo. Existem algumas alternativas embora. Com o JavaScript, por exemplo, houve uma mudança no uso de promessas (o que há de tão bom nas promessas de javascript ).
Eles ainda envolvem a passagem de funções para outras funções, mas as chamadas assíncronas retornam um valor que recebe um retorno de chamada, em vez de receber diretamente um retorno de chamada. Isso oferece mais flexibilidade para compor essas chamadas em conjunto. Algo assim pode ser implementado facilmente no ActionScript.
fonte