¿Por qué escribir un script bash completo en funciones?

59

En el trabajo, escribo scripts de bash con frecuencia. Mi supervisor ha sugerido que todo el script se divida en funciones, similar al siguiente ejemplo:

#!/bin/bash

# Configure variables
declare_variables() {
    noun=geese
    count=three
}

# Announce something
i_am_foo() {
    echo "I am foo"
    sleep 0.5
    echo "hear me roar!"
}

# Tell a joke
walk_into_bar() {
    echo "So these ${count} ${noun} walk into a bar..."
}

# Emulate a pendulum clock for a bit
do_baz() {
    for i in {1..6}; do
        expr $i % 2 >/dev/null && echo "tick" || echo "tock"
        sleep 1
    done
}

# Establish run order
main() {
    declare_variables
    i_am_foo
    walk_into_bar
    do_baz
}

main

¿Hay alguna razón para hacer esto además de la "legibilidad", que creo que podría estar igualmente bien establecida con algunos comentarios más y un poco de espacio entre líneas?

¿Hace que el script se ejecute de manera más eficiente (en realidad esperaría lo contrario, si es que lo hace), o hace que sea más fácil modificar el código más allá del potencial de legibilidad antes mencionado? ¿O es realmente solo una preferencia estilística?

Tenga en cuenta que, aunque el guión no lo demuestra así, el "orden de ejecución" de las funciones en nuestros scripts actuales tiende a ser muy lineal - walk_into_bardepende de las cosas que i_am_fooha hecho, y do_bazactúa sobre la materia creada por walk_into_bar- así que estar poder intercambiar arbitrariamente el orden de ejecución no es algo que generalmente estaríamos haciendo. Por ejemplo, de repente no querrás poner declare_variablesdespués walk_into_bar, eso rompería las cosas.

Un ejemplo de cómo escribiría el script anterior sería:

#!/bin/bash

# Configure variables
noun=geese
count=three

# Announce something
echo "I am foo"
sleep 0.5
echo "hear me roar!"

# Tell a joke
echo "So these ${count} ${noun} walk into a bar..."

# Emulate a pendulum clock for a bit
for i in {1..6}; do
    expr $i % 2 >/dev/null && echo "tick" || echo "tock"
    sleep 1
done
Doktor J
fuente
30
Me gusta tu jefe En mis scripts también pongo main()en la parte superior y agrego main "$@"en la parte inferior para llamarlo. Eso le permite ver la lógica del script de alto nivel primero cuando la abre.
John Kugelman apoya a Monica el
22
No estoy de acuerdo con la idea de que la legibilidad puede "estar igualmente bien establecida con algunos comentarios más y un poco de espacio entre líneas". Excepto tal vez para la ficción, no me gustaría tratar con un libro que no tiene una tabla de contenido y nombres descriptivos para cada capítulo y sección. En los lenguajes de programación, ese es el tipo de legibilidad que las funciones pueden proporcionar, y los comentarios no pueden.
Rhymoid
66
Tenga en cuenta que las variables declaradas en funciones deben declararse local: esto proporciona un alcance variable que es increíblemente importante en cualquier script no trivial.
Boris the Spider
8
No estoy de acuerdo con tu jefe. Si tiene que dividir su script en funciones, probablemente no debería escribir un script de shell en primer lugar. Escribe un programa en su lugar.
el.pescado
66
Las funciones son para procesos que se repiten, ya sea dentro del script o en más de un script. También permiten que se pongan en práctica metodologías uniformes. Por ejemplo, usar una función para escribir en syslog. Mientras todos usen la misma función, sus entradas de syslog son más consistentes. Las funciones de uso único como su ejemplo complican innecesariamente el script. En algunos casos, presentan problemas (alcance variable).
Xalorous

Respuestas:

40

