Legibilidade da programação funcional [fechada]


13

Estou curioso sobre isso porque, antes de aprender qualquer linguagem funcional, lembro-me de todas horrivelmente, terrivelmente, terrivelmente ilegíveis. Agora que conheço Haskell e f #, acho que demora um pouco mais para ler menos código, mas esse código faz muito mais do que uma quantia equivalente faria em uma linguagem imperativa, então parece um ganho líquido e não sou extremamente praticado em funcional.

Aqui está minha pergunta, eu sempre ouço do pessoal da OOP que o estilo funcional é terrivelmente ilegível. Estou curioso para saber se é esse o caso e estou me iludindo, ou se eles tivessem tempo para aprender uma linguagem funcional, todo o estilo não seria mais ilegível que o OOP?

Alguém viu alguma evidência ou tem histórias de que viu isso acontecer de uma maneira ou de outra com frequência suficiente para dizer? Se a escrita funcional é realmente de menor legibilidade, não quero continuar usando, mas realmente não sei se é esse o caso ou não.


1
Lembro-me de olhar o código para "Super Nario Brothers" svn.coderepos.org/share/lang/haskell/nario quando mal sabia algo sobre programação funcional e lembro-me de pensar 'Uau. Isso parece realmente legível '
WuHoUnited 2/12



3
@BlackICE linq e lambdas estão muito longe de definir "programação funcional". A programação funcional envolve sistemas de tipos mais frequentemente do que não, porque quando você começa a reconhecer funções como tipos, em vez de apenas objetos / classes / registros como tipos, você acaba com um monte de novas habilidades e técnicas. As expressões LINQ e Lambda (ou as funções de mônada de lista e ordem superior) são apenas duas técnicas resultantes específicas, das quais existem muito mais.
Jimmy Hoffa 27/02

Respostas:


15

A legibilidade do código é muito subjetiva . Por esse motivo, pessoas diferentes considerariam o mesmo código legível ou ilegível.

Uma tarefa x = x + 1parece estranha para um matemático, porque uma tarefa parece enganosamente semelhante a uma comparação.

Um simples padrão de design de OOP não seria totalmente claro para alguém que não esteja familiarizado com esses padrões. Considere singleton . Alguém perguntaria "Por que preciso de um construtor privado? Qual é o método misterioso getInstance() ? Por que não criamos uma variável global e atribuímos um objeto lá?"

O mesmo se aplica a um código FP. A menos que você conheça os padrões lógicos nos bastidores, será muito difícil até entender algo muito básico, por exemplo, como passar uma função como argumento para outra função.

Dito isto, deve-se entender que o FP não é uma bala de prata. Existem muitas aplicações em que o FP seria difícil de aplicar e, portanto, levaria a um código legível pior .


As pessoas devem criar algo semelhante a elas mesmas (humanidade). Por exemplo, mesmo na visão computacional, temos redes neurais agora. O corpo humano consiste em objetos, atributos, métodos e descrevemos outras coisas usando objetos, atributos, métodos. Portanto, a programação funcional não faz nenhum sentido
user25

12

Resposta curta:

Um dos elementos que faz as pessoas dizerem que o código de programação funcional é difícil de ler é que ele dá preferência a uma sintaxe mais compacta.

Resposta longa:

A programação funcional em si não pode ser legível ou ilegível, pois é um paradigma, não um estilo de escrever código. Em C #, por exemplo, a programação funcional se parece com:

return this.Data.Products
    .Where(c => c.IsEnabled)
    .GroupBy(c => c.Category)
    .Select(c => new PricesPerCategory(category: c.Key, minimum: c.Min(d => d.Price), maximum: c.Max(d => d.Price)));

e seria considerado legível por qualquer pessoa com experiência suficiente em Java, C # ou linguagens semelhantes.

