Depois de aprender a programação funcional em Haskell e F #, o paradigma OOP parece invertido com classes, interfaces, objetos. Quais aspectos do PF posso trazer para o trabalho que meus colegas de trabalho possam entender? Vale a pena conversar com meu chefe sobre estilos de reciclagem da minha equipe para que possamos usá-los?
Possíveis aspectos do PF:
- Imutabilidade
- Aplicação Parcial e Caril
- Funções de Primeira Classe (ponteiros de função / Objetos Funcionais / Padrão de Estratégia)
- Avaliação preguiçosa (e mônadas)
- Funções puras (sem efeitos colaterais)
- Expressões (vs. declarações - cada linha de código produz um valor em vez de ou além de causar efeitos colaterais)
- Recursão
- Correspondência de padrões
É um espaço livre para todos, onde podemos fazer o que a linguagem de programação suportar até o limite que a linguagem suporta? Ou existe uma orientação melhor?
object-oriented
programming-practices
functional-programming
paradigms
Trident D'Gao
fonte
fonte
Respostas:
A programação funcional é um paradigma diferente da programação orientada a objetos (uma mentalidade diferente e uma maneira diferente de pensar sobre os programas). Você começou a perceber que aqui há mais de uma maneira (orientada a objetos) para pensar sobre os problemas e suas soluções. Existem outros (programação processual e genérica vêm à mente). Como você reage a esse novo conhecimento, se você aceita e integra essas novas ferramentas e abordagens ao seu conjunto de habilidades, determinará se você cresce e se torna um desenvolvedor mais completo e qualificado.
Todos somos treinados para lidar com isso e nos sentimos confortáveis com um certo nível de complexidade. Eu gosto de chamar isso de limite hrair de uma pessoa (de Watership Down, quão alto você pode contar). É ótimo expandir sua mente, sua capacidade de considerar mais opções e ter mais ferramentas para abordar e resolver problemas. Mas é uma mudança e tira você da sua zona de conforto.
Um problema que você pode encontrar é que ficará menos conteúdo para acompanhar a multidão "tudo é um objeto". Talvez você precise desenvolver paciência ao trabalhar com pessoas que podem não entender (ou querer entender) por que uma abordagem funcional para o desenvolvimento de software funciona bem para certos problemas. Assim como uma abordagem de programação genérica funciona bem para certos problemas.
Boa sorte!
fonte
A programação funcional gera produtividade muito prática e prática na escrita diária de códigos: alguns recursos favorecem a dispersão, o que é ótimo porque quanto menos código você escreve, menos falhas você faz e menos manutenção é necessária.
Sendo um matemático, acho as coisas funcionais sofisticadas muito atraentes, mas geralmente é útil ao projetar um aplicativo: essas estruturas podem codificar na estrutura do programa muitos invariantes do programa, sem representar esses invariantes por variáveis.
Minha combinação favorita pode parecer bastante trivial, no entanto, acredito que ela tenha um impacto muito alto na produtividade. Essa combinação é de Aplicação Parcial e Funções de Currying e Primeira Classe, que eu rotularia de novo para nunca mais escrever um loop for : em vez disso, passe o corpo do loop para uma função de iteração ou mapeamento. Recentemente, fui contratado para um trabalho em C ++ e notei divertidamente que perdi o hábito de escrever loops!
A combinação de recursão e correspondência de padrões aniquila a necessidade desse padrão de design do visitante . Basta comparar o código que você precisa para programar um avaliador de expressões booleanas: em qualquer linguagem de programação funcional, isso deve ter cerca de 15 linhas de código; em OOP, a coisa certa a fazer é usar esse padrão de design do Visitor , que transforma esse exemplo de brinquedo em um extenso ensaio. As vantagens são óbvias e não conheço nenhum inconveniente.
fonte
list.forEach(System.out::println);
Do ponto de vista do FP,println
é uma função que aceita dois argumentos, um destinoPrintStream
e um valor,Object
mas o método doCollection
sforEach
espera uma função com apenas um argumento que pode ser aplicado a todos os elementos. Portanto, o primeiro argumento está vinculado à instância encontrada aoSystem.out
ceder a uma nova função com um argumento. É mais simples queBiConsumer<…> c=PrintStream::println; PrintStream a1=System.out; list.forEach(a2 -> c.accept(a1, a2));
Você pode ter que restringir quais partes do seu conhecimento você usa no trabalho, da maneira que o Super-homem tem que fingir ser Clark Kent para aproveitar as vantagens de uma vida normal. Mas saber mais nunca vai te machucar. Dito isto, alguns aspectos da Programação Funcional são apropriados para uma loja Orientada a Objetos, e outros podem valer a pena conversar com seu chefe, para que você possa aumentar o nível médio de conhecimento da sua loja e escrever um código melhor como resultado.
FP e OOP não são mutuamente exclusivos. Olhe para Scala. Alguns acham que é o pior porque é um FP impuro, mas alguns acham que é o melhor pelo mesmo motivo.
Um por um, aqui estão alguns aspectos que funcionam muito bem com OOP:
Funções puras (sem efeitos colaterais) - Todas as linguagens de programação que conheço suportam isso. Eles tornam seu código muito, muito mais fácil de raciocinar e devem ser usados sempre que possível. Você não precisa chamá-lo de FP. Apenas chame de boas práticas de codificação.
Imutabilidade: String é sem dúvida o objeto Java mais usado e é imutável. Eu cubro objetos imutáveis em Java e imutáveis coleções de Java no meu blog. Parte disso pode ser aplicável a você.
Funções de primeira classe (ponteiros de função / objetos funcionais / padrão de estratégia) - O Java possui uma versão mutante e prejudicada desde a versão 1.1, com a maioria das classes de API (e existem centenas) que implementam a interface do Listener. Runnable é provavelmente o objeto funcional mais comumente usado. As funções de primeira classe são mais trabalhosas para codificar em um idioma que não as suporta nativamente, mas às vezes valem o esforço extra quando simplificam outros aspectos do seu código.
A recursão é útil para processar árvores. Em uma loja OOP, esse é provavelmente o principal uso apropriado de recursão. O uso de recursão por diversão no OOP provavelmente deve ser desaprovado, se por nenhum outro motivo, a maioria dos idiomas OOP não tiver o espaço de pilha por padrão para tornar essa uma boa idéia.
Expressões (vs. Declarações - cada linha de código produz um valor em vez de, ou além de causar efeitos colaterais) - O único operador avaliador em C, C ++ e Java é o Operador Ternário . Discuto o uso apropriado no meu blog. Você pode escrever algumas funções simples que são altamente reutilizáveis e avaliativas.
Avaliação Preguiçosa (e Mônadas) - principalmente restrita à Inicialização preguiçosa no OOP. Sem os recursos de idioma para suportá-lo, você pode encontrar algumas APIs que são úteis, mas escrever sua própria é difícil. Maximize o uso de fluxos - consulte as interfaces Writer e Reader para obter exemplos.
Aplicação Parcial e Caril - Não é prático sem as funções de primeira classe.
Correspondência de padrões - geralmente desencorajada em OOP.
Em resumo, eu não acho que o trabalho deva ser gratuito para todos, onde você pode fazer o que a linguagem de programação suportar, até o limite que ela suporta. Acho que a legibilidade de seus colegas de trabalho deve ser seu teste decisivo para códigos feitos para contratação. Onde isso o incomoda mais, eu gostaria de começar uma educação no trabalho para ampliar os horizontes de seus colegas de trabalho.
fonte
public interface BiConsumer<T, U> { public void accept(T t, U u); }
Existem outras interfaces funcionais úteis no java.util.function.Most OOP languages don't have the stack space for it
Verdade? Tudo o que você precisa é de 30 níveis de recursão para gerenciar bilhões de nós em uma árvore binária equilibrada. Tenho certeza de que meu espaço de pilha é adequado para muito mais níveis do que isso.Além da programação funcional e da programação orientada a objetos, também há programação declarativa (SQL, XQuery). Aprender cada estilo ajuda a obter novas idéias e você aprenderá a escolher a ferramenta certa para o trabalho.
Mas sim, pode ser muito frustrante escrever código em um idioma e saber que se você estivesse usando outra coisa, seria muito mais produtivo para um domínio de problema específico. No entanto, mesmo se você estiver usando uma linguagem como Java, é possível aplicar conceitos do FP ao seu código Java, ainda que de maneira indireta. A estrutura do Guava, por exemplo, faz parte disso.
fonte
Como programador, acho que você nunca deve parar de aprender. Dito isto, é muito interessante que o aprendizado de FP esteja manchando suas habilidades de OOP. Costumo pensar em aprender POO como aprender a andar de bicicleta; você nunca esquece como fazê-lo.
À medida que aprendi os meandros do FP, me vi pensando mais matematicamente e ganhei uma melhor perspectiva dos meios pelos quais escrevo software. Essa é a minha experiência pessoal.
À medida que você ganha mais experiência, os principais conceitos de programação serão muito mais difíceis de perder. Então, sugiro que você relaxe no FP até que os conceitos de POO sejam totalmente solidificados em sua mente. FP é uma mudança de paradigma definitiva. Boa sorte!
fonte
Já existem muitas respostas boas, portanto as minhas abordarão um subconjunto da sua pergunta; ou seja, eu me ofendo à premissa de sua pergunta, já que OOP e recursos funcionais não são mutuamente exclusivos.
Se você usa C ++ 11, existem muitos desses tipos de recursos de programação funcional incorporados à biblioteca de idiomas / padrão que sinergizam (muito) bem com o OOP. Obviamente, não tenho certeza de quão bem o TMP será recebido por seu chefe ou colegas de trabalho, mas o ponto é que você pode obter muitos desses recursos de uma forma ou de outra em linguagens / OOP não funcionais, como C ++.
O uso de modelos com recursão no tempo de compilação depende dos seus três primeiros pontos,
Como os valores do modelo são imutáveis (constantes em tempo de compilação), qualquer iteração é feita usando recursão e a ramificação é feita usando (mais ou menos) correspondência de padrões, na forma de resolução de sobrecarga.
Quanto aos outros pontos, o uso
std::bind
estd::function
a aplicação parcial de funções são fornecidas, e os ponteiros de função estão embutidos no idioma. Objetos que podem ser chamados são objetos funcionais (assim como aplicativos de funções parciais). Observe que, por objetos que podem ser chamados, quero dizer aqueles que definem seusoperator ()
.Avaliação preguiçosa e funções puras seriam um pouco mais difíceis; para funções puras, você pode usar funções lambda que capturam apenas por valor, mas isso não é o ideal.
Por fim, aqui está um exemplo de uso de recursão em tempo de compilação com aplicativo de função parcial. É um exemplo um tanto artificial, mas demonstra a maioria dos pontos acima. Ele vincula recursivamente os valores de uma tupla a uma determinada função e gera um objeto de função (que pode ser chamado)
fonte