Comencé a usar este mismo estilo de programación bash después de leer la publicación del blog de Kfir Lavi "Defensive Bash Programming" . Da bastantes buenas razones, pero personalmente considero que estas son las más importantes:

  • los procedimientos se vuelven descriptivos: es mucho más fácil descubrir qué debe hacer una parte particular del código. En lugar de un muro de código, verá "Oh, la find_log_errorsfunción lee ese archivo de registro en busca de errores". Compárelo con la búsqueda de un montón de líneas awk / grep / sed que usan dios sabe qué tipo de expresiones regulares en medio de un guión largo: no tiene idea de lo que está haciendo allí a menos que haya comentarios.

  • puede depurar funciones encerrándolas en set -xy set +x. Una vez que sepa que el resto del código funciona bien, puede usar este truco para centrarse en depurar solo esa función específica. Claro, puede encerrar partes del guión, pero ¿qué pasa si es una porción larga? Es más fácil hacer algo como esto:

     set -x
     parse_process_list
     set +x
    
  • uso de impresión con cat <<- EOF . . . EOF. Lo he usado varias veces para que mi código sea mucho más profesional. Además, parse_args()con la getoptsfunción es bastante conveniente. Nuevamente, esto ayuda con la legibilidad, en lugar de incluir todo en el script como un muro de texto gigante. También es conveniente reutilizarlos.

Y obviamente, esto es mucho más legible para alguien que conoce C o Java, o Vala, pero tiene una experiencia bash limitada. En cuanto a la eficiencia, no hay mucho de lo que puede hacer: bash en sí no es el lenguaje más eficiente y la gente prefiere perl y python cuando se trata de velocidad y eficiencia. Sin embargo, puede niceuna función:

nice -10 resource_hungry_function

En comparación con las llamadas agradables en todas y cada una de las líneas de código, esto disminuye la gran cantidad de tipeo Y puede usarse convenientemente cuando desea que solo una parte de su script se ejecute con menor prioridad.

Ejecutar funciones en segundo plano, en mi opinión, también ayuda cuando quieres tener un montón de declaraciones para ejecutar en segundo plano.

Algunos de los ejemplos en los que he usado este estilo:

Sergiy Kolodyazhnyy
fuente
3
No estoy seguro de que deba tomar muy en serio las sugerencias de ese artículo. De acuerdo, tiene algunas buenas ideas, pero claramente no es alguien acostumbrado a usar scripts de shell. No se cita una sola variable en ninguno de los ejemplos (!) Y sugiere el uso de nombres de variables MAYÚSCULAS, que a menudo es una muy mala idea ya que pueden entrar en conflicto con los entornos existentes. Sus puntos en esta respuesta tienen sentido, pero el artículo vinculado parece haber sido escrito por alguien que está acostumbrado a otros idiomas y está tratando de forzar su estilo a bash.
terdon
1
@terdon Regresé al artículo y lo releí. El único lugar donde el autor menciona nombres de variables en mayúscula es en "Variables globales inmutables". Si considera las variables globales como aquellas que tienen que estar dentro del entorno de la función, entonces tiene sentido convertirlas en capitales. En la nota al margen, el manual de bash no establece la convención para el caso variable. Incluso aquí la respuesta aceptada dice "generalmente" y el único "estándar" es Google, que no representa a toda la industria de TI.
Sergiy Kolodyazhnyy
@terdon en otra nota, estoy de acuerdo al 100% en que la cita variable debería haberse mencionado en el artículo, y también se ha señalado en los comentarios en el blog. Además, no juzgaría a alguien que usa este estilo de codificación, independientemente de si está acostumbrado o no a otro idioma. Toda esta pregunta y respuestas muestran claramente que tiene ventajas, y el grado de la persona a la que están acostumbradas a otro idioma probablemente sea irrelevante aquí.
Sergiy Kolodyazhnyy
1
@terdon bueno, el artículo fue publicado como parte del material "fuente". Podría haber publicado todo como mis propias opiniones, pero solo tenía que reconocer que algunas de las cosas que aprendí del artículo, y que todo esto vino de la investigación a lo largo del tiempo. La página de linkedin del autor muestra que tienen una buena experiencia con Linux y TI en general, por lo que supongo que el artículo realmente no muestra eso, pero confío en su experiencia cuando se trata de Linux y scripting de shell, por lo que puede tener razón .
Sergiy Kolodyazhnyy
1
Esa es una excelente respuesta, pero también me gustaría agregar que el alcance variable en Bash es funky. Por esa razón, prefiero declarar mis variables dentro de las funciones usando localy llamando todo a través de la main()función. Esto hace que las cosas sean mucho más manejables y puede evitar una situación potencialmente desordenada.
Housni
65

