Atualmente, estou lendo o Código Limpo de Robert Martin . Eu acho ótimo e, ao escrever o código OO, levo suas lições a sério. Em particular, acho que o conselho dele de usar pequenas funções com nomes significativos faz meu código fluir muito mais suavemente. É melhor resumido por esta citação:
[Nós] queremos poder ler o programa como se fosse um conjunto de parágrafos TO, cada um dos quais descrevendo o nível atual de abstração e referenciando parágrafos TO subsequentes no próximo nível abaixo.
( Código Limpo , página 37: um "parágrafo TO" é um parágrafo que começa com uma frase expressa no infinitivo. "Para executar X, executamos as etapas Y e Z." "Para executar Y, nós ..." etc. ) Por exemplo:
PARA RenderPageWithSetupsAndTeardowns, verificamos se a página é uma página de teste e, se for o caso, incluímos as configurações e os teardowns. Nos dois casos, renderizamos a página em HTML
Também escrevo código funcional para o meu trabalho. Os exemplos de Martin no livro definitivamente são lidos como se fossem um conjunto de parágrafos e são muito claros - mas não tenho tanta certeza de que "leia como um conjunto de parágrafos" seja uma qualidade desejável para o código funcional. .
Tomando um exemplo da biblioteca padrão Haskell :
maximumBy :: (a -> a -> Ordering) -> [a] -> a
maximumBy _ [] = error "List.maximumBy: empty list"
maximumBy cmp xs = foldl1 maxBy xs
where
maxBy x y = case cmp x y of
GT -> x
_ -> y
Isso é o mais longe que você pode obter dos conselhos de Martin, mas é conciso e idiomático Haskell. Ao contrário dos exemplos de Java em seu livro, não consigo imaginar como refatorá-lo para algo que tenha o tipo de cadência que ele pede. Suspeito que Haskell, escrito de acordo com o padrão do Código Limpo , sairia por muito tempo e antinatural.
Estou errado ao considerar (pelo menos alguns) o Código Limpo em desacordo com as práticas recomendadas de programação funcional? Existe uma maneira sensata de reinterpretar o que ele diz em um paradigma diferente?
fonte
xs
é um nome ruim, mas é tão comum em linguagens funcionais quantoi
em variáveis de loop.Respostas:
O Código Limpo é, antes de tudo, um manual de estilo. Strunk e branco não se aplicam quando você está escrevendo em Klingon. A idéia é que você queira deixar claro para os programadores que provavelmente lerão seu código. Você deseja ter um código modularizado e fácil de reestruturar. Existem maneiras de fazer isso em Haskell, assim como existem em qualquer outro idioma, mas os detalhes precisos variam.
Dito isto, existem várias diretrizes de estilo para Haskell. O Stack Overflow também possui um guia bastante abrangente . Manter a lógica de codificação direta e breve parece ser bastante constante. A generalização de funções também é enfatizada, pois leva à modularidade. O código DRY também é enfatizado, o mesmo que com o Código Limpo.
No final, as diretrizes de código da Clean Code e Haskell lutam pela mesma coisa, mas acabam seguindo seus próprios caminhos para chegar lá.
fonte
Não sei se sigo o que você quer dizer com seu exemplo. Os parágrafos, como ele os descreve, não exigem muito esforço. Ele não quer dizer que o código deva ler como o inglês. A parte importante é o agrupamento de funcionalidades no mesmo nível de abstração, em uma progressão lógica. Esse é um conceito estrutural teórico que transcende os paradigmas de programação.
Expressado no formato "parágrafo" de Bob Martin, li seu exemplo como:
maximumBy
, você precisa de uma função de pedido e de uma lista, e o resultado é um elemento dessa lista.maximumBy
lista vazia e qualquer função de pedido, é um erro.maximumBy
de uma listaxs
, você dobra essa lista usando amaxBy
funçãomaxBy
dois elementos da lista, compare-os usando a função de pedido fornecida. Se o primeiro elemento for maior, escolha-o. Caso contrário, escolha o segundo.Você está começando com os conceitos mais gerais e progredindo para mais detalhes, assim como nos exemplos imperativos. A idéia dos "parágrafos TO" é que você pode parar de ler em um determinado momento quando obtiver detalhes suficientes, sem precisar pular a página para cima e para baixo. Esse é certamente o caso aqui.
Talvez alguns nomes possam ser melhores, mas são convenções comuns da linguagem, especialmente ao escrever funções genéricas de ordem superior. Nomes de funções de ordem superior também não se traduzem bem em frases verbais imperativas, como nos exemplos do livro, porque descrevem mais as relações entre os verbos.
Existem maneiras de implementar isso que não seguem as diretrizes "parágrafo TO". Deixar a assinatura de tipo explícita omitiria a sentença "visão geral" de nível superior. Você pode usar uma expressão if para o tratamento de erros em vez da correspondência de padrões, o que atrapalha isso de maneira inadequada com outro nível de abstração. Você pode incorporar
maxBy
uma função anônima em vez de atribuir um nome que possa ser descrito posteriormente com mais detalhes.Na verdade, acho que construções como
where
na verdade se encaixam melhor no formato do parágrafo, porque você pode usá-las para dar um nome a um detalhe mais profundo de uma maneira próxima à maneira como a expressamos em inglês e limitar o escopo de maneira semelhante em um caminho claro para o contexto do "parágrafo".fonte