Siempre me he preguntado qué piensan otros programadores sobre la idea de crear funciones estéticas puras.
Decir que tengo una función que procesa un fragmento de datos: Function ProcessBigData
. Digo que necesito varias etapas del proceso, sólo es válida para que los datos: Step1
, Step2
, Step3
.
El enfoque normal que más veo en el código fuente es escribir comentarios así:
Function ProcessBigData:
# Does Step1
Step1..
Step1..
#Does Step2
Step2..
Step2..
Lo que suelo hacer, pero siempre me sentí mal debido a la falta de ese estilo de codificación por parte de otros compañeros es:
Function ProcessBigData:
Function Step1:
Step1..
Step1..
Function Step2:
Step2..
Step2..
Step1() -> Step2()
Me preocupa principalmente si hay inconvenientes para ese estilo en Javascript y Python
¿Hay alguna alternativa que no esté viendo?
javascript
python
coding-style
Slytael
fuente
fuente
Respuestas:
No es tan extraño como podrías pensar. Por ejemplo, en ML estándar se acostumbra limitar el alcance de las funciones auxiliares. De acuerdo, SML tiene sintaxis para facilitarlo:
Consideraría este buen estilo, dado que 1) las funciones pequeñas facilitan el razonamiento sobre el programa, y 2) le indica al lector que estas funciones no se usan fuera de ese alcance.
Supongo que es posible que haya algo de sobrecarga en la creación de las funciones internas cada vez que se llama a la función externa (no sé si JS o Python optimizan eso) pero ya sabes lo que dicen sobre la optimización prematura.
fuente
Por lo general, es bueno hacer esto siempre que sea posible, pero me gusta pensar en este tipo de trabajo no como "pasos", sino como subtareas .
Una subtarea es una unidad de trabajo específica que se puede hacer: tiene una responsabilidad específica y entradas y salidas definidas (piense en la "S" en SÓLIDO ). Una subtarea no necesita ser reutilizable: algunas personas tienden a pensar "Nunca tendré que llamar a esto desde otra cosa, entonces ¿por qué escribirlo como una función?" Pero eso es una falacia.
Intentaré también describir los beneficios y también cómo se aplica a las funciones anidadas (cierres) frente a solo otra función de la clase. En términos generales, recomendaría no usar cierres a menos que lo necesite específicamente (hay muchos usos, pero separar el código en fragmentos lógicos no es uno de ellos).
Legibilidad.
Más de 200 líneas de código de procedimiento (cuerpo de una función) son difíciles de leer. Las funciones de 2 a 20 líneas son fáciles de leer. El código es para humanos.
Anidado o no, en su mayoría obtiene el beneficio de la legibilidad, a menos que esté utilizando muchas variables del ámbito primario, en cuyo caso puede ser tan difícil de leer.
Limitar alcance variable
Tener otra función lo obliga a limitar el alcance variable y específicamente a pasar lo que necesita.
Esto a menudo también hace que el código de estructura sea mejor, porque si necesita algún tipo de variable de estado de un "paso" anterior, es posible que en realidad haya otra subtarea que debería escribirse y ejecutarse primero para obtener ese valor. O, en otras palabras, hace que sea más difícil escribir fragmentos de código altamente acoplados.
Tener funciones anidadas le permite acceder a variables en el ámbito primario desde el interior de la función anidada (cierre). Esto puede ser muy útil, pero también puede conducir a errores sutiles y difíciles de encontrar, ya que la ejecución de la función puede no ocurrir en la forma en que está escrita. Este es aún más el caso si está modificando variables en el ámbito primario (una muy mala idea, en general).
Pruebas unitarias
Cada subtarea, implementada una función (o incluso una clase) es una pieza de código independiente y comprobable. Los beneficios de las pruebas unitarias y TDD están bien documentados en otros lugares.
El uso de funciones / cierres anidados no permite pruebas unitarias. Para mí, esto es un factor decisivo y la razón por la que debería ser otra función, a menos que haya una necesidad específica de un cierre.
Trabajando en equipo / Diseño de arriba hacia abajo
Las subtareas pueden ser escritas por diferentes personas, independientemente, si es necesario.
Incluso solo, puede ser útil cuando se escribe código simplemente invocar alguna subtarea que aún no existe, mientras se construye la funcionalidad principal, y preocuparse por implementar la subtarea solo después de saber que obtendrá los resultados que necesita en un de manera significativa. Esto también se llama diseño / programación de arriba hacia abajo.
Reutilización de código
Bien, a pesar de lo que dije antes, a veces en realidad termina siendo una razón más tarde para reutilizar una subtarea para otra cosa. No estoy abogando en absoluto por el "astronauta de la arquitectura", sino que al escribir código débilmente acoplado, puede terminar beneficiándose más tarde de la reutilización.
A menudo, esa reutilización significa una refactorización, lo cual es perfectamente esperado, pero refactorizar los parámetros de entrada a una pequeña función independiente es MUCHO más fácil que extraerlo de una función de más de 200 meses después de que se escribió, lo cual es realmente mi punto aquí.
Si usa una función anidada, reutilizarla generalmente es una cuestión de refactorizar a una función separada de todos modos, lo cual nuevamente, es por eso que argumentaría que anidar no es el camino a seguir.
fuente