La legibilidad es una cosa. Pero hay más en la modularización que solo esto. (La semi-modularización es quizás más correcta para las funciones).

En las funciones, puede mantener algunas variables locales, lo que aumenta la confiabilidad y disminuye la posibilidad de que las cosas se estropeen.

Otro profesional de las funciones es la reutilización . Una vez que se codifica una función, se puede aplicar varias veces en el script. También puede portarlo a otro script.

Su código ahora puede ser lineal, pero en el futuro puede ingresar en el ámbito de subprocesamiento múltiple o procesamiento múltiple en el mundo Bash. Una vez que aprenda a hacer cosas en funciones, estará bien equipado para el paso hacia el paralelo.

Un punto más para agregar. Como Etsitpab Nioliv nota en el comentario a continuación, es fácil redirigir desde las funciones como una entidad coherente. Pero hay un aspecto más de las redirecciones con funciones. A saber, las redirecciones se pueden establecer a lo largo de la definición de la función. P.ej.:

f () { echo something; } > log

Ahora las llamadas a funciones no necesitan redireccionamientos explícitos.

$ f

Esto puede evitar muchas repeticiones, lo que nuevamente aumenta la confiabilidad y ayuda a mantener las cosas en orden.

Ver también

Tomász
fuente
55
Muy buena respuesta, aunque sería mucho mejor si se dividiera en funciones.
Pierre Arlaud
1
Quizás agregar esas funciones le permita importar ese script en otro script (usando sourceo . scriptname.sh, y use esas funciones como si estuvieran en su nuevo script.
SnakeDoc
Eso ya está cubierto en otra respuesta.
Tomasz
1
Soy consciente de que. Pero prefiero dejar que otras personas sean importantes también.
Tomasz
77
Hoy enfrenté un caso en el que tuve que redirigir parte de la salida de un script a un archivo (para enviarlo por correo electrónico) en lugar de hacer eco. Simplemente tenía que hacer myFunction >> myFile para redirigir la salida de las funciones deseadas. Muy conveniente Puede ser relevante.
Etsitpab Nioliv
39

En mi comentario, mencioné tres ventajas de las funciones:

  1. Son más fáciles de probar y verificar la corrección.

  2. Las funciones se pueden reutilizar (obtener) fácilmente en futuros scripts

  3. A tu jefe le gustan.

Y, nunca subestimes la importancia del número 3.

Me gustaría abordar un problema más:

... así que poder intercambiar arbitrariamente el orden de ejecución no es algo que generalmente estaríamos haciendo. Por ejemplo, de repente no querrás poner declare_variablesdespués walk_into_bar, eso rompería las cosas.

Para obtener el beneficio de dividir el código en funciones, uno debe tratar de hacer que las funciones sean lo más independientes posible. Si walk_into_barrequiere una variable que no se usa en otro lugar, entonces esa variable debe definirse y hacerse local para walk_into_bar. El proceso de separar el código en funciones y minimizar sus interdependencias debería hacer que el código sea más claro y simple.

Idealmente, las funciones deberían ser fáciles de probar individualmente. Si, debido a las interacciones, no son fáciles de probar, entonces esa es una señal de que podrían beneficiarse de la refactorización.

John1024
fuente
Yo diría que a veces es sensato modelar y hacer cumplir esas dependencias, en lugar de refactorizarlas para evitarlas (ya que si hay suficientes y son lo suficientemente peludas, eso puede llevar a un caso en el que las cosas ya no están modularizadas en funciones en absoluto). Un caso de uso muy complicado alguna vez inspiró un marco para hacer precisamente eso .
Charles Duffy
44
Lo que debe dividirse en funciones debería serlo, pero el ejemplo lo lleva demasiado lejos. Creo que el único que realmente me molesta es la función de declaración variable. Las variables globales, especialmente las estáticas, deben definirse globalmente en una sección comentada dedicada a ese propósito. Las variables dinámicas deben ser locales para las funciones que las usan y las modifican.
Xalorous
@Xalorous He visto prácticas donde las variables globales se inicializan en un procedimiento, como un paso intermedio y rápido antes del desarrollo de un procedimiento que lea su valor de un archivo externo ... Estoy de acuerdo en que debería ser más limpio separar la definición y inicialización pero rara vez hay que doblarse para obtener la ventaja número 3;-)
Hastur
14

