Caso : estou trabalhando em uma empresa, escrevendo um aplicativo em Python que lida com muitos dados em matrizes. Eu sou o único desenvolvedor deste programa no momento, mas provavelmente será usado / modificado / estendido no futuro (1-3 anos) por algum outro programador, neste momento desconhecido para mim. Provavelmente não estarei lá diretamente para ajudar, mas talvez dê algum suporte por e-mail se tiver tempo para isso.
Então, como desenvolvedor que aprendeu programação funcional (Haskell), eu tendem a resolver, por exemplo, filtrar assim:
filtered = filter(lambda item: included(item.time, dur), measures)
O restante do código é OO, são apenas alguns casos pequenos em que eu quero resolvê-lo assim, porque é muito mais simples e mais bonito para mim.
Pergunta : Hoje está bom escrever código como este?
- Como um desenvolvedor que não escreveu / aprendeu FP reage a códigos como este?
- É legível?
- Modificável?
Devo escrever uma documentação como explicar a uma criança o que a linha faz?
# Filter out the items from measures for which included(item.time, dur) != True
Perguntei ao meu chefe e ele apenas disse "FP é magia negra, mas se funcionar e for a solução mais eficiente, não há problema em usá-lo".
Qual a sua opinião sobre isso? Como programador não-FP, como você reage ao código? O código é "googable" para que você possa entender o que ele faz? Eu adoraria comentários sobre isso.
# Select the item's from measures for which included(item.time, dur) == True
evitar um duplo negativo sempre melhora a compreensão.Respostas:
Para mim: Sim, mas eu entendi que a comunidade Python geralmente considera as compreensões de lista uma solução mais limpa do que usar
map()
/filter()
.De fato, o GvR até considerou abandonar completamente essas funções.
Considere isto:
Além disso, isso tem o benefício de que a compreensão da lista sempre retornará uma lista.
map()
e,filter()
por outro lado, retornará um iterador no Python 3.Nota: Se você deseja ter um iterador, é tão simples quanto substituir
[]
por()
:Para ser sincero, vejo pouca ou nenhuma razão para usar
map()
oufilter()
no Python.Sim, certamente, no entanto, há uma coisa para facilitar: tornar uma função, não uma lambda.
Se sua condição se tornar mais complexa, isso será muito mais fácil, além disso, permitirá que você reutilize seu cheque. (Observe que você pode criar funções dentro de outras funções, isso pode mantê-lo mais próximo do local onde é usado.)
Ele procura na documentação do Python e sabe como funciona cinco minutos depois. Caso contrário, ele não deveria estar programando em Python.
map()
efilter()
são extremamente simples. Não é como se você estivesse pedindo para eles entenderem mônadas. É por isso que acho que você não precisa escrever esses comentários. Use bons nomes de variáveis e funções, então o código é quase auto-explicativo. Você não pode prever que idioma os recursos que um desenvolvedor não conhece. Pelo que você sabe, o próximo desenvolvedor pode não saber o que é um dicionário.O que não entendemos geralmente não é legível para nós. Assim, você poderia argumentar que não é menos legível do que a compreensão de uma lista, se você nunca viu nenhum deles antes. Mas, como Joshua mencionou em seu comentário, eu também acredito que é importante ser consistente com o que outros desenvolvedores usam - pelo menos se a alternativa não oferecer uma vantagem substancial.
fonte
map
efilter
fazer em python 3.reduce
como exemplo um contra-exemplo: você sempre pode usar um argumento de compreensão de lista , pois é relativamente difícil substituí-loreduce
por um gerador embutido ou compreensão de lista.Como a comunidade de desenvolvedores está recuperando o interesse pela programação funcional, não é incomum ver alguma programação funcional em linguagens que eram originalmente totalmente orientadas a objetos. Um bom exemplo é o C #, onde tipos anônimos e expressões lambda permitem ser muito mais curtos e expressivos através da programação funcional.
Dito isto, a programação funcional é estranha para iniciantes. Por exemplo, quando, durante um curso de treinamento, expliquei aos iniciantes como eles podem aprimorar seu código por meio da programação funcional em C #, alguns deles não estavam convencidos e outros disseram que o código original era mais fácil de entender para eles. O exemplo que dei a eles foi o seguinte:
Código antes da refatoração:
Mesmo código após refatoração usando FP:
Isso me faz pensar que:
não se preocupe se souber que o próximo desenvolvedor que manterá seu código terá experiência geral suficiente e algum conhecimento de programação funcional, mas:
caso contrário, evite a programação funcional ou coloque um comentário detalhado explicando ao mesmo tempo a sintaxe, as vantagens e as possíveis advertências de sua abordagem em comparação com uma não-funcional de programação.
fonte
Não sou programador de FP e recentemente modifiquei o código do meu colega em JavaScript. Houve uma solicitação de HTTP com um retorno de chamada que se parecia muito com a declaração incluída por você. Devo dizer que demorei algum tempo (como meia hora) para descobrir tudo (o código em geral não era muito grande).
Não houve comentários e acho que não houve necessidade de nenhum. Eu nem pedi ao meu colega para me ajudar a entender o código dele.
Considerando que estou trabalhando há cerca de 1,5 anos, acho que a maioria dos programadores será capaz de entender e modificar esse código, desde que eu fiz.
Além disso, como Joachim Sauer disse em seu comentário, muitas vezes existem partes do FP em vários idiomas, como o C # (indexOf, por exemplo). Muitos programadores que não são de FP lidam com isso com bastante frequência, e o trecho de código que você incluiu não é algo terrível ou incompreensível.
fonte
Eu diria que sim definitivamente!
Existem muitos aspectos da programação funcional, e o uso de funções de ordem superior, como no seu exemplo, é apenas um deles.
Por exemplo, considero que escrever funções puras é extremamente importante para qualquer software escrito em qualquer idioma (onde "puro" não quero dizer efeitos colaterais), porque:
Também evito muitas vezes alterar valores e variáveis - outro conceito emprestado do FP.
Ambas as técnicas funcionam bem em Python e em outras linguagens que normalmente não são classificadas como funcionais. Eles geralmente são suportados pela própria linguagem (ou seja,
final
variáveis em Java). Assim, futuros programadores de manutenção não enfrentarão uma barreira enorme para entender o código.fonte
Tivemos a mesma discussão sobre uma empresa em que trabalhei no ano passado.
A discussão dizia respeito a "código mágico" e se deveria ser encorajada ou não. Ao analisar um pouco mais, parecia que as pessoas tinham opiniões muito diferentes sobre o que realmente era "código mágico". Os que iniciaram a discussão pareciam significar principalmente que expressões (em PHP) que usavam estilo funcional eram "códigos mágicos", enquanto desenvolvedores originários de outras linguagens que usavam mais estilo FP em seus códigos parecem pensar que o código mágico era bastante quando você fez a inclusão dinâmica de arquivos por meio de nomes de arquivos e assim por diante.
Nunca chegamos a uma boa conclusão sobre isso, mais do que as pessoas pensam que o código que parece desconhecido é "mágico" ou difícil de ler. Portanto, é uma boa idéia evitar código que parece desconhecido para outros usuários? Eu acho que depende de onde é usado. Eu evitaria usar expressões no estilo fp (inclusão dinâmica de arquivos e assim por diante) em um método principal (ou partes centrais importantes de aplicativos) em que os dados deveriam ser encapsulados de maneira clara e fácil de ler, intuitiva. Por outro lado, não acho que deva ter medo de empurrar o envelope, os outros desenvolvedores provavelmente aprenderão FP rapidamente se forem confrontados com o código FP e talvez tenham algum bom recurso interno para consultar sobre os problemas.
TL; DR: Evite na parte central de alto nível dos aplicativos (que precisam ser lidos para obter uma visão geral da funcionalidade do aplicativo). Caso contrário, use-o.
fonte
A comunidade C ++ recentemente também recebeu lambda e acredito que eles tenham aproximadamente a mesma pergunta. A resposta pode não ser a mesma, no entanto. O equivalente em C ++ seria:
Agora
std::copy
não é novo, e as_if
variantes também não são novas, mas o lambda é. No entanto, é definido de forma bastante clara no contexto:dur
é capturado e, portanto, constante,Item i
varia no loop, e a únicareturn
declaração faz todo o trabalho.Isso parece aceitável para muitos desenvolvedores de C ++. Porém, não amostrei opiniões sobre lambda de ordem superior e esperaria muito menos aceitação.
fonte
Poste um trecho de código em um colega desenvolvedor que não seja tão fluente em python e pergunte se ele pode passar 5 minutos verificando o código para ver se ele entende.
Se sim, você provavelmente está pronto para ir. Caso contrário, você deve torná-lo mais claro.
Seu colega poderia ser tolo e não entender algo que deveria ser óbvio? Sim, mas você deve sempre programar de acordo com o KISS.
Talvez seu código seja mais eficiente / bonito / elegante do que uma abordagem mais direta e à prova de idiotas? Então você precisa se perguntar: eu preciso fazer isso? Novamente, se a resposta for não, não faça!
Se depois de tudo isso, você ainda acha que precisa e deseja fazê-lo da maneira FP, faça-o de qualquer maneira. Confie nos seus instintos, eles são mais adequados às suas necessidades do que a maioria das pessoas em qualquer fórum :)
fonte