Después de aprender la programación funcional en Haskell y F #, el paradigma de OOP parece retroceder con clases, interfaces, objetos. ¿Qué aspectos de FP puedo llevar al trabajo que mis compañeros de trabajo puedan entender? ¿Vale la pena hablar con mi jefe sobre los estilos de FP para volver a capacitar a mi equipo para que podamos usarlos?
Posibles aspectos de la PF:
- Inmutabilidad
- Aplicación parcial y curry
- Funciones de primera clase (punteros de función / objetos funcionales / patrón de estrategia)
- Evaluación perezosa (y mónadas)
- Funciones puras (sin efectos secundarios)
- Expresiones (frente a declaraciones: cada línea de código produce un valor en lugar de, o además de causar efectos secundarios)
- Recursividad
- La coincidencia de patrones
¿Es un programa gratuito para todos donde podemos hacer lo que sea que el lenguaje de programación admite hasta el límite que ese lenguaje lo admite? ¿O hay una mejor pauta?
Respuestas:
La programación funcional es un paradigma diferente de la programación orientada a objetos (una mentalidad diferente y una forma diferente de pensar acerca de los programas). Has comenzado a darte cuenta de que aquí hay más de una forma (orientada a objetos) para pensar sobre los problemas y sus soluciones. Hay otros (viene a la mente la programación procesal y genérica). La forma en que reaccione a este nuevo conocimiento, si acepta e integra estas nuevas herramientas y enfoques en su conjunto de habilidades, determinará si crece y se convierte en un desarrollador más completo y calificado.
Todos estamos capacitados para manejar y nos sentimos cómodos con un cierto nivel de complejidad. Me gusta llamar a esto el límite de cabello de una persona (desde Watership Down, qué tan alto puedes contar). Es una gran cosa expandir su mente, su capacidad de considerar más opciones y tener más herramientas para abordar y resolver problemas. Pero es un cambio y te saca de tu zona de confort.
Un problema que puede encontrar es que estará menos contento de seguir a la multitud "todo es un objeto". Es posible que tenga que desarrollar paciencia mientras trabaja con personas que tal vez no entiendan (o quieran entender) por qué un enfoque funcional para el desarrollo de software funciona bien para ciertos problemas. Así como un enfoque de programación genérico funciona bien para ciertos problemas.
¡Buena suerte!
fuente
La programación funcional produce una productividad muy práctica y práctica en la escritura de códigos de todos los días: algunas características favorecen la concisión, lo cual es excelente porque cuanto menos código escriba, menos fallas tendrá y se requerirá menos mantenimiento.
Siendo matemático, encuentro cosas funcionales sofisticadas muy atractivas, pero generalmente es útil al diseñar una aplicación: estas estructuras pueden codificar en la estructura del programa muchos invariantes del programa, sin representar estos invariantes por variables.
Mi combinación favorita puede parecer bastante trivial, sin embargo, creo que tiene un impacto muy alto en la productividad. Esta combinación es Aplicación parcial y funciones de currificación y primera clase que volvería a etiquetar nunca volvería a escribir un ciclo for : en su lugar, pase el cuerpo del ciclo a una función de iteración o mapeo. Recientemente fui contratado para un trabajo en C ++ y me di cuenta de manera divertida, ¡perdí totalmente el hábito de escribir for-loops!
La combinación de Recursion y Pattern Matching aniquila la necesidad de ese patrón de diseño Visitor . Simplemente compare el código que necesita para programar un evaluador de expresiones booleanas: en cualquier lenguaje de programación funcional, esto debería ser alrededor de 15 líneas de código, en OOP lo correcto es usar ese patrón de diseño Visitor , que convierte ese ejemplo de juguete en Un extenso ensayo. Las ventajas son obvias y no conozco ningún inconveniente.
fuente
list.forEach(System.out::println);
Desde el punto de vista de FP,println
es una función que toma dos argumentos, un objetivoPrintStream
y un valor,Object
pero el métodoCollection
'sforEach
espera una función con un solo argumento que se puede aplicar a cada elemento. Entonces, el primer argumento está vinculado a la instancia que se encuentra alSystem.out
ceder el paso a una nueva función con un argumento. Es más simple queBiConsumer<…> c=PrintStream::println; PrintStream a1=System.out; list.forEach(a2 -> c.accept(a1, a2));
Es posible que tenga que restringir qué partes de su conocimiento usa en el trabajo, la forma en que Superman tiene que fingir que es Clark Kent para disfrutar de las ventajas de una vida normal. Pero saber más nunca te hará daño. Dicho esto, algunos aspectos de la programación funcional son apropiados para una tienda orientada a objetos, y vale la pena hablar con su jefe sobre otros aspectos para que pueda aumentar el nivel de conocimiento promedio de su tienda y, como resultado, escribir un mejor código.
FP y OOP no son mutuamente excluyentes. Mira a Scala. Algunos piensan que es lo peor porque es FP impuro, pero algunos piensan que es lo mejor por esa misma razón.
Uno por uno, aquí hay algunos aspectos que funcionan muy bien con OOP:
Funciones puras (sin efectos secundarios): todos los lenguajes de programación que conozco admiten esto. Hacen que su código sea mucho más fácil de razonar y deben usarse siempre que sea práctico. No tienes que llamarlo FP. Solo llámalo buenas prácticas de codificación.
Inmutabilidad: String es posiblemente el objeto Java más utilizado y es inmutable. Cubro objetos inmutables Java y inmutables colecciones de Java en mi blog. Algo de eso puede ser aplicable a usted.
Funciones de primera clase (punteros de función / Objetos funcionales / Patrón de estrategia): Java ha tenido una versión mutante y cobarde de esto desde la versión 1.1 con la mayoría de las clases de API (y hay cientos) que implementan la interfaz de escucha. Runnable es probablemente el objeto funcional más utilizado. Las funciones de primera clase requieren más trabajo para codificar en un lenguaje que no las admite de forma nativa, pero a veces vale la pena el esfuerzo adicional cuando simplifican otros aspectos de su código.
La recursión es útil para procesar árboles. En una tienda OOP, ese es probablemente el uso principal apropiado de la recursividad. El uso de la recursión por diversión en OOP probablemente debería estar mal visto si, por ninguna otra razón, la mayoría de los lenguajes OOP no tienen el espacio de pila por defecto para hacer de esto una buena idea.
Expresiones (frente a declaraciones: cada línea de código produce un valor en lugar de, o además de causar efectos secundarios): el único operador evaluativo en C, C ++ y Java es el operador ternario . Discuto el uso apropiado en mi blog. Puede encontrar que escribe algunas funciones simples que son altamente reutilizables y evaluativas.
Evaluación diferida (y mónadas): principalmente restringida a la inicialización diferida en OOP. Sin funciones de lenguaje que lo admitan, puede encontrar algunas API que son útiles, pero escribir las suyas es difícil. En su lugar, maximice el uso de las transmisiones: consulte las interfaces de Writer y Reader para ver ejemplos.
Aplicación parcial y currículum - No es práctico sin funciones de primera clase.
Coincidencia de patrones: generalmente desaconsejado en OOP.
En resumen, no creo que el trabajo deba ser libre para todos, en el que puedas hacer lo que sea que el lenguaje de programación admita hasta el límite que lo admita el lenguaje. Creo que la legibilidad de tus compañeros de trabajo debería ser tu prueba de fuego para el código hecho para contratar. Donde eso te irrita más, buscaría comenzar un poco de educación en el trabajo para ampliar los horizontes de tus compañeros de trabajo.
fuente
public interface BiConsumer<T, U> { public void accept(T t, U u); }
hay otras interfaces funcionales útiles en java.util.function.Most OOP languages don't have the stack space for it
De Verdad? Todo lo que necesitaría es 30 niveles de recursión para administrar miles de millones de nodos en un árbol binario equilibrado. Estoy bastante seguro de que mi espacio de pila es adecuado para muchos más niveles que este.Además de la programación funcional y la programación orientada a objetos, también hay programación declarativa (SQL, XQuery). Aprender cada estilo te ayuda a obtener nuevos conocimientos, y aprenderás a elegir la herramienta adecuada para el trabajo.
Pero sí, puede ser muy frustrante escribir código en un idioma, y saber que si estuviera usando otra cosa, podría ser mucho más productivo para un dominio de problema en particular. Sin embargo, incluso si está utilizando un lenguaje como Java, es posible aplicar conceptos de FP a su código Java, aunque de manera indirecta. El marco de la guayaba, por ejemplo, hace algo de esto.
fuente
Como programador, creo que nunca debes dejar de aprender. Dicho esto, es muy interesante que aprender FP esté contaminando tus habilidades de OOP. Tiendo a pensar en aprender OOP como aprender a andar en bicicleta; nunca olvidas cómo hacerlo.
A medida que aprendí los entresijos de FP, me encontré pensando más matemáticamente y obtuve una mejor perspectiva de los medios en los que escribo el software. Esa es mi experiencia personal.
A medida que gane más experiencia, los conceptos básicos de programación serán mucho más difíciles de perder. Por lo tanto, le sugiero que lo tome con calma en el FP hasta que los conceptos de POO se solidifiquen totalmente en su mente. FP es un cambio de paradigma definitivo. ¡Buena suerte!
fuente
Ya hay muchas buenas respuestas, por lo que la mía abordará un subconjunto de su pregunta; a saber, considero la premisa de su pregunta, ya que las características funcionales y OOP no son mutuamente excluyentes.
Si usa C ++ 11, hay muchas de estas características de programación funcional integradas en el lenguaje / biblioteca estándar que sinergizan (bastante) bien con OOP. Por supuesto, no estoy seguro de qué tan bien TMP será recibido por su jefe o compañeros de trabajo, pero el punto es que puede obtener muchas de estas características de una forma u otra en lenguajes no funcionales / OOP, como C ++.
El uso de plantillas con recursión en tiempo de compilación depende de sus primeros 3 puntos,
En que los valores de plantilla son inmutables (constantes de tiempo de compilación), cualquier iteración se realiza mediante recursión, y la ramificación se realiza utilizando (más o menos) coincidencia de patrones, en forma de resolución de sobrecarga.
En cuanto a los otros puntos, el uso de
std::bind
ystd::function
le brinda una aplicación de función parcial, y los punteros de función están integrados en el lenguaje. Los objetos invocables son objetos funcionales (así como una aplicación de función parcial). Tenga en cuenta que por objetos invocables, me refiero a los que definen susoperator ()
.La evaluación perezosa y las funciones puras serían un poco más difíciles; para funciones puras, puede usar funciones lambda que solo capturan por valor, pero esto no es ideal.
Por último, aquí hay un ejemplo del uso de la recursión en tiempo de compilación con la aplicación de función parcial. Es un ejemplo un tanto artificial, pero demuestra la mayoría de los puntos anteriores. Enlazará recursivamente los valores en una tupla dada a una función dada y generará un objeto de función (invocable)
fuente