A functional programming substitui os padrões de design do GoF?

Desde que comecei a aprender F # e OCaml no ano passado, li um grande número de artigos que insistem que padrões de design (especialmente em Java) são soluções alternativas para os resources ausentes em linguagens imperativas. Um artigo que encontrei faz uma afirmação bastante forte :

A maioria das pessoas que conheci leram o livro Design Patterns da Gang of Four. Qualquer programador que se preze lhe dirá que o livro é agnóstico em termos de linguagem e os padrões se aplicam à engenharia de software em geral, independentemente do idioma que você usa. Esta é uma afirmação nobre. Infelizmente está muito longe da verdade.

Linguagens funcionais são extremamente expressivas. Em uma linguagem funcional, não é necessário ter padrões de design, porque a linguagem é provavelmente de alto nível; você acaba programando em conceitos que eliminam todos os padrões de design.

As principais características da functional programming incluem funções como valores de primeira class, currying, valores imutáveis, etc. Não parece óbvio para mim que os padrões de projeto OO estejam se aproximando de qualquer um desses resources.

Além disso, em linguagens funcionais que suportam OOP (como F # e OCaml), parece-me óbvio que os programadores que usam essas linguagens usariam os mesmos padrões de projeto disponíveis para todas as outras linguagens OOP. Na verdade, agora eu uso F # e OCaml todos os dias, e não há diferenças marcantes entre os padrões que eu uso nessas linguagens versus os padrões que uso quando escrevo em Java.

Existe alguma verdade na alegação de que a functional programming elimina a necessidade de padrões de projeto de OOP? Em caso afirmativo, você poderia postar ou vincular a um exemplo de um padrão típico de design OOP e seu equivalente funcional?

A postagem do blog que você citou exagera sua afirmação um pouco. O FP não elimina a necessidade de padrões de design. O termo “padrões de design” não é amplamente usado para descrever a mesma coisa em linguagens FP. Mas eles existem. As linguagens funcionais têm muitas regras de melhores práticas na forma “quando você encontrar o problema X, use código que se parece com Y”, que é basicamente o que é um padrão de design.

No entanto, é correto que a maioria dos padrões de projeto específicos de OOP sejam praticamente irrelevantes em linguagens funcionais.

Não acho que seja particularmente controverso dizer que os padrões de design em geral só existem para consertar falhas na linguagem. E se outra linguagem puder resolver o mesmo problema trivialmente, essa outra linguagem não precisará de um padrão de design para ela. Os usuários desse idioma podem nem estar cientes de que o problema existe , porque, bem, não é um problema nesse idioma.

Aqui está o que a Gang of Four tem a dizer sobre este assunto:

A escolha da linguagem de programação é importante porque influencia o ponto de vista da pessoa. Nossos padrões assumem os resources de linguagem de nível Smalltalk / C ++, e essa escolha determina o que pode e não pode ser implementado facilmente. Se assumíssemos linguagens procedurais, poderíamos ter incluído padrões de design chamados “Herança”, “Encapsulamento” e “Polimorfismo”. Da mesma forma, alguns dos nossos padrões são suportados diretamente pelas linguagens orientadas a objects menos comuns. O CLOS possui vários methods, por exemplo, que diminuem a necessidade de um padrão como o Visitante. Na verdade, existem diferenças suficientes entre Smalltalk e C ++ para significar que alguns padrões podem ser expressos mais facilmente em um idioma do que no outro. (Veja Iterator por exemplo).

(A descrição acima é uma citação do livro Introdução ao Padrão de Design, página 4, parágrafo 3)

As principais características da functional programming incluem funções como valores de primeira class, currying, valores imutáveis, etc. Não parece óbvio para mim que os padrões de projeto OO estejam se aproximando de qualquer um desses resources.

Qual é o padrão de comando, se não uma aproximação de funções de primeira class? 🙂 Em uma linguagem FP, você simplesmente passaria uma function como o argumento para outra function. Em uma linguagem OOP, você tem que encerrar a function em uma class, que você pode instanciar e então passar esse object para a outra function. O efeito é o mesmo, mas em OOP é chamado de padrão de design, e requer muito mais código. E qual é o padrão de fábrica abstrata, se não currying? Passe os parâmetros para uma function um pouco de cada vez, para configurar o tipo de valor que ele libera quando você finalmente o chama.

Então, sim, vários padrões de projeto do GoF são redundantes em linguagens FP, porque existem alternativas mais poderosas e mais fáceis de usar.

Mas é claro que ainda existem padrões de design que não são resolvidos por linguagens FP. Qual é o equivalente do FP de um singleton? (Desconsiderando por um momento que singletons são geralmente um padrão terrível de usar)

E também funciona nos dois sentidos. Como eu disse, o FP também tem seus padrões de design, as pessoas não costumam pensar neles como tal.

Mas você pode ter se deparado com mônadas. Quais são eles, se não um padrão de design para “lidar com o estado global”? Esse é um problema tão simples em linguagens OOP que nenhum padrão de design equivalente existe lá.

Não precisamos de um padrão de design para “incrementar uma variável estática” ou “ler desse soquete”, porque é exatamente o que você faz .

Em linguagens funcionais (puras), os efeitos colaterais e o estado mutável são impossíveis, a menos que você trabalhe com o “padrão de design” da mônada ou com qualquer outro método para permitir a mesma coisa.

Além disso, em linguagens funcionais que suportam OOP (como F # e OCaml), parece-me óbvio que os programadores que usam essas linguagens usariam os mesmos padrões de projeto disponíveis para todas as outras linguagens OOP. Na verdade, agora eu uso F # e OCaml todos os dias, e não há diferenças marcantes entre os padrões que eu uso nessas linguagens versus os padrões que eu uso quando escrevo em Java.

Talvez porque você ainda esteja pensando imperativamente? Muitas pessoas, depois de lidar com linguagens imperativas durante toda a vida, têm dificuldade em desistir desse hábito quando tentam uma linguagem funcional. (Eu vi algumas tentativas muito engraçadas em F #, onde literalmente cada function era apenas uma string de instruções ‘let’, basicamente como se você tivesse pegado um programa em C, e substituído todos os ponto-e-vírgulas por ‘let’. :))

Mas outra possibilidade pode ser que você simplesmente não tenha percebido que está resolvendo problemas trivialmente, o que exigiria padrões de design em uma linguagem OOP.

Quando você usa currying ou passa uma function como argumento para outra, pare e pense em como você faria isso em uma linguagem OOP.

Existe alguma verdade na alegação de que a functional programming elimina a necessidade de padrões de projeto de OOP?

Sim. 🙂 Quando você trabalha em uma linguagem FP, não precisa mais dos padrões de design específicos da OOP. Mas você ainda precisa de alguns padrões gerais de projeto, como o MVC ou outras coisas não OOP específicas, e você precisa de alguns novos “padrões de design” específicos para cada FP. Todos os idiomas têm suas deficiências e os padrões de design geralmente são como trabalhamos em torno deles.

De qualquer forma, você pode achar interessante tentar usar linguagens FP mais “limpas”, como o ML (meu favorito pessoal, pelo menos para fins de aprendizado), ou o Haskell, onde você não tem a muleta OOP para recorrer quando você se depara com algo novo.


Como esperado, algumas pessoas se opuseram à minha definição de padrões de projeto como “remendar defeitos em uma linguagem”, então aqui está minha justificativa: Como já foi dito, a maioria dos padrões de design é específica de um paradigma de programação ou, às vezes, de uma linguagem específica. Muitas vezes, eles resolvem problemas que só existem nesse paradigma (veja monads for FP, ou abstract factory for OOP). Por que o padrão de fábrica abstrato não existe no FP? Porque o problema que ele tenta resolver não existe lá. Então, se existe um problema em linguagens OOP, o que não existe em linguagens FP, então claramente isso é uma deficiência das linguagens OOP. O problema pode ser resolvido, mas a sua linguagem não o faz, mas requer um monte de código clichê de você para contorná-lo. Idealmente, gostaríamos que nossa linguagem de programação fizesse com que todos os problemas desaparecessem. Qualquer problema que ainda existe é, em princípio, uma falha da linguagem. 😉

Existe alguma verdade na alegação de que a functional programming elimina a necessidade de padrões de projeto de OOP?

Programação funcional não é o mesmo que programação orientada a objects. Padrões de design orientados a objects não se aplicam à functional programming. Em vez disso, você tem padrões de design de functional programming.

Para functional programming, você não lerá os livros de padrões de projeto OO, lerá outros livros sobre padrões de projeto FP.

linguagem agnóstica

Não totalmente. Apenas agnóstico de linguagem em relação a idiomas OO. Os padrões de design não se aplicam às linguagens procedurais. Eles mal fazem sentido em um contexto de design de database relacional. Eles não se aplicam ao projetar uma planilha.

um padrão típico de design OOP e seu equivalente funcional?

O acima não deveria existir. É como pedir por um código procedural reescrito como código OO. Ummm … Se eu traduzir o Fortran (ou C) original para Java, não fiz nada mais do que traduzi-lo. Se eu reescrevê-lo totalmente em um paradigma OO, ele não será mais parecido com o original Fortran ou C – ele será irreconhecível.

Não há mapeamento simples de Design OO para Design Funcional. São maneiras muito diferentes de analisar o problema.

A functional programming (como todos os estilos de programação) possui padrões de design. Bancos de dados relacionais possuem padrões de projeto, OO possui padrões de projeto, programação procedural possui padrões de design. Tudo tem padrões de design, até mesmo a arquitetura dos edifícios.

Os padrões de design – como um conceito – são uma forma atemporal de construção, independentemente da tecnologia ou do domínio do problema. No entanto, padrões de design específicos se aplicam a domínios e tecnologias de problemas específicos.

Todo mundo que pensa sobre o que está fazendo descobrirá padrões de design.

Os comentários de Brian sobre a estreita binding entre linguagem e padrão é o ponto,

A parte que falta nesta discussão é o conceito de idioma. O livro de Coplien, “Advanced C ++” foi uma grande influência aqui. Muito antes de ele descobrir Christopher Alexander e Column Without a Name (e você não pode falar sensatamente sobre padrões sem ler Alexander também), ele falou sobre a importância de dominar o idioma para realmente aprender uma língua. Ele usou a string copy em C como exemplo, while (* from ++ = * to ++); Você pode ver isso como um bandaid para um recurso de linguagem ausente (ou recurso de biblioteca), mas o que realmente importa é que é uma unidade maior de pensamento, ou de expressão, do que qualquer uma de suas partes.

É isso que os padrões e as linguagens estão tentando fazer, para nos permitir expressar nossas intenções de maneira mais sucinta. Quanto mais ricas as unidades de pensamento, mais complexos são os pensamentos que você pode expressar. Ter um vocabulário rico e compartilhado em uma variedade de escalas – desde a arquitetura do sistema até o bit twiddling – nos permite ter conversas mais inteligentes e pensamentos sobre o que deveríamos estar fazendo.

Nós também podemos, como indivíduos, aprender. Qual é o ponto inteiro do exercício. Cada um de nós pode entender e usar coisas que nunca poderíamos pensar em nós mesmos. Idiomas, estruturas, bibliotecas, padrões, expressões idiomáticas e assim por diante, todos têm seu lugar em compartilhar a riqueza intelectual.

O livro GOF se vincula explicitamente à OOP – o título é Design Patterns – Elementos do software orientado a object reutilizável (ênfase minha).

Design Patterns in Dynamic Programming por Peter Norvig tem uma cobertura cuidadosa deste tema geral, embora sobre linguagens dinâmicas em vez de funcionais (há sobreposição).

Aqui está outro link, discutindo este tópico: http://blog.ezyang.com/2010/05/design-patterns-in-haskel/

Em seu post, Edward descreve todos os 23 padrões originais do GoF em termos de Haskell.

Quando você tenta olhar para isso no nível de “design patterns” (em geral) e “FP versus OOP”, as respostas que você encontrará serão obscuras na melhor das hipóteses.

No entanto, vá mais fundo nos dois eixos e considere padrões de design específicos e resources de linguagem específicos, e as coisas ficarão mais claras.

Assim, por exemplo, alguns padrões específicos, como Visitante , Estratégia , Comando e Observador definitivamente mudam ou desaparecem ao usar uma linguagem com tipos de dados algébricos e correspondência de padrões , closures , funções de primeira class , etc. Alguns outros padrões do livro GoF ainda “Fique por aqui”, no entanto.

Em geral, eu diria que, com o tempo, padrões específicos estão sendo eliminados por novos resources de linguagem (ou apenas aumento de popularidade). Este é o curso natural do design da linguagem; À medida que as linguagens se tornam mais de alto nível, as abstrações que anteriormente só podiam ser chamadas em um livro usando exemplos agora se tornam aplicações de um recurso de linguagem ou biblioteca particular.

(Além: aqui está um blog recente que escrevi, que tem outros links para mais discussões sobre FP e padrões de design.)

A apresentação de Norvig alude a uma análise que fizeram de todos os padrões do GoF, e eles dizem que 16 dos 23 padrões tinham implementações mais simples em linguagens funcionais, ou eram simplesmente parte da linguagem. Então presumivelmente pelo menos sete deles eram a) igualmente complicados ou b) não presentes na língua. Infelizmente para nós, eles não são enumerados!

Eu acho que é claro que a maioria dos padrões “criacionais” ou “estruturais” no GoF são apenas truques para fazer com que os sistemas de tipos primitivos em Java ou C ++ façam o que você quiser. Mas o resto é digno de consideração, não importa em que idioma você esteja.

Um pode ser protótipo; Embora seja uma noção fundamental de JavaScript, ele deve ser implementado do zero em outros idiomas.

Um dos meus padrões favoritos é o padrão Objeto Nulo: representa a ausência de algo como um object que faz um tipo apropriado de nada. Isso pode ser mais fácil de modelar em uma linguagem funcional. No entanto, a verdadeira conquista é a mudança de perspectiva.

Eu diria que quando você tem uma linguagem como Lisp com seu suporte para macros, então você pode construir suas próprias abstrações específicas de domínio, abstrações que muitas vezes são muito melhores do que as soluções idiomáticas gerais.

E até mesmo as soluções OO Design Pattern são específicas da linguagem. Padrões de design são soluções para problemas comuns que sua linguagem de programação não resolve para você. Em Java, o padrão Singleton resolve o problema de um-de-algo (simplificado). No Scala, você tem uma construção de nível superior chamada Objeto além da Classe. É preguiçosamente instanciado e só existe um. Você não precisa usar o padrão Singleton para obter um Singleton. Faz parte da linguagem.

Os padrões são formas de resolver problemas semelhantes que são vistos repetidas vezes e depois descritos e documentados. Então não, FP não vai replace padrões; no entanto, o FP pode criar novos padrões e tornar alguns padrões atuais de “melhores práticas” “obsoletos”.

Como outros já disseram, existem padrões específicos de functional programming. Eu acho que a questão de se livrar de padrões de design não é tanto uma questão de mudar para funcional, mas uma questão de resources de linguagem .

Dê uma olhada em como o Scala elimina o “padrão singleton”: você simplesmente declara um object em vez de uma class. Outro recurso, correspondência de padrões, ajuda a evitar o ruído do padrão de visitantes. Veja a comparação aqui: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html

E o Scala, como o F #, é uma fusão de OO-funcional. Eu não sei sobre F #, mas provavelmente tem esse tipo de resources.

Fechamentos estão presentes na linguagem funcional, mas não precisam ser restritos a eles. Eles ajudam com o padrão de delegação.

Mais uma observação. Este pedaço de código implementa um padrão: é um clássico e é tão elementar que geralmente não pensamos nele como um “padrão”, mas com certeza é:

 for(int i = 0; i < myList.size(); i++) { doWhatever(myList.get(i)); } 

Linguagens imperativas como Java e C # adotaram o que é essencialmente uma construção funcional para lidar com isso: "foreach".

Os Padrões de Design GoF estão codificando receitas alternativas para linguagens OO que são descendentes do Simula 67, como Java e C ++.

A maioria dos “males” tratados pelos padrões de projeto são causados ​​por:

  • classs estaticamente tipadas, que especificam objects, mas não são objects;
  • restrição ao despacho único (somente o argumento mais à esquerda é usado para selecionar um método, os argumentos restantes são considerados apenas como tipos estáticos: se eles tiverem tipos dynamics, cabe ao método classificá-los com abordagens ad-hoc);
  • distinção entre chamadas de function regulares e chamadas de function orientadas a objects, o que significa que funções orientadas a objects não podem ser passadas como argumentos funcionais onde funções regulares são esperadas e vice-versa; e
  • distinção entre “tipos de base” e “tipos de class”.

Não existe um único desses padrões de design que não desapareça no Common Lisp Object System, mesmo que a solução seja estruturada essencialmente da mesma maneira que no padrão de design correspondente. (Além disso, esse sistema de objects precede o livro GoF por mais de uma década. O Common Lisp tornou-se um padrão ANSI no mesmo ano em que o livro foi publicado pela primeira vez.)

No que diz respeito à functional programming, se os padrões se aplicam ou não a ela, depende se a linguagem de functional programming tem algum tipo de sistema de objects e se é modelada a partir dos sistemas de objects que se beneficiam dos padrões. Esse tipo de orientação a objects não combina bem com functional programming, porque a mutação de estado está na frente e no centro.

A construção e o access não mutante são compatíveis com a functional programming e, portanto, padrões que têm a ver com access ou construção de abstração podem ser aplicáveis: padrões como Fábrica, Fachada, Proxy, Decorador, Visitante.

Por outro lado, os padrões comportamentais, como o Estado e a Estratégia, provavelmente não se aplicam diretamente na OOP funcional, porque a mutação do estado é a essência. Isso não significa que eles não se apliquem; talvez eles de alguma forma se apliquem em combinação com qualquer truque disponível para simular um estado mutável.

Eu gostaria de include alguns documentos excelentes, mas um tanto densos, de Jeremy Gibbons: “Projete padrões como programas de tipo genérico de ordem superior” e “A essência do padrão de Iterador” (ambos disponíveis aqui: http: // www. comlab.ox.ac.uk/jeremy.gibbons/publications/ ).

Ambos descrevem como os construtos funcionais idiomáticos cobrem o terreno coberto por padrões de projeto específicos em outras configurações (orientadas a object).

Você não pode ter essa discussão sem abrir sistemas de tipos.

As principais características da functional programming incluem funções como valores de primeira class, currying, valores imutáveis, etc. Não parece óbvio para mim que os padrões de projeto OO estejam se aproximando de qualquer um desses resources.

Isso porque esses resources não abordam os mesmos problemas que a POO faz … eles são alternativas à programação imperativa. A resposta da FP à OOP está nos sistemas de tipos de ML e Haskell … especificamente tipos de sum, tipos de dados abstratos, módulos ML, typeclasss Haskell.

Mas é claro que ainda existem padrões de design que não são resolvidos por linguagens FP. Qual é o equivalente do FP de um singleton? (Desconsiderando por um momento que singletons são geralmente um padrão terrível de usar)

A primeira coisa que as typeclasss fazem é eliminar a necessidade de singletons.

Você poderia passar pela lista de 23 e eliminar mais, mas eu não tenho tempo para agora.

Acho que apenas dois Padrões de Design GoF foram projetados para introduzir a lógica de functional programming na linguagem OO natural. Eu penso em Estratégia e Comando. Alguns dos outros padrões de projeto do GoF podem ser modificados por functional programming para simplificar o design e manter o propósito.

Essencialmente, sim !

  • Quando um padrão contorna os resources ausentes (funções de alta ordem, manipulação de stream …) que, ultimamente, facilitam a composição .
  • A necessidade de rewrite a implementação de padrões repetidas vezes pode ser vista como um cheiro de linguagem .

Além disso, esta página (AreDesignPatternsMissingLanguageFeatures) fornece uma tabela de conversão de “padrão / recurso” e algumas discussões interessantes, se você estiver disposto a cavar.

OOP e os padrões do GoF lidam com os estados. A OOP modela a realidade para manter a base de código tão próxima quanto possível dos requisitos da realidade. Os padrões de projeto GoF são padrões que foram identificados para resolver problemas atômicos do mundo real. Eles lidam com o problema do estado de maneira semântica.

Como na functional programming real não existe nenhum estado, não faz sentido aplicar os padrões do GoF. Não há padrões de design funcional da mesma forma que há padrões de design do GoF. Cada padrão de design funcional é artificial em contraste com a realidade, pois as funções são construções de matemática e não de realidade.

As funções não têm o conceito de tempo, pois elas sempre retornam o mesmo valor, qualquer que seja a hora atual, a menos que o tempo faça parte dos parâmetros da function, o que dificulta o processamento de “solicitações futuras”. As linguagens híbridas misturam esses conceitos para tornar as linguagens linguísticas funcionais não reais.

As linguagens funcionais estão surgindo apenas por causa de uma coisa: as atuais restrições naturais da física. Processadores de hoje são limitados em sua velocidade de instruções de processamento devido a leis físicas. Você vê uma estagnação na frequência do clock, mas uma expansão nos núcleos de processamento. É por isso que o paralelismo de instruções se torna cada vez mais importante para aumentar a velocidade das aplicações modernas. Como a functional programming por definição não tem estado e, portanto, não tem efeitos colaterais, é seguro processar as funções com segurança em paralelo.

Padrões de GoF não são obsoletos. Eles são pelo menos necessários para modelar os requisitos do mundo real. Mas se você usa uma linguagem de functional programming, precisa transformá-las em seus equivalentes híbridos. Finalmente, você não tem chance de criar apenas programas funcionais se usar persistência. Para os elementos híbridos do seu programa, permanece a necessidade de usar padrões GoF. Qualquer outro elemento que seja puramente funcional, não há necessidade de usar padrões GoF porque não há estado.

Como o padrão GoF não é necessário para uma functional programming real, isso não significa que os princípios do SOLID não devam ser aplicados. Os princípios do SOLID estão além de qualquer paradigma de linguagem.

A functional programming não substitui os padrões de design. Padrões de design não podem ser substituídos.

Padrões simplesmente existem; eles surgiram com o tempo. O livro GoF formalizou alguns deles. Se novos padrões estão surgindo, os desenvolvedores usam linguagens de programação funcionais que são interessantes, e talvez haja livros escritos sobre eles também.

No novo livro de 2013 chamado “Functional Programming Patterns- in Scala e Clojure”, o autor Michael.B. Linn faz um trabalho decente comparando e fornecendo substituições em muitos casos para os padrões GoF e também discute os padrões funcionais mais recentes como ‘recursion da cauda’, ‘memoização’, ‘sequência lenta’, etc.

Este livro está disponível na Amazon. Eu achei muito informativo e encorajador quando vindo de um fundo OO de um par de décadas.

Acho que cada paradigma serve a um propósito diferente e, como tal, não pode ser comparado dessa maneira.

Eu não ouvi dizer que os padrões de design do GoF são aplicáveis ​​a todos os idiomas. Ouvi dizer que são aplicáveis ​​a todas as línguas OOP . Se você usa a functional programming, o domínio dos problemas que você resolve é diferente dos idiomas OO.

Eu não usaria linguagem funcional para escrever uma interface de usuário, mas uma das linguagens OO, como C # ou Java, tornaria esse trabalho mais fácil. Se eu estivesse escrevendo uma linguagem funcional, não consideraria o uso de Padrões de Design OO.

OOP e FP têm objectives diferentes, a OOP visa encapsular as complexidades / partes móveis de componentes de software e FP visa minimizar a complexidade e dependencies de componentes de software, no entanto esses 2 paradigmas não são necessariamente 100% contraditórios e poderiam ser aplicados juntos para obter o benefício dos dois mundos. Mesmo com uma linguagem que não suporta nativamente a functional programming como C #, você poderia escrever código funcional se você entender os princípios FP, da mesma forma você poderia aplicar princípios OOP usando F # se você entender os princípios, padrões e melhores práticas de POO. Você faria a escolha certa com base na situação e no problema que tentar resolver, independentemente da linguagem de programação usada.

Como a resposta aceita disse, OOP e FP têm todos os seus padrões específicos.

No entanto, existem alguns padrões que são tão comuns que todas as plataformas de programação que eu posso pensar deveriam ter. Aqui está uma lista (incompleta):

  • Adaptador. Eu mal consigo pensar em uma plataforma de programação útil que seja tão abrangente (e auto-realizada) que não precise falar com o mundo. Se isso for feito, é definitivamente necessário um adaptador.

  • Fachada. Qualquer plataforma de programação que possa manipular grandes códigos-fonte deve ser capaz de modularizar. Se você fosse criar um módulo para outras partes do programa, você iria querer esconder as partes “sujas” do código e dar-lhe uma boa interface.

  • Intérprete. Em geral, qualquer programa está apenas fazendo duas coisas: analisar a input e imprimir a saída. As inputs do mouse precisam ser analisadas e os widgets da janela precisam ser impressos. Portanto, ter um interpretador embutido dá ao programa um poder adicional para personalizar as coisas.

Além disso, notei em uma linguagem FP típica, Haskell, há algo semelhante aos padrões GoF, mas com nomes diferentes. Na minha opinião, isso sugere que eles estavam lá porque há alguns problemas comuns para resolver em ambas as linguagens FP e OOP.

  • Monad transformador e decorador. O primeiro usado para adicionar capacidade adicional em uma mônada existente, o último adicionar capacidade adicional para um object existente.