[design-patterns] ¿La programación funcional reemplaza los patrones de diseño de GoF?


Answers

¿Hay algo de cierto en la afirmación de que la programación funcional elimina la necesidad de patrones de diseño OOP?

La programación funcional no es lo mismo que la programación orientada a objetos. Los patrones de diseño orientados a objetos no se aplican a la programación funcional. En cambio, tiene patrones de diseño de programación funcional.

Para la programación funcional, no leerá los libros de patrones de diseño de OO, leerá otros libros sobre patrones de diseño de PF.

lenguaje agnóstico

No totalmente. Solo es independiente del idioma con respecto a los lenguajes OO. Los patrones de diseño no se aplican a los lenguajes de procedimiento en absoluto. Apenas tienen sentido en un contexto de diseño de base de datos relacional. No se aplican al diseñar una hoja de cálculo.

un patrón de diseño de OOP típico y su equivalente funcional?

Lo anterior no debería existir. Es como pedir un trozo de código de procedimiento reescrito como código OO. Ummm ... Si traduzco el Fortran original (o C) a Java, no he hecho nada más que traducirlo. Si lo reescribo totalmente en un paradigma OO, ya no se verá como el Fortran o C original: será irreconocible.

No hay un mapeo simple desde OO Design hasta Functional Design. Son formas muy diferentes de ver el problema.

La programación funcional (como todos los estilos de programación) tiene patrones de diseño. Las bases de datos relacionales tienen patrones de diseño, OO tiene patrones de diseño, la programación de procedimientos tiene patrones de diseño. Todo tiene patrones de diseño, incluso la arquitectura de los edificios.

Los patrones de diseño, como concepto, son una forma intemporal de construcción, independientemente de la tecnología o el dominio del problema. Sin embargo, los patrones de diseño específicos se aplican a dominios y tecnologías de problemas específicos.

Todos los que piensen en lo que están haciendo descubrirán patrones de diseño.

Question

Desde que comencé a aprender F # y OCaml el año pasado, he leído una gran cantidad de artículos que insisten en que los patrones de diseño (especialmente en Java) son soluciones para las características que faltan en los idiomas imperativos. Un artículo que encontré hace un reclamo bastante fuerte :

La mayoría de las personas que he conocido han leído el libro Patrones de diseño de la Banda de los Cuatro. Cualquier programador que se respete a sí mismo le dirá que el libro es independiente del idioma y que los patrones se aplican a la ingeniería del software en general, independientemente del idioma que use. Este es un noble reclamo. Desafortunadamente, está muy lejos de la verdad.

Los lenguajes funcionales son extremadamente expresivos. En un lenguaje funcional, uno no necesita patrones de diseño porque el lenguaje es probablemente de tan alto nivel, terminas programando en conceptos que eliminan patrones de diseño en conjunto.

Las principales características de la programación funcional incluyen funciones como valores de primera clase, currying, valores inmutables, etc. No me parece obvio que los patrones de diseño de OO se aproximen a cualquiera de esas características.

