¿Las personas que no pertenecen a la PF pueden entender pequeñas cantidades de programación funcional? [cerrado]

43

Caso : estoy trabajando en una empresa, escribiendo una aplicación en Python que está manejando una gran cantidad de datos en arreglos. Soy el único desarrollador de este programa en este momento, pero probablemente será utilizado / modificado / extendido en el futuro (1-3 años) por otro programador, en este momento desconocido para mí. Probablemente no estaré allí directamente para ayudarlo, pero quizás le ofrezca asistencia por correo electrónico si tengo tiempo para hacerlo.

Entonces, como desarrollador que ha aprendido programación funcional (Haskell), tiendo a resolver, por ejemplo, filtrar de esta manera:

filtered = filter(lambda item: included(item.time, dur), measures)

El resto del código es OO, son solo algunos casos pequeños en los que quiero resolverlo así, porque es mucho más simple y hermoso según mi opinión.

Pregunta : ¿Está bien hoy escribir código como este?

  • ¿Cómo reacciona un desarrollador que no ha escrito / aprendido FP a un código como este?
  • ¿Es legible?
  • ¿Modificable?
  • ¿Debo escribir documentación como explicando a un niño qué hace la línea?

     # Filter out the items from measures for which included(item.time, dur) != True
    

Le he preguntado a mi jefe y él simplemente dice "FP es magia negra, pero si funciona y es la solución más eficiente, está bien usarla".

¿Cuál es tu opinión sobre esto? Como programador no FP, ¿cómo reaccionas al código? ¿Es el código "googable" para que pueda entender lo que hace? Me encantaría recibir comentarios sobre esto.

    
pregunta kd35a 30.07.2012 - 11:54

7 respuestas

50
  

¿Es legible?

Para mí: sí, pero he llegado a entender que la comunidad de Python a menudo parece considerar las comprensiones de listas como una solución más limpia que usar map() / filter() .

De hecho, GvR incluso considerado descartar esas funciones por completo.

Considera esto:

filtered = [item for item in measures if included(item.time, dur)]

Además, esto tiene el beneficio de que una lista de comprensión siempre devolverá una lista. map() y filter() por otra parte devolverán un iterador en Python 3.

Nota: si quieres tener un iterador, es tan simple como reemplazar [] con () :

filtered = (item for item in measures if included(item.time, dur))

Para ser honesto, veo poca o ninguna razón para usar map() o filter() en Python.

  

¿Es modificable?

Sí, ciertamente, sin embargo, hay una cosa para hacerlo más fácil: hacer que sea una función, no una lambda.

def is_included(item):
    return included(item.time, dur)
filtered = filter(is_included, measures)
filtered = [item for item in measures if is_included(item)]

Si su condición se vuelve más compleja, esto se escalará mucho más fácilmente, también le permite reutilizar su cheque. (Tenga en cuenta que puede crear funciones dentro de otras funciones, esto lo puede mantener más cerca del lugar donde se usa).

  

¿Cómo reacciona un desarrollador que no ha escrito / aprendido FP en un código como este?

Busca en Google la documentación de Python y sabe cómo funciona cinco minutos después. De lo contrario, no debería estar programando en Python.

map() y filter() son extremadamente simples. No es como si les estuvieras pidiendo que comprendan las mónadas. Es por eso que no creo que necesites escribir tales comentarios. Use buenos nombres de variables y funciones, entonces el código es casi auto explicativo. No puedes anticipar qué características de lenguaje no conoce un desarrollador. Por lo que sabe, el siguiente desarrollador puede no saber qué es un diccionario.

Lo que no entendemos generalmente no es legible para nosotros. Por lo tanto, podría argumentar que no es menos legible que una comprensión de lista si nunca ha visto a ninguno de ellos antes. Pero como Joshua mencionó en su comentario, yo también creo que es importante ser coherente con lo que usan otros desarrolladores, al menos si la alternativa no ofrece una ventaja sustancial.

    
respondido por el phant0m 30.07.2012 - 12:46
23