Divide el código en funciones por la misma razón que lo haría para C / C ++, python, perl, ruby ​​o cualquier código de lenguaje de programación. La razón más profunda es la abstracción: encapsula las tareas de nivel inferior en primitivas (funciones) de nivel superior para que no tenga que preocuparse por cómo se hacen las cosas. Al mismo tiempo, el código se vuelve más legible (y mantenible), y la lógica del programa se vuelve más clara.

Sin embargo, mirando su código, me resulta bastante extraño tener una función para declarar variables; Esto realmente me hace levantar una ceja.

contramodo
fuente
Respuesta subestimada en mi humilde opinión. ¿Sugieres declarar las variables en la mainfunción / método, entonces?
David Tabernero M.
13

Si bien estoy totalmente de acuerdo con la reutilización , legibilidad y besar delicadamente a los jefes, pero hay otra ventaja de las funciones en : alcance variable . Como muestra LDP :

#!/bin/bash
# ex62.sh: Global and local variables inside a function.

func ()
{
  local loc_var=23       # Declared as local variable.
  echo                   # Uses the 'local' builtin.
  echo "\"loc_var\" in function = $loc_var"
  global_var=999         # Not declared as local.
                         # Therefore, defaults to global. 
  echo "\"global_var\" in function = $global_var"
}  

func

# Now, to see if local variable "loc_var" exists outside the function.

echo
echo "\"loc_var\" outside function = $loc_var"
                                      # $loc_var outside function = 
                                      # No, $loc_var not visible globally.
echo "\"global_var\" outside function = $global_var"
                                      # $global_var outside function = 999
                                      # $global_var is visible globally.
echo                      

exit 0
#  In contrast to C, a Bash variable declared inside a function
#+ is local ONLY if declared as such.

No veo esto muy a menudo en los scripts de shell del mundo real, pero parece una buena idea para scripts más complejos. La reducción de la cohesión ayuda a evitar errores en los que está tropezando con una variable esperada en otra parte del código.

La reutilización a menudo significa crear una biblioteca común de funciones e incorporar sourceesa biblioteca a todos sus scripts. Esto no los ayudará a correr más rápido, pero te ayudará a escribirlos más rápido.

polluelos
fuente
1
Pocas personas usan explícitamente local, pero creo que la mayoría de las personas que escriben scripts divididos en funciones siguen el principio de diseño. Usign localsolo hace que sea más difícil introducir errores.
Voo
localhace que las variables estén disponibles para funcionar y sus hijos, por lo que es realmente bueno tener una variable que se pueda transmitir desde la función A, pero que no esté disponible para la función B, que puede querer tener una variable con el mismo nombre pero con un propósito diferente. Así que eso es bueno para definir el alcance, y como dijo Voo - menos errores
Sergiy Kolodyazhnyy
10