A sintaxe do idioma, por outro lado, é mais compacta para muitos idiomas funcionais (incluindo Haskell e F #) em comparação aos idiomas populares de POO, dando preferência a símbolos em vez de palavras em inglês comum.

Isso se aplica a idiomas fora do FP também. Se você comparar idiomas populares de POO com outros menos populares que tendem a usar mais palavras em inglês, os últimos pareceriam mais fáceis de entender para pessoas sem experiência em programação.

Comparar:

public void IsWithinRanges<T>(T number, param Range<T>[] ranges) where T : INumeric
{
    foreach (var range in ranges)
    {
        if (number >= range.Left && number <= range.Right)
        {
            return true;
        }
    }

    return false;
}

para:

public function void IsWithinRanges
    with parameters T number, param array of (Range of T) ranges
    using generic type T
    given that T implements INumeric
{
    for each (var range in ranges)
    {
        if (number is from range.Left to range.Right)
        {
            return true;
        }
    }

    return false;
}

Do mesmo jeito:

var a = ((b - c) in 1..n) ? d : 0;

pode ser expresso em uma linguagem imaginária como:

define variable a being equal to d if (b minus c) is between 1 and n or 0 otherwise;

Quando uma sintaxe mais curta é melhor?

Embora uma sintaxe mais detalhada seja mais fácil de entender para um iniciante, uma sintaxe mais compacta é mais fácil para desenvolvedores experientes. Código mais curto significa menos caracteres para digitar, o que significa mais produtividade.

Especialmente, não faz sentido forçar uma pessoa a digitar uma palavra-chave para indicar algo que pode ser deduzido da sintaxe.

Exemplos:

  • No PHP, você precisa digitar functionantes de cada função ou método, sem motivo específico para fazê-lo.

  • Ada sempre me horrorizou por forçar os desenvolvedores a digitar muitas palavras em inglês, especialmente porque não há um IDE correto com preenchimento automático. Eu não usei Ada recentemente e o tutorial oficial está fora do ar, então não posso dar um exemplo; se alguém tiver um exemplo, fique à vontade para modificar minha resposta.

  • A sintaxe 1..n, usada em muitos FP (e Matlab), pode ser substituída por between 1, nou between 1 and nou between (1, n). A betweenpalavra-chave facilita a compreensão de pessoas que não estão familiarizadas com a sintaxe do idioma, mas ainda assim, dois pontos são muito mais rápidos para digitar.


8
Eu concordo com o sentimento, mas por razões diferentes. Não se trata da facilidade com que um especialista pode escrever código, pois o código geralmente é lido com muito mais frequência do que está escrito. Um código mais curto também pode ajudar na legibilidade, não desperdiçando tempo precioso, espaço na tela e capacidade mental se algo já fosse óbvio a partir de um indicador mais curto (por exemplo, novas linhas em vez de ponto e vírgula, as duas coincidências de qualquer maneira). Também pode doer quando se torna muito enigmático (por exemplo, prefiro for x in xsmais for x xs, porque me ajuda a distinguir variável e contêiner de loop).

Muitas das pessoas que eu acho queixam-se do FP, bem como do snippet C # que você listou como disse, também é um exemplo de FP. Talvez isso seja mais um problema dos meus colegas do que a legibilidade, se a maioria das pessoas de OOP achar esse trecho legível, embora eu não esteja completamente convencido de que a maioria das pessoas de OOP faça com minhas experiências.
Jimmy Hoffa

@ Jimmy Hoffa: Veja programmers.stackexchange.com/a/158721/6605, onde discuto exatamente o trecho de C # e como ele é percebido pelos programadores iniciantes.
Arseni Mourzenko

1
@Ergiy: em Java ou C #, uma assinatura de método não possui uma methodpalavra-chave. Exemplo: public int ComputePrice(Product product). Adicionar essa palavra-chave, como o que o PHP fez, apenas adiciona confusão ao invés de facilitar a leitura. Se um programador é incapaz de entender que uma função é uma função de sua assinatura, esse programador não tem experiência alguma ou o código é muito mais ilegível do que o pior código de peça que eu já vi.
Arseni Mourzenko

1
@Ergiy: há casos em que a verbosidade pode ajudar (caso contrário, veríamos idiomas e códigos como p i ComputePrice(product): _.unitPrice * ~.cart[_]), mas alguns idiomas levam isso muito longe. O exemplo da functionpalavra-chave redundante no PHP é um bom exemplo.
Arseni Mourzenko

6

Eu acho que uma das razões é que a programação funcional tende a trabalhar com conceitos muito mais abstratos. Isso torna o código mais curto e mais legível para as pessoas que conhecem e entendem os conceitos (porque expressam adequadamente a essência do problema), mas é ilegível para as pessoas que não estão familiarizadas com eles.

Por exemplo, para um programador funcional, é natural escrever um código que possa falhar em diferentes pontos da Maybemônada ou Eithermônada. Ou, para escrever uma computação com estado com a ajuda da Statemônada. Mas para alguém que não entende o conceito de mônadas, tudo isso parece algum tipo de feitiçaria negra.

Portanto, acho que seria razoável usar bits de programação funcional, mesmo em uma equipe de pessoas com OOP, desde que se use conceitos fáceis de entender ou aprender, como mapear uma coleção com uma função ou fechamentos .

(E, é claro, isso também depende do programador que escreveu algum trecho de código. Você pode escrever um código terrivelmente ilegível em qualquer idioma, assim como um estilo agradável e limpo.)


2

A legibilidade não tem nada a ver com paradigmas, modelos e outros. Quanto mais o código refletir a semântica do domínio do problema, mais ele estará operando uma terminologia e expressões idiomáticas desse domínio do problema, mais legível será.

Esta é a razão pela qual o código OOP não é tão legível: nem todos os problemas do mundo real são naturalmente expressos em termos de taxonomias hierárquicas. Objetos que passam mensagens entre si é um conceito estranho e está muito longe de qualquer coisa "real". Surpreendentemente, existem muito mais conceitos do mundo real que podem ser mapeados naturalmente para os idiomas funcionais. Os problemas tendem a ser definidos declarativamente; portanto, uma solução declarativa é mais natural.

Embora existam muitas outras semânticas que poderiam estar mais próximas do mundo real do que uma pura OOP funcional, pura, um fluxo de dados puro ou o que quer que seja. E devido a esse fato, uma abordagem orientada à linguagem para a solução de problemas produz o código mais legível, superando todos os paradigmas "puros" existentes. Com os idiomas específicos do domínio, todo problema é expresso em sua própria terminologia natural. E as linguagens funcionais são um pouco melhores do que as coisas comuns da OOP para facilitar a implementação de DSLs (embora abordagens muito melhores estejam disponíveis).


1

A legibilidade do código é subjetiva. Tenho certeza de que algumas pessoas o criticam por falta de entendimento. Existem idiomas naturalmente diferentes na maneira como os padrões comuns são implementados. Por exemplo, o padrão Visitor realmente não faz sentido em um idioma com correspondência de padrões .

A inferência de tipo pode ser um recurso complicado. Geralmente, é um grande acelerador de desenvolvimento; no entanto, às vezes pode ser difícil descobrir quais tipos estão envolvidos devido à falta de contexto que leva a erros confusos. Isso não se limita a quais linguagens de programação funcional - eu já vi isso também em modelos C ++!

As linguagens modernas tendem a ser multiparadigma . Isso inclui C # e F #. É possível escrever um estilo funcional em C # e um estilo imperativo em F #. As mesmas pessoas que criticam linguagens funcionais provavelmente escrevem código funcional em sua linguagem orientada a objetos.

O desenvolvimento comercial em linguagens funcionais ainda é relativamente imaturo. Eu já vi vários erros cometidos que seriam considerados ruins em qualquer idioma. Tal como:

  1. Mudando de estilo à medida que você aprende o idioma (e não a refatoração), levando à inconsistência.
  2. Muito em um arquivo.
  3. Muitas declarações em uma linha.

Em relação aos erros, eu também acrescentaria: 4. Uso excessivo de símbolos, por exemplo: ~ @ # $% ^ & * () -_ + = \ | /.,; 5. Recursos implícitos: declarações / palavras-chave / declarações opcionais, conversões implícitas, etc .;
Sergiy Sokolenko
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.