2009-12-25 24 views
20

Mientras más profundizo en javascript, más pienso en las consecuencias de ciertas decisiones de diseño y prácticas recomendadas. En este caso, estoy observando funciones anónimas, una característica que no solo está provista por JavaScript, sino que la veo muy utilizada.funciones anónimas consideradas nocivas?

Creo que todos estamos de acuerdo en los siguientes hechos:

  • la mente humana no se ocupa de más de 7 ± dos entidades (Miller's law)
  • hendidura profunda se considera bad programming practice, y señala general en problemas de diseño si sangra más de tres o cuatro niveles. Esto se extiende a las entidades anidadas, y está bien presentado en la entrada de python Zen "Flat es mejor que anidado".
  • La idea de tener un nombre de función es tanto de referencia como para una fácil documentación de la tarea que realiza. Sabemos, o podemos esperar, lo que hace una función llamada removeListEntry(). El código claro y autodocumentado es importante para la depuración y la legibilidad.

Mientras que las funciones anónimas parecen ser una característica muy agradable, su uso conduce a un diseño de código profundamente anidado. El código es rápido de escribir, pero difícil de leer. En lugar de tener que inventar un contexto con nombre para una funcionalidad y aplanar su jerarquía de objetos invocables, fomenta un "nivel profundo", empujando su pila de cerebros y desbordando rápidamente la regla 7 +/- 2. Un concepto similar se expresa en "About Face" de Alan Cooper, citando de forma vaga "las personas no entienden las jerarquías". Como programadores, entendemos las jerarquías, pero nuestra biología aún limita nuestra comprensión de la anidación profunda.

Me gustaría escucharlo sobre este punto. ¿Deben considerarse las funciones anónimas perjudiciales, un azúcar sintáctico brillante aparente que más tarde descubriremos que es sal o incluso veneno para ratas?

CW ya que no hay una respuesta correcta.

+0

¿Qué quiere decir con considerar funciones anónimas como "un azúcar sintáctico"? – day

+0

¿Prefiere ver un nivel más de sangría para una función única/lambda o tiene que encontrar dónde se encuentra una función no anónima en el nivel superior? Si la función está en un lugar diferente, entonces para mí eso es como una entidad más con la que lidiar, donde como si estuviera en línea, es solo parte de la misma entidad. Si tu opinión es que es más difícil leer código con funciones anónimas, mi opinión es que eres raro – Andy

Respuesta

16

Como yo lo veo, el problema al que se enfrenta no son las funciones anónimas, sino la falta de voluntad de factorizar la funcionalidad en unidades útiles y reutilizables. Lo cual es interesante, porque es más fácil para reutilizar la funcionalidad en idiomas con funciones de primera clase (y, necesariamente, funciones anónimas) que en idiomas sin.

Si ve muchas funciones anónimas profundamente anidadas en su código, sugeriría que puede haber una gran cantidad de funcionalidades comunes que pueden incluirse en funciones nombradas de orden superior (es decir, funciones que toman o devuelven (" construir ") otras funciones). Incluso las transformaciones "simples" de las funciones existentes deberían recibir nombres si se usan con frecuencia. Este es solo el principio SECO.

+4

Esto es exactamente. No hay nada intrínsecamente incorrecto con el uso de funciones anónimas en situaciones en las que tienen sentido, pero cuando hacen algo no trivial, es mejor poner la funcionalidad real en una función nombrada (o varias, incluso). – mcv

+0

@mvc - ¿En qué situaciones podrían tener sentido? –

+0

@ToniLeigh: tiene sentido usar una función anónima si (1) es lo suficientemente corta para que se entienda fácilmente y (2) solo se usa en ese lugar. P.ej. Utilizo los gustos de '@backup_filenames = map {" $ _. Bak "} @ filenames' en Perl todo el tiempo - el' {"$ _. Bak"} 'es una función anónima que toma un argumento,' $ _', le agrega '" .bak "' y devuelve la respuesta. 'map' aplica esto a todos los elementos en la matriz' @ filenames'. –

2

Creo que los cierres tienen enormes beneficios que no deben pasarse por alto. Por ejemplo, Apple aprovecha los "bloqueos" (cierres para C) con GCD para proporcionar un multihilo realmente fácil: no necesita configurar estructuras de contexto, y solo puede hacer referencia a las variables por su nombre, ya que están dentro del alcance.

Creo que un problema mayor con Javascript es que no tiene alcance de bloque (en este caso, los bloques se refieren al código entre llaves, como una instrucción if). Esto puede conducir a enormes complicaciones, obligando a los programadores a utilizar cierres innecesarios para evitar esta limitación de diseño de Javascript.

8

Las funciones anónimas son más útiles funcionalmente de lo que son perjudiciales de forma legible. Creo que si formatea su código lo suficientemente bien, no debería tener un problema. No tengo ningún problema con eso, y estoy seguro de que no puedo manejar 7 elementos, y mucho menos 7 + 2 :)