Una razón completamente diferente de las que ya se dan en otras respuestas: una razón por la que a veces se utiliza esta técnica, donde la única declaración de definición de no función en el nivel superior es una llamada main, es asegurarse de que el script no haga nada desagradable accidentalmente si el script está truncado El script puede truncarse si se canaliza desde el proceso A al proceso B (el shell), y el proceso A finaliza por cualquier motivo antes de que haya terminado de escribir el script completo. Esto es especialmente probable que suceda si el proceso A recupera el script desde un recurso remoto. Si bien por razones de seguridad no es una buena idea, es algo que se hace y algunos scripts se han modificado para anticipar el problema.

hvd
fuente
55
¡Interesante! Pero me resulta preocupante que uno tenga que ocuparse de esas cosas en cada uno de los programas. Por otro lado, exactamente este main()patrón es habitual en Python, donde se usa if __name__ == '__main__': main()al final del archivo.
Martin Ueding
1
El idioma de Python tiene la ventaja de permitir que otros scripts importel script actual sin ejecutarse main. Supongo que se podría poner un guardia similar en un script bash.
Jake Cobb el
@Jake Cobb Sí. Ahora hago eso en todos los nuevos scripts de bash. Tengo un script que contiene una infraestructura central de funciones utilizadas por todos los nuevos scripts. Ese script puede ser obtenido o ejecutado. Si se obtiene, su función principal no se ejecuta. La detección de la fuente frente a la ejecución es a través del hecho de que BASH_SOURCE contiene el nombre del script de ejecución. Si es lo mismo que el script central, el script se está ejecutando. De lo contrario, se está obteniendo.
DocSalvager
7

Un proceso requiere una secuencia. La mayoría de las tareas son secuenciales. No tiene sentido meterse con el pedido.

Pero lo más importante de la programación, que incluye secuencias de comandos, es la prueba. Pruebas, pruebas, pruebas. ¿Qué scripts de prueba tiene actualmente para validar la exactitud de sus scripts?

Tu jefe está tratando de guiarte de ser un guionista a ser un programador. Esta es una buena dirección para entrar. A las personas que vienen después de ti les gustará.

PERO. Siempre recuerda tus raíces orientadas al proceso. Si tiene sentido tener las funciones ordenadas en la secuencia en la que normalmente se ejecutan, haga eso, al menos como primer paso.

Más adelante, verá que algunas de sus funciones están manejando entradas, otras salidas, otras procesando, otras modelando datos y otras manipulando datos, por lo que puede ser inteligente agrupar métodos similares, tal vez incluso moverlos a archivos separados .

Más tarde aún, puede darse cuenta de que ahora ha escrito bibliotecas de pequeñas funciones auxiliares que utiliza en muchos de sus scripts.

Dewi Morgan
fuente
7

Los comentarios y el espacio no pueden acercarse a la legibilidad de las funciones, como demostraré. Sin funciones, no se puede ver el bosque por los árboles: grandes problemas se esconden entre muchas líneas de detalle. En otras palabras, las personas no pueden enfocarse simultáneamente en los detalles finos y en el panorama general. Eso podría no ser obvio en un guión corto; siempre que sea breve, puede ser lo suficientemente legible. Sin embargo, el software se hace más grande, no más pequeño, y ciertamente es parte de todo el sistema de software de su empresa, que seguramente es mucho más grande, probablemente millones de líneas.

Considera si te di instrucciones como esta:

Place your hands on your desk.
Tense your arm muscles.
Extend your knee and hip joints.
Relax your arms.
Move your arms backwards.
Move your left leg backwards.
Move your right leg backwards.
(continue for 10,000 more lines)

Cuando llegaste a la mitad, o incluso al 5%, habrías olvidado cuáles fueron los primeros pasos. No podrías detectar la mayoría de los problemas, porque no podías ver el bosque por los árboles. Comparar con funciones:

stand_up();
walk_to(break_room);
pour(coffee);
walk_to(office);