Dado que la comunidad de desarrolladores está recuperando el interés en la programación funcional, no es raro ver alguna programación funcional en lenguajes que originalmente estaban completamente orientados a objetos. Un buen ejemplo es C #, donde los tipos anónimos y las expresiones lambda permiten ser mucho más cortos y expresivos a través de la programación funcional.

Dicho esto, la programación funcional es rara para los principiantes. Por ejemplo, cuando durante un curso de capacitación, les expliqué a los principiantes cómo pueden mejorar su código a través de la programación funcional en C #, algunos de ellos no estaban convencidos, y algunos dijeron que el código original era más fácil de entender para ellos. El ejemplo que les di fue el siguiente:

Código antes de refactorización:

var categorizedProducts = new Dictionary<string, List<Product>>();

// Get only enabled products, filtering the disabled ones, and group them by categories.
foreach (var product in this.Data.Products)
{
    if (product.IsEnabled)
    {
        if (!categorizedProducts.ContainsKey(product.Category))
        {
            // The category is missing. Create one.
            categorizedProducts.Add(product.Category, new List<Product>());
        }

        categorizedProducts[product.Category].Add(product);
    }
}

// Walk through the categories.
foreach (var productsInCategory in categorizedProducts)
{
    var minimumPrice = double.MaxValue;
    var maximumPrice = double.MinValue;

    // Walk through the products in a category to search for the maximum and minimum prices.
    foreach (var product in productsInCategory.Value)
    {
        if (product.Price < minimumPrice)
        {
            minimumPrice = product.Price;
        }

        if (product.Price > maximumPrice)
        {
            maximumPrice = product.Price;
        }
    }

    yield return new PricesPerCategory(category: productsInCategory.Key, minimum: minimumPrice, maximum: maximumPrice);
}

El mismo código después de refactorizar utilizando FP:

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

Esto me hace pensar que:

  • no debe preocuparse si sabe que el próximo desarrollador que mantendrá su código tendrá suficiente experiencia general y cierto conocimiento de la programación funcional, pero:

  • de lo contrario, evite la programación funcional o haga un comentario detallado que explique al mismo tiempo la sintaxis, las ventajas y las posibles advertencias de su enfoque frente a una programación no funcional.

respondido por el Arseni Mourzenko 30.07.2012 - 12:24
20

Soy un programador que no es de FP y recientemente tuve que modificar el código de mi colega en JavaScript. Hubo una solicitud de Http con una devolución de llamada que se parecía mucho a la declaración incluida por usted. Debo decir que me llevó algo de tiempo (como media hora) resolverlo todo (el código no era muy grande).

No hubo comentarios, y creo que no hubo necesidad para ninguno. Ni siquiera le pedí a mi colega que me ayudara a entender su código.

Teniendo en cuenta que estoy trabajando durante aproximadamente 1,5 años, creo que la mayoría de los programadores podrán entender y modificar dicho código, como hice yo.

Además, como Joachim Sauer dijo en su comentario, a menudo hay piezas de FP en muchos idiomas, como C # (indexOf, por ejemplo). Muchos programadores que no pertenecen a FP se enfrentan a esto con bastante frecuencia, y el fragmento de código que incluyó no es algo terrible o incomprensible.

    
respondido por el superM 30.07.2012 - 12:26
3

¡Definitivamente diría que sí!

Hay muchos aspectos de la programación funcional, y el uso de funciones de orden superior, como en su ejemplo, es solo uno de ellos.

Por ejemplo, considero que escribir funciones puras es extremadamente importante para cualquier software escrito en cualquier idioma (donde por " puro "no quiero decir efectos secundarios), porque:

  • son más fáciles de probar por unidad
  • son mucho más compuestas que las funciones de efectos secundarios
  • son más fáciles de depurar