Además, en los lenguajes funcionales que soportan OOP (como F # y OCaml), me parece obvio que los programadores que usan estos lenguajes usarían los mismos patrones de diseño disponibles para cada otro lenguaje OOP. De hecho, en este momento utilizo F # y OCaml todos los días, y no hay diferencias notables entre los patrones que uso en estos lenguajes frente a los patrones que uso cuando escribo en Java.

¿Hay algo de cierto en la afirmación de que la programación funcional elimina la necesidad de patrones de diseño OOP? De ser así, ¿podría publicar o vincular un ejemplo de un patrón de diseño OOP típico y su equivalente funcional?




Como han dicho otros, hay patrones específicos de programación funcional. Creo que la cuestión de deshacerse de los patrones de diseño no es tanto una cuestión de cambiar a funcional, sino una cuestión de características del lenguaje .

Eche un vistazo a cómo Scala elimina el "patrón de singleton": simplemente declara un objeto en lugar de una clase. Otra característica, la coincidencia de patrones, ayuda a evitar el clunkiness del patrón de visitante. Ver la comparación aquí: http://andymaleh.blogspot.com/2008/04/scalas-pattern-matching-visitor-pattern.html

Y Scala, como F #, es una fusión de OO-funcional. No sé sobre F # pero probablemente tiene este tipo de características.

Los cierres están presentes en el lenguaje funcional, pero no necesitan estar restringidos a ellos. Ellos ayudan con el patrón del delegador.

Una observación más. Esta pieza de código implementa un patrón: es un clásico y es tan elemental que normalmente no lo consideramos un "patrón", pero seguro:

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

Los lenguajes imperativos como Java y C # han adoptado lo que es esencialmente una construcción funcional para lidiar con esto: "foreach".




Esencialmente, !

  • Cuando un patrón elude las características que faltan (funciones de orden superior, manejo de flujo ...) esa ultimalty facilidad facilita la composition .
  • La necesidad de volver a escribir la implementación de los patrones una y otra vez puede verse como un olor a lenguaje .

Además, esta página (AreDesignPatternsMissingLanguageFeatures) proporciona una tabla de traducción "patrón / función" y algunas buenas discusiones, si está dispuesto a excavar.




Me gustaría incluir un par de documentos excelentes pero algo densos de Jeremy Gibbons: "Patrones de diseño como programas genéricos de tipo de datos de orden superior" y "La esencia del patrón iterador" (ambos disponibles aquí: http://www.comlab.ox.ac.uk/jeremy.gibbons/publications/ ).

Ambos describen cómo las construcciones idiomáticas funcionales cubren el terreno que está cubierto por patrones de diseño específicos en otros entornos (orientados a objetos).




OOP y FP tienen diferentes objetivos, OOP pretende encapsular las complejidades / partes móviles de los componentes de software y los objetivos de FP para minimizar la complejidad y las dependencias de los componentes de software. Sin embargo, estos 2 paradigmas no son necesariamente 100% contradictorios y podrían aplicarse conjuntamente para obtener el beneficio de ambos mundos. Incluso con un lenguaje que no admite nativamente programación funcional como C #, podría escribir código funcional si comprende los principios de FP, de la misma manera podría aplicar los principios de OOP usando F # si comprende los principios de OOP, patrones y mejores prácticas. Haría la elección correcta en función de la situación y el problema que trate de resolver, independientemente del lenguaje de programación que utilice.




En el nuevo libro de 2013 llamado "Patrones de programación funcional- en Scala y Clojure", el autor Michael.B. Linn hace un trabajo decente al comparar y proporcionar reemplazos en muchos casos para los patrones GoF y también discute los patrones funcionales más nuevos como 'recursividad final', 'memoización', 'secuencia diferida', etc.

Este libro está disponible en Amazon. Me pareció muy informativo y alentador cuando provenía de un fondo OO de un par de décadas.







E incluso las soluciones de patrón de diseño OO son específicas del idioma. Los patrones de diseño son soluciones a problemas comunes que su lenguaje de programación no resuelve para usted. En Java, el patrón Singleton resuelve el problema de uno de algo (simplificado). En Scala, tiene una construcción de nivel superior llamada Object además de Class. Es instanciado perezosamente y solo hay uno. No tiene que usar el patrón de Singleton para obtener un Singleton. Es parte del lenguaje.




La presentación de Norvig alude a un análisis que hicieron de todos los patrones de GoF, y dicen que 16 de los 23 patrones tenían implementaciones más simples en lenguajes funcionales, o simplemente eran parte del lenguaje. Entonces, presumiblemente, al menos siete de ellos eran a) igualmente complicados ob) no estaban presentes en el idioma. Desafortunadamente para nosotros, ¡no están enumerados!

Creo que está claro que la mayoría de los patrones "creacionales" o "estructurales" en GoF son simplemente trucos para hacer que los sistemas de tipos primitivos en Java o C ++ hagan lo que quieres. Pero el resto es digno de consideración sin importar en qué idioma programe.

Uno podría ser Prototipo; si bien es una noción fundamental de JavaScript, debe implementarse desde cero en otros idiomas.

Uno de mis patrones favoritos es el patrón Objeto nulo: representa la ausencia de algo como un objeto que hace un tipo apropiado de nada. Esto puede ser más fácil de modelar en un lenguaje funcional. Sin embargo, el verdadero logro es el cambio de perspectiva.




El libro GOF se vincula explícitamente con OOP, el título es Patrones de diseño: elementos del software reutilizable orientado a objetos (énfasis mío).




Creo que solo dos GoF Design Patterns están diseñados para introducir la lógica de programación funcional en el lenguaje OO natural. Pienso en Estrategia y Comando. Algunos de los otros patrones de diseño GoF se pueden modificar mediante programación funcional para simplificar el diseño y mantener el propósito.




Links