Eso es ciertamente mucho más comprensible, sin importar cuántos comentarios pueda poner en la versión secuencial línea por línea. También hace que sea mucho más probable que notes que olvidaste hacer el café, y probablemente olvidaste sit_down () al final. Cuando su mente está pensando en los detalles de las expresiones regulares grep y awk, no puede estar pensando en el panorama general: "¿y si no hay café preparado"?

Las funciones principalmente le permiten ver el panorama general y notar que olvidó preparar el café (o que alguien podría preferir el té). En otro momento, en un estado mental diferente, le preocupa la implementación detallada.

También hay otros beneficios discutidos en otras respuestas, por supuesto. Otro beneficio que no se indica claramente en las otras respuestas es que las funciones proporcionan una garantía que es importante para prevenir y corregir errores. Si descubre que alguna variable $ foo en la función adecuada walk_to () estaba mal, sabrá que solo tiene que mirar las otras 6 líneas de esa función para encontrar todo lo que podría haber sido afectado por ese problema, y ​​todo lo que podría han hecho que esté mal. Sin funciones (apropiadas), cualquier cosa y todo en todo el sistema podría ser una causa de que $ foo sea incorrecto, y cualquier cosa y todo podría verse afectado por $ foo. Por lo tanto, no puede arreglar $ foo de manera segura sin volver a examinar cada línea del programa. Si $ foo es local para una función,

Ray Morris
fuente
1
Esto no es bashsintaxis. Sin embargo, es una pena; No creo que haya una manera de pasar información a funciones como esa. (es decir, pour();< coffee). Se parece más a c++o php(creo).
voces
2
@ tjt263 sin paréntesis, es la sintaxis bash: vierta café. Con parens, es prácticamente cualquier otro idioma. :)
Ray Morris
6

Algunos truismos relevantes sobre la programación:

  • Su programa cambiará, incluso si su jefe insiste en que este no es el caso.
  • Solo el código y la entrada afectan el comportamiento del programa.
  • Nombrar es difícil.

Los comentarios comienzan como una brecha para no poder expresar sus ideas claramente en el código *, y empeoran (o simplemente se equivocan) con el cambio. Por lo tanto, si es posible, exprese conceptos, estructuras, razonamiento, semántica, flujo, manejo de errores y cualquier otra cosa pertinente para la comprensión del código como código.

Dicho esto, las funciones de Bash tienen algunos problemas que no se encuentran en la mayoría de los idiomas:

  • El espaciado de nombres es terrible en Bash. Por ejemplo, olvidarse de usar la localpalabra clave da como resultado la contaminación del espacio de nombres global.
  • Usando local foo="$(bar)"resultados en la pérdida del código de salida debar .
  • No hay parámetros con nombre, por lo que debe tener en cuenta lo que "$@"significa en diferentes contextos.

* Lo siento si esto ofende, pero después de usar comentarios durante algunos años y desarrollarlos sin ellos ** durante más años, está bastante claro cuál es superior.

** Todavía es necesario usar comentarios para la licencia, documentación de API y similares.

l0b0
fuente
Me puse casi todas las variables locales al declararlas en nulo al inicio de la función ... local foo=""Entonces el establecimiento de ellos utilizando la ejecución de comandos para actuar en el resultado ... foo="$(bar)" || { echo "bar() failed"; return 1; }. Esto nos saca de la función rápidamente cuando no se puede establecer un valor requerido. Las llaves son necesarias para asegurar que return 1solo se ejecute en caso de falla.
DocSalvager
6

El tiempo es dinero

Hay otras buenas respuestas que arrojan luz sobre las razones técnicas para escribir de forma modular un guión, potencialmente largo, desarrollado en un entorno de trabajo, desarrollado para ser utilizado por un grupo de personas y no solo para su propio uso.

Quiero centrarme en una expectativa: en un entorno laboral "el tiempo es dinero" . Por lo tanto, la ausencia de errores y el rendimiento de su código se evalúan junto con la capacidad de lectura , la capacidad de prueba , el mantenimiento, la refactorización, la reutilización ...