También a menudo evito la mutación de valores y variables, otro concepto tomado de FP.

Ambas técnicas funcionan bien en Python y en otros lenguajes que no suelen clasificarse como funcionales. A menudo, incluso son compatibles con el lenguaje en sí (es decir, final variables en Java). Por lo tanto, los futuros programadores de mantenimiento no enfrentarán una barrera enorme para comprender el código.

    
respondido por el user39685 30.07.2012 - 18:48
2

Tuvimos esta misma discusión en una empresa para la que trabajé el año pasado.

La discusión se refería al "código mágico" y si era para alentarlo o no. Al examinarlo un poco más, parecía que la gente tenía puntos de vista muy diferentes sobre lo que en realidad era el "código mágico". Los que plantearon la discusión parecían significar principalmente que las expresiones (en PHP) que usaban el estilo funcional eran "códigos mágicos", mientras que los desarrolladores que se originaron en otros idiomas que usaban más estilos de PF en su código parecen pensar que el código mágico era bastante cuando hiciste la inclusión dinámica de archivos a través de nombres de archivos y así sucesivamente.

Nunca llegamos a una buena conclusión sobre esto, más de lo que la mayoría de las personas piensan que el código que parece desconocido es "mágico" o difícil de leer. Entonces, ¿es una buena idea evitar el código que parece desconocido para otros usuarios? Creo que depende de donde se usa. Me abstendré de usar expresiones de estilo fp (inclusión dinámica de archivos, etc.) en un método principal (o partes centrales importantes de las aplicaciones) donde los datos deben ser un túnel de forma clara, fácil de leer e intuitiva. Por otro lado, no creo que uno deba temer empujar el sobre, los otros desarrolladores probablemente aprenderán FP rápidamente si se enfrentan con el código de FP y quizás tengan algún buen recurso interno para consultar sobre los problemas.

TL; DR: evite en la parte central de alto nivel de las aplicaciones (que deben leerse para obtener una descripción general de la funcionalidad de la aplicación). De lo contrario, úsalo.

    
respondido por el Christopher Käck 30.07.2012 - 12:47
2

La comunidad de C ++ recientemente también recibió lambda, y creo que tienen aproximadamente la misma pregunta. Sin embargo, la respuesta puede no ser la misma. El equivalente de C ++ sería:

std::copy_if(measures.begin(), measures.end(), inserter(filter),
  [dur](Item i) { return included(i, dur) } );

Ahora std::copy no es nuevo, y las variantes _if tampoco son nuevas, pero la lambda sí lo es. Sin embargo, se define claramente en el contexto: dur se captura y, por lo tanto, es constante, Item i varía en el bucle, y la única instrucción return hace todo el trabajo.

Esto parece aceptable para muchos desarrolladores de C ++. Sin embargo, no he probado opiniones sobre lambda de orden superior, y esperaría mucha menos aceptación.

    
respondido por el MSalters 30.07.2012 - 15:19
0

Publica un fragmento de código a un compañero de desarrollo que no sea tan fluido en python, y pregúntale si puede dedicar 5 minutos a verificar el código para ver si lo entiende.

Si es así, es probable que estés listo. Si no es así, deberías mirar a hacerlo más claro.

¿Podría tu colega ser tonto y no entender algo que debería ser obvio? Sí, pero siempre debes programar de acuerdo con KISS.

¿Tal vez su código es más eficiente / atractivo / elegante que un enfoque más directo e idóneo? Entonces debes preguntarte: ¿Necesito hacer esto? Nuevamente, si la respuesta es no, ¡no lo hagas!

Si después de todo esto, todavía crees que necesitas hacerlo y quieres hacerlo a través de FP, entonces hazlo por todos los medios. Confíe en sus instintos, son más adecuados para sus necesidades que la mayoría de las personas en cualquier foro :)

    
respondido por el Arnab Datta 21.08.2012 - 12:01

Lea otras preguntas en las etiquetas