+0

¿Qué significa eso? "útil funcionalmente" Por favor, elabore. –

+0

Supongo que en esta respuesta de hace 5 años quise decir la compensación entre la utilidad de las funciones anónimas y su legibilidad en el código favorecido al usarlas.En otras palabras, no debe elegir no usar funciones anónimas porque hacen que su código sea más difícil de leer porque hacen que sea más fácil escribir. – Jason

+0

Entiendo la compensación que estaba explicando. Pero no puedo entenderlo completamente hasta que desarrolles lo que quieres decir con "funcionalmente útil". ¿A menos que quiera decir que las funciones anónimas son más fáciles de escribir? ¿Si es así, cómo? –

4

En realidad, las jerarquías ayudan a superar 7 +/- 2 reglas de la misma manera que OOP lo hace. Cuando estás escribiendo o leyendo una clase, lees su contenido y nada de código externo, por lo que estás tratando con porciones relativamente pequeñas de entidades. Cuando mira las jerarquías de clase, no mira dentro de ellas, lo que significa que está tratando con un número pequeño de entidades.

Lo mismo si es verdadero para funciones anidadas. Al dividir tu código en varios niveles de jerarquía, mantienes cada nivel lo suficientemente pequeño para que el cerebro humano lo comprenda.

Los cierres (o funciones anónimas) solo ayudan a descifrar el código de una manera ligeramente diferente a la de OOP, pero en realidad no crean ninguna jerarquía.Están aquí para ayudarte a ejecutar tu código en el contexto de otro bloque de código. En C++ o Java tienes que crear una clase para eso, en JavaScript la función es suficiente. Por supuesto, la clase independiente es más fácil de entender, ya que es más fácil para los humanos verla como un bloque independiente. La función parece ser mucho más pequeña en tamaño y el cerebro a veces piensa que puede comprenderla Y codificar a su alrededor al mismo tiempo, lo que generalmente es una mala idea. Pero puedes entrenar a tu cerebro para que no lo haga :)

Así que no, no creo que las funciones anónimas sean para nada dañinas, solo tienes que aprender a lidiar con ellas, ya que aprendiste a manejar las clases.

+0

Sí, pero al insistir en este punto de vista, cualquier programa sería simplemente una llamada anidada profundamente a funciones anónimas, que es lo que creo que son los lenguajes funcionales, por lo tanto el)))))))))))))) al final de cada programa LISP. se supone que la eliminación de anidamientos mejora la legibilidad, reduce la sangría, mantiene el número de paréntesis anidados en un mínimo manejable y, en general, tiene un código de autodescripción. Si lo anida, básicamente está haciendo el trabajo de la computadora: realizar una pila de llamadas, y en el proceso no está etiquetando (por lo tanto describiendo) nada. –

+0

El código LISP es tan legible y autodescriptivo como cualquier código OOP. Solo tienes que leerlo de otra manera, es una habilidad especial a la que tienes que dedicar tiempo. Digamos, el idioma alemán es tan legible como el inglés para una persona que los conoce a ambos. La misma situación aquí. – vava

+0

Excepto que no tiene idea de la acción que realiza sobre un objeto hasta el final de la frase, algo que es aún más evidente en japonés, donde el verbo siempre _hacia_ al final. Personalmente creo que los lenguajes de SVO son superiores a los de SOV, y llevo mi opinión a los lenguajes de programación. –

-2

A quien se le ocurrió la idea de exigir que las funciones se vinculen a los identificadores, no le hicieron ningún favor a ningún programador. Si nunca has hecho una programación funcional y no estás familiarizado y cómodo con las funciones que son valores de primera clase, no eres un verdadero programador.

De hecho, para contrarrestar su propio argumento, llegaría a considerar que las funciones vinculadas a nombres (globales) son dañinas. Consulte Crockford's article about private and public members y obtenga más información.

+1

funciona como entidades de primera clase, y el hecho de que puedan vincularse a identificadores son conceptos separados. En cualquier caso, vincular un nombre dado y descriptivo a una función es útil para la documentación. Si le doy una función anónima, no puede entender su uso a menos que eche un vistazo al interior y "ejecute" su lógica. Si le digo que la función está asociada al identificador readFile, obtiene su comportamiento simplemente leyendo en el identificador asociado. Esto no es posible con funciones anónimas, y la ventaja de no tener que dar un nombre duele en la legibilidad. –

+0

@Stefano: no creo que sea exacto decir que "funciona como entidades de primera clase, y el hecho de que puedan estar vinculados a los identificadores son conceptos separados". Para poder tratar las funciones como entidades de primera clase, debe poder evitar darles un nombre, ¿correcto? De lo contrario, no pueden pasarse o devolverse desde funciones como valores sin nombre como '42',' 6.9' o '" una cadena "'. Y funciona como entidades de primera clase es una construcción poderosa y útil, ¿estarías de acuerdo? –

+1

No necesita dar un nombre a una función como 'función (x, y) {return x + y; } '- es tan útil como escribir' ++ i; // incrementa i'. –

0

También creo que las funciones anónimas (en los últimos idiomas a los que a menudo se hace referencia como cierres) tienen grandes ventajas y hacen que el código sea a menudo más legible y más corto. A veces me estoy volviendo loco cuando tengo que trabajar con Java (donde los cierres no son características de lenguaje de primera clase).

Si el problema es la indentación y demasiadas variables de función encapsuladas, entonces debe refactorizar el código para que sea más modular y legible.

En cuanto a java-script, creo que las variables de función se ven bastante feas y hacen que el código esté desordenado (la cadena de función encapsulada (...) {} hace que el código de java script sea menos legible). Como ejemplo, prefiero la sintaxis de cierre de groovy ('{}' y '->' caracteres).

3

Sorprendentemente, JavaScript le permite nombrar funciones "anónimos":

function f(x) { 
    return function add(y) { 
     return x+y; 
    }; 
} 
+1

Una vez que comprenda que esas son ** expresiones de función **, no solo "funciones anónimas", se vuelve menos entretenido;) – kangax

+0

@Mark Bessey: No estoy seguro exactamente de lo que está diciendo. La mayoría de los idiomas que le permiten generar valores del tipo de función (== funciones anónimas) le permitirán asociar esos valores con nombres de variables. Esto es lo mismo que asignar el valor "anónimo" '4.2' a la variable nombrada' x' en la instrucción C 'x = 4.2;'. –

+1

Supongo que el punto que estaba tratando de hacer es que las expresiones de función tienen una propiedad de nombre opcional, lo cual es irónico para una función "anónima". Por ejemplo: var s = function square (x) {return x * x;} que define una función llamada square y la enlaza a la s variable. Rara vez hay una buena razón para no nombrar las funciones en Javascript. El nombre de la función aparece en los rastreos de la pila, por ejemplo, lo que puede ayudar con la depuración. –

0

Si una función no es comprensible sin un nombre, el nombre es probablemente demasiado tiempo. Usa los comentarios para explicar el código críptico, no confíes en los nombres.

+1

comentarios no se ejecutan. el código lo hace. –

Cuestiones relacionadas