Escribir en "módulos" un código disminuirá el tiempo de lectura necesario no solo para el codificador en sí, sino incluso el tiempo utilizado por los evaluadores o por el jefe. Además, tenga en cuenta que el tiempo de un jefe generalmente se paga más que el tiempo de un codificador y que su jefe evaluará la calidad de su trabajo.

Además, escribir en "módulos" independientes un código (incluso un script bash) le permitirá trabajar en "paralelo" con otro componente de su equipo, acortando el tiempo de producción general y utilizando, en el mejor de los casos, la experiencia del single, para revisar o reescribir una parte con sin efectos secundarios en los demás, para reciclar el código que acaba de escribir "tal cual"para otro programa / script, para crear bibliotecas (o bibliotecas de fragmentos), para reducir el tamaño general y la probabilidad relacionada de errores, para depurar y probar minuciosamente cada parte ... y, por supuesto, se organizará en la sección lógica de su programa / script y mejorar su legibilidad. Todo lo que ahorrará tiempo y dinero. El inconveniente es que debe atenerse a los estándares y comentar sus funciones (que, sin embargo, debe hacer en un entorno de trabajo).

Cumplir con un estándar ralentizará su trabajo al principio, pero acelerará el trabajo de todos los demás (y también el suyo) después. De hecho, cuando la colaboración crece en número de personas involucradas, esto se convierte en una necesidad inevitable. Entonces, por ejemplo, incluso si creo que las variables globales tienen que definirse globalmente y no en una función, puedo entender un estándar que las inicializa en una función llamada declare_variables()llamada siempre en la primera línea de la main()...

Por último, pero no menos importante, no subestimes la posibilidad en los editores de código fuente modernos de mostrar u ocultar rutinas selectivamente separadas ( plegado de código ). Esto mantendrá el código compacto y enfocará al usuario ahorrando nuevamente tiempo.

ingrese la descripción de la imagen aquí

Aquí arriba puedes ver cómo se despliega solo la walk_into_bar()función. Incluso de los otros tenían 1000 líneas de largo cada uno, aún podía mantener bajo control todo el código en una sola página. Tenga en cuenta que se pliega incluso la sección donde va a declarar / inicializar las variables.

Hastur
fuente
2

Aparte de las razones dadas en otras respuestas:

  1. Psicología: un programador cuya productividad se esté midiendo en líneas de código tendrá un incentivo para escribir código innecesariamente detallado. Cuanto más se centre la administración en las líneas de código, más incentivo tendrá el programador para expandir su código con una complejidad innecesaria. Esto no es deseable ya que una mayor complejidad puede conducir a un mayor costo de mantenimiento y un mayor esfuerzo requerido para la corrección de errores.
agc
fuente
1
No es una respuesta tan mala, como dicen los votos negativos. Nota: agc dice, también esta es una posibilidad, y sí, lo es. No dice que sería la única posibilidad, y no acusa a nadie, solo declara los hechos. Aunque creo que hoy en día casi no se escucha una "línea de código" directa -> "$$" al estilo de contrato, indirectamente significa que es bastante común, eso sí, la masa del código producido cuenta por los líderes / jefes.
user259412
2

Otra razón que a menudo se pasa por alto es el análisis sintáctico de bash:

set -eu

echo "this shouldn't run"
{
echo "this shouldn't run either"

Este script obviamente contiene un error de sintaxis y bash no debería ejecutarlo, ¿verdad? Incorrecto.

~ $ bash t1.sh
this shouldn't run
t1.sh: line 7: syntax error: unexpected end of file

Si envolviéramos el código en una función, esto no sucedería:

set -eu

main() {
  echo "this shouldn't run"
  {
  echo "this shouldn't run either"
}

main
~ $ bash t1.sh
t1.sh: line 10: syntax error: unexpected end of file
Hubert Grzeskowiak
fuente