OK, então o título é um pouco clickbaity, mas sério, eu já falei, não peça chute por um tempo. Gosto de como incentiva os métodos a serem usados como mensagens de maneira realmente orientada a objetos. Mas isso tem um problema incômodo que tem sido perturbador na minha cabeça.
Cheguei a suspeitar que código bem escrito pode seguir os princípios OO e princípios funcionais ao mesmo tempo. Estou tentando conciliar essas idéias e o grande ponto de discórdia em que aterrei é return
.
Uma função pura tem duas qualidades:
Chamá-lo repetidamente com as mesmas entradas sempre dá o mesmo resultado. Isso implica que é imutável. Seu estado é definido apenas uma vez.
Não produz efeitos colaterais. A única alteração causada pela chamada está produzindo o resultado.
Então, como alguém pode ser puramente funcional se você jurou usar return
como forma de comunicar resultados?
O dizer, não pergunte que a ideia funciona usando o que alguns considerariam um efeito colateral. Quando trato de um objeto, não o pergunto sobre seu estado interno. Eu digo o que preciso fazer e ele usa seu estado interno para descobrir o que fazer com o que eu disse para fazer. Depois que digo, não pergunto o que fez. Só espero que tenha feito algo sobre o que foi dito para fazer.
Penso em Tell, Don't Ask como mais do que apenas um nome diferente para encapsulamento. Quando uso return
, não faço ideia do que me chamou. Não posso falar do protocolo, tenho que forçá-lo a lidar com o meu protocolo. Que em muitos casos é expresso como o estado interno. Mesmo que o que está exposto não seja exatamente o estado, geralmente são apenas alguns cálculos realizados nos argumentos de estado e entrada. Ter uma interface para responder oferece a chance de massagear os resultados em algo mais significativo que o estado interno ou os cálculos. Isso é passagem de mensagem . Veja este exemplo .
No passado, quando unidades de disco tinham discos e um pen drive era o que você fazia no carro quando o volante estava frio demais para tocar com os dedos, fui ensinado como as pessoas irritantes consideram funções que possuem parâmetros fora dos parâmetros. void swap(int *first, int *second)
parecia tão útil, mas fomos encorajados a escrever funções que retornassem os resultados. Então, levei isso a sério pela fé e comecei a segui-la.
Mas agora vejo pessoas construindo arquiteturas onde objetos permitem que como eles foram construídos controlem para onde enviam seus resultados. Aqui está um exemplo de implementação . Injetar o objeto da porta de saída parece um pouco com a idéia do parâmetro out novamente. Mas é assim que os objetos dizer e não perguntar dizem a outros objetos o que fizeram.
Quando soube dos efeitos colaterais, pensei nele como o parâmetro de saída. Estávamos nos dizendo para não surpreender as pessoas, fazendo com que parte do trabalho acontecesse de maneira surpreendente, ou seja, não seguindo a return result
convenção. Agora, claro, eu sei que há uma pilha de problemas de encadeamento assíncrono paralelo com os quais os efeitos colaterais se complicam, mas o retorno é realmente apenas uma convenção que faz com que você deixe o resultado pressionado na pilha para que, como quer que seja chamado, você poderá soltá-lo mais tarde. Isso é tudo o que realmente é.
O que estou realmente tentando perguntar:
É return
a única maneira de evitar todo esse efeito colateral da miséria e obter segurança de linha sem travas, etc. Ou posso seguir dizer, não pergunte de uma maneira puramente funcional?