Cuando trato con algoritmos complicados en lenguajes con soporte para funciones anidadas (como Python y D), a menudo escribo funciones enormes (porque el algoritmo es complicado) pero mitigo esto usando funciones anidadas para estructurar el código complicado. ¿Las funciones enormes (más de 100 líneas) todavía se consideran malas, incluso si están bien estructuradas internamente mediante el uso de funciones anidadas?
Editar: para aquellos de ustedes que no están familiarizados con Python o D, las funciones anidadas en estos lenguajes también permiten el acceso al alcance de la función externa. En D este acceso permite la mutación de variables en el ámbito externo. En Python solo permite la lectura. En D puede deshabilitar explícitamente el acceso al ámbito externo en una función anidada al declararlo static
.
Respuestas:
¡Siempre recuerda la regla, una función hace una cosa y lo hace bien! Si puede hacerlo, evite las funciones anidadas.
Se dificulta la legibilidad y las pruebas.
fuente
Algunos han argumentado que las funciones cortas pueden ser más propensas a errores que las funciones largas .
Personalmente, descubrí que el código de línea recta bien comentado es más fácil de seguir (especialmente cuando usted no fue quien lo escribió originalmente) que cuando se divide en múltiples funciones que nunca se usan en otro lugar. Pero realmente depende de la situación.
Creo que la conclusión principal es que cuando divide un bloque de código, está intercambiando un tipo de complejidad por otro. Probablemente hay un punto dulce en algún lugar en el medio.
fuente
Idealmente, toda la función debería ser visible sin tener que desplazarse. A veces, esto no es posible. Pero si puede dividirlo en pedazos, hará que leer el código sea mucho más fácil.
Sé que tan pronto como presione Page Up / Down o me mueva a una sección diferente del código, solo puedo recordar 7 +/- 2 cosas de la página anterior. Y desafortunadamente, algunas de esas ubicaciones se utilizarán al leer el nuevo código.
Siempre me gusta pensar en mi memoria a corto plazo como los registros de una computadora (CISC, no RISC). Si tiene la función completa en la misma página, puede ir al caché para obtener la información requerida de otra sección del programa. Si la función completa no cabe en una página, eso sería el equivalente de siempre empujar cualquier memoria al disco después de cada operación.
fuente
¿Por qué usar funciones anidadas, en lugar de funciones externas normales?
Incluso si las funciones externas solo se usan alguna vez en una función que antes era grande, todavía hace que todo el desastre sea más fácil de leer:
fuente
No tengo el libro frente a mí en este momento (para citar), pero según Code Complete, el "punto dulce" para la longitud de la función era de alrededor de 25-50 líneas de código según su investigación.
Hay momentos en los que está bien tener funciones largas:
Los momentos en que no está bien tener funciones largas:
La conclusión es que la capacidad de mantenimiento debe ser una de las principales prioridades de su lista. Si otro desarrollador no puede ver su código y obtener una "idea" de lo que está haciendo el código en menos de 5 segundos, su código no proporciona suficientes "metadatos" para decir lo que está haciendo. Otros desarrolladores deberían poder decir qué está haciendo su clase simplemente mirando el navegador de objetos en su IDE elegido en lugar de leer más de 100 líneas de código.
Las funciones más pequeñas tienen las siguientes ventajas:
La lista continua.....
fuente
La respuesta es que depende, sin embargo, probablemente debería convertir eso en una clase.
fuente
No me gustan la mayoría de las funciones anidadas. Las lambdas caen en esa categoría, pero generalmente no me señalan a menos que tengan más de 30-40 caracteres.
La razón básica es que se convierte en una función localmente densa con recursividad semántica interna, lo que significa que es difícil para mí asimilar mi cerebro y es más fácil llevar algunas cosas a una función auxiliar que no satura el espacio de código .
Considero que una función debe hacer lo suyo. Hacer otras cosas es lo que hacen otras funciones. Entonces, si tiene una función de 200 líneas Doing Its Thing, y todo fluye, eso está bien.
fuente
Es aceptable? Esa es realmente una pregunta que solo tú puedes responder. ¿La función logra lo que necesita? ¿Es mantenible? ¿Es 'aceptable' para los otros miembros de su equipo? Si es así, eso es lo que realmente importa.
Editar: no vi lo que pasa con las funciones anidadas. Personalmente, no los usaría. En su lugar, usaría funciones regulares.
fuente
Una función larga "en línea recta" puede ser una forma clara de especificar una secuencia larga de pasos que siempre ocurren en una secuencia particular.
Sin embargo, como otros han mencionado, esta forma es propensa a tener tramos locales de complejidad en los que el flujo general es menos evidente. Colocar esa complejidad local en una función anidada (es decir, definida en otro lugar dentro de la función larga, quizás en la parte superior o inferior) puede restaurar la claridad del flujo de la línea principal.
Una segunda consideración importante es controlar el alcance de las variables que están destinadas a ser utilizadas solo en un tramo local de una función larga. Se requiere vigilancia para evitar tener una variable que se introdujo en una sección del código referenciada involuntariamente en otro lugar (por ejemplo, después de ciclos de edición), ya que este tipo de error no aparecerá como un error de compilación o tiempo de ejecución.
En algunos idiomas, este problema se puede evitar fácilmente: un tramo de código local se puede envolver en su propio bloque, como con "{...}", dentro del cual las variables recién introducidas solo son visibles para ese bloque. Algunos lenguajes, como Python, carecen de esta característica, en cuyo caso las funciones locales pueden ser útiles para imponer regiones de menor alcance.
fuente
No, las funciones de varias páginas no son deseables y no deben pasar la revisión del código. Solía escribir funciones largas también, pero después de leer Refactorización de Martin Fowler , me detuve. Las funciones largas son difíciles de escribir correctamente, difíciles de entender y de probar. Nunca he visto una función de incluso 50 líneas que no se entendería y probaría más fácilmente si se dividiera en un conjunto de funciones más pequeñas. En una función de varias páginas, es casi seguro que haya clases enteras que se deben factorizar. Es difícil ser más específico. Tal vez debería publicar una de sus funciones largas en Code Review y alguien (tal vez yo) puede mostrarle cómo mejorarla.
fuente
Cuando estoy programando en Python, me gusta dar un paso atrás después de haber escrito una función y preguntarme si se adhiere al "Zen de Python" (escriba 'importar esto' en su intérprete de Python):
Hermoso es mejor que feo.
Explícito es mejor que implícito.
Simple es mejor que complejo.
Complejo es mejor que complicado.
Plano es mejor que anidado.
Escaso es mejor que denso.
La legibilidad cuenta.
Los casos especiales no son lo suficientemente especiales como para romper las reglas.
Aunque la practicidad supera la pureza.
Los errores nunca deben pasar en silencio.
A menos que sea silenciado explícitamente.
Ante la ambigüedad, rechaza la tentación de adivinar.
Debe haber una, y preferiblemente solo una, forma obvia de hacerlo.
Aunque esa manera puede no ser obvia al principio a menos que seas holandés.
Ahora es mejor que nunca.
Aunque nunca es mejor que lo correctoahora.
Si la implementación es difícil de explicar, es una mala idea.
Si la implementación es fácil de explicar, puede ser una buena idea.
Los espacios de nombres son una gran idea, ¡hagamos más de eso!
fuente
Póngalos en un módulo separado.
Asumiendo que su solución no está más hinchada que la necesidad, no tiene demasiadas opciones. Ya ha dividido las funciones en diferentes subfunciones, por lo que la pregunta es dónde debe colocarlo:
Ahora, tanto la segunda como la tercera alternativa anidan en cierto sentido, pero la segunda alternativa para algunos programadores no parece estar mal. Si no descarta la segunda alternativa, no veo demasiadas razones para descartar la tercera.
fuente