Pourquoi écrire un script bash complet dans des fonctions?

59

Au travail, j'écris fréquemment des scripts bash. Mon superviseur a suggéré que le script entier soit divisé en fonctions, comme dans l'exemple suivant:

#!/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

Y a-t-il une raison de faire cela autre que la "lisibilité", qui, à mon avis, pourrait être tout aussi bien établie avec quelques commentaires supplémentaires et un espacement des lignes?

Cela rend-il le script plus efficace (je pense en réalité le contraire), ou facilite-t-il la modification du code au-delà du potentiel de lisibilité susmentionné? Ou est-ce vraiment juste une préférence stylistique?

Veuillez noter que, bien que le script ne le montre pas bien, "l'ordre d'exécution" des fonctions de nos scripts actuels tend à être très linéaire: cela walk_into_bardépend des choses que vous avez i_am_foofaites et do_bazagit walk_into_barcomme pouvoir échanger arbitrairement l'ordre d'exécution n'est généralement pas ce que nous ferions. Par exemple, vous ne voudriez pas soudainement mettre declare_variablesaprès walk_into_bar, cela casserait les choses.

Voici un exemple d'écriture du script ci-dessus:

#!/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
la source
30
J'aime ton patron. Dans mes scripts, j'ai également mis main()en haut et ajouter main "$@"en bas pour l'appeler. Cela vous permet de voir la logique de script de haut niveau en tout temps lorsque vous l'ouvrez.
John Kugelman soutient Monica le
22
Je suis en désaccord avec l'idée selon laquelle la lisibilité peut "être tout aussi bien établie avec quelques commentaires supplémentaires et un peu d'espacement des lignes". Sauf peut-être pour la fiction, je ne voudrais pas parler d'un livre sans table des matières ni nom descriptif pour chaque chapitre et chaque section. Dans les langages de programmation, c'est le type de lisibilité que les fonctions peuvent fournir, contrairement aux commentaires.
Rhymoid
6
Notez que les variables déclarées dans des fonctions doivent être déclarées local- ceci fournit une étendue de variable extrêmement importante pour tout script non trivial.
Boris l'Araignée
8
Je ne suis pas d'accord avec votre patron. Si vous devez décomposer votre script en fonctions, vous ne devriez probablement pas écrire de script shell en premier lieu. Écrivez un programme à la place.
el.pescado
6
Les fonctions sont destinées aux processus répétés, soit dans le script, soit dans plusieurs scripts. Ils permettent également la mise en place de méthodologies uniformes. Par exemple, utiliser une fonction pour écrire dans syslog. Tant que tout le monde utilise la même fonction, vos entrées syslog sont plus cohérentes. Les fonctions à usage unique telles que votre exemple compliquent inutilement le script. Dans certains cas, ils introduisent des problèmes (portée variable).
Xalorous

Réponses:

40

J'ai commencé à utiliser ce même style de programmation bash après avoir lu le billet de blog "Defensive Bash Programming" de Kfir Lavi . Il donne quelques bonnes raisons, mais personnellement, je trouve celles-ci les plus importantes:

  • les procédures deviennent descriptives: il est beaucoup plus facile de déterminer ce qu’une partie du code est censée faire. Au lieu d'un mur de code, vous voyez "Oh, la find_log_errorsfonction lit ce fichier journal pour rechercher les erreurs". Comparez cela avec la recherche d'un grand nombre de lignes awk / grep / sed qui utilisent dieu sait quel type de regex au milieu d'un long script - vous n'avez aucune idée de ce que ça fait là-bas sauf s'il y a des commentaires.

  • vous pouvez déboguer des fonctions en incluant dans set -xet set +x. Une fois que vous savez que le reste du code fonctionne correctement, vous pouvez utiliser cette astuce pour vous concentrer sur le débogage de cette fonction spécifique uniquement. Bien sûr, vous pouvez inclure des parties de script, mais que faire si c'est une longue partie? C'est plus facile de faire quelque chose comme ça:

     set -x
     parse_process_list
     set +x
  • utilisation de l'impression avec cat <<- EOF . . . EOF. Je l'ai utilisé plusieurs fois pour rendre mon code beaucoup plus professionnel. En outre, parse_args()avec la getoptsfonction est très pratique. Encore une fois, cela aide à la lisibilité, au lieu de tout placer dans le script en tant que mur de texte géant. Il est également pratique de les réutiliser.

Et bien évidemment, ceci est beaucoup plus lisible pour quelqu'un qui connaît C ou Java, ou Vala, mais qui a une expérience limitée en matière de jeu. En ce qui concerne l'efficacité, il n'y a pas beaucoup de choses que vous puissiez faire - bash n'est pas le langage le plus efficace et les gens préfèrent perl et python en termes de rapidité et d'efficacité. Cependant, vous pouvez avoir niceune fonction:

nice -10 resource_hungry_function

Comparé à un appel gentil sur chaque ligne de code, cela réduit considérablement le typage ET peut être utilisé de manière pratique lorsque vous souhaitez qu'une partie seulement de votre script s'exécute avec une priorité inférieure.

L'exécution de fonctions en arrière-plan, à mon avis, est également utile lorsque vous souhaitez que de nombreuses instructions soient exécutées en arrière-plan.

Certains des exemples où j'ai utilisé ce style:

Sergiy Kolodyazhnyy
la source
3
Je ne suis pas sûr que vous devriez prendre très au sérieux les suggestions de cet article. Certes, il a quelques bonnes idées, mais ce n’est clairement pas une personne habituée au shell scripting. Pas seule variable dans l' un des exemples est cité (!) Et il suggère d' utiliser des noms de variables Majuscules qui est souvent une très mauvaise idée , car ils peuvent entrer en conflit avec vars env existant. Vos arguments dans cette réponse sont logiques, mais l'article lié semble avoir été écrit par une personne habituée aux autres langues et qui tente de forcer leur style à la bash.
terdon
1
@terdon, je suis retourné à l'article et je l'ai relu. Le seul endroit où l'auteur mentionne le nommage des variables majuscules se trouve dans "Variables globales immuables". Si vous considérez les variables globales comme celles qui doivent être dans l'environnement de la fonction, il est logique de les transformer en capital. En passant, le manuel de bash ne stipule pas de convention pour les cas variables. Même dans ce cas, la réponse acceptée indique "généralement" et le seul "standard" est celui de Google, qui ne représente pas l’ensemble du secteur informatique.
Sergiy Kolodyazhnyy 10/02/2017
@terdon sur une autre note, je suis d'accord à 100% sur le fait que la citation de variable aurait dû être mentionnée dans l'article, et cela a également été souligné dans les commentaires sur le blog. De plus, je ne jugerais pas que quelqu'un utilise ce style de codage, qu'il soit ou non habitué à une autre langue. Toute la question et les réponses montrent clairement qu'il y a des avantages à cela, et le degré auquel une personne est habituée à parler une autre langue n'est probablement pas pertinent ici.
Sergiy Kolodyazhnyy
1
@terdon eh bien, l'article a été posté dans le cadre de la "source". J'aurais pu tout publier comme mes propres opinions, mais je devais simplement reconnaître que certaines des choses que j'ai apprises dans l'article et que tout cela provenait de recherches menées au fil du temps. La page linkedin de l'auteur montre qu'ils ont une bonne expérience de Linux et de l'informatique en général. Je suppose donc que cet article ne le montre pas vraiment, mais je fais confiance à votre expérience en ce qui concerne Linux et les scripts shell. Vous avez peut-être raison .
Sergiy Kolodyazhnyy
1
C'est une excellente réponse, mais j'aimerais aussi ajouter que la portée variable de Bash est géniale. Pour cette raison, je préfère déclarer mes variables dans les fonctions en utilisant localet en appelant tout via la main()fonction. Cela rend les choses beaucoup plus faciles à gérer et vous pouvez éviter une situation potentiellement compliquée.
Housni
65

La lisibilité est une chose. Mais la modularisation ne se limite pas à cela. (La semi-modularisation est peut-être plus correcte pour les fonctions.)

Dans les fonctions, vous pouvez garder certaines variables locales, ce qui augmente la fiabilité et réduit les risques d’embrouillage.

Un autre avantage des fonctions est la réutilisation . Une fois qu'une fonction est codée, elle peut être appliquée plusieurs fois dans le script. Vous pouvez également le porter sur un autre script.

Votre code peut maintenant être linéaire, mais à l'avenir, vous pourrez entrer dans le domaine du multi-threading ou du multi-traitement dans le monde Bash. Une fois que vous apprenez à faire des choses dans les fonctions, vous serez bien équipé pour entrer dans le parallèle.

Un dernier point à ajouter. Comme le remarque Etsitpab Nioliv dans le commentaire ci-dessous, il est facile de rediriger les fonctions en tant qu’entité cohérente. Mais il y a un autre aspect des redirections avec des fonctions. À savoir, les redirections peuvent être définies dans la définition de la fonction. Par exemple.:

f () { echo something; } > log

Maintenant, aucune redirection explicite n'est nécessaire pour les appels de fonction.

$ f

Cela peut épargner de nombreuses répétitions, ce qui augmente encore la fiabilité et aide à garder les choses en ordre.

Voir également

Tomasz
la source
55
Très bonne réponse bien que ce serait beaucoup mieux si elle était divisée en fonctions.
Pierre Arlaud
1
Peut-être ajouter que les fonctions vous permettent d'importer ce script dans un autre script (en utilisant sourceou . scriptname.sh, et d'utiliser ces fonctions telles quelles, si elles étaient dans votre nouveau script.
SnakeDoc
C'est déjà couvert dans une autre réponse.
Tomasz
1
J'apprécie ça. Mais je préférerais que les autres soient aussi importants.
Tomasz
7
Aujourd’hui, j’ai été confronté à une affaire dans laquelle je devais rediriger une partie de la sortie d’un script vers un fichier (pour l’envoyer par courrier électronique) au lieu de faire écho. Je devais simplement faire maFonction >> monFichier pour rediriger la sortie des fonctions désirées. Assez pratique. Pourrait être pertinent.
Etsitpab Nioliv
39

Dans mon commentaire, j'ai mentionné trois avantages des fonctions:

  1. Ils sont plus faciles à tester et à vérifier leur exactitude.

  2. Les fonctions peuvent être facilement réutilisées (source) dans les futurs scripts

  3. Votre patron les aime.

Et ne sous-estimez jamais l’importance du chiffre 3.

J'aimerais aborder un autre problème:

... donc pouvoir échanger arbitrairement l'ordre d'exécution n'est généralement pas ce que nous ferions. Par exemple, vous ne voudriez pas soudainement mettre declare_variablesaprès walk_into_bar, cela casserait les choses.

Pour tirer le meilleur parti du code, c’est-à-dire rendre les fonctions aussi indépendantes que possible. Si walk_into_barnécessite une variable qui n’est pas utilisée ailleurs, cette variable doit alors être définie et localisée dans walk_into_bar. Le processus de séparation du code en fonctions et de réduction de leurs interdépendances devrait rendre le code plus clair et plus simple.

Idéalement, les fonctions devraient être faciles à tester individuellement. Si, en raison des interactions, ils ne sont pas faciles à tester, c'est un signe qu'ils pourraient bénéficier de la refactorisation.

John1024
la source
Je dirais qu’il est parfois judicieux de modéliser et d’appliquer ces dépendances, par opposition au refactoring pour les éviter (car s’ils sont suffisants, et suffisamment poilus, cela peut simplement conduire à un cas où les choses ne sont plus modélisées. fonctions du tout). Un cas d'utilisation très compliqué a par le passé inspiré un cadre pour faire exactement cela .
Charles Duffy
4
Ce qui doit être divisé en fonctions devrait l'être, mais l'exemple le prend trop loin. Je pense que le seul qui me dérange vraiment est la fonction de déclaration de variable. Les variables globales, en particulier les variables statiques, doivent être définies globalement dans une section commentée dédiée à cette fin. Les variables dynamiques doivent être locales aux fonctions qui les utilisent et les modifient.
Xalorous
@Xalorous J'ai vu des pratiques dans lesquelles les variables globales sont initialisées dans une procédure, comme une étape intermédiaire et rapide avant le développement d'une procédure qui lit leur valeur à partir d'un fichier externe ... Je conviens qu'il devrait être plus propre de séparer la définition et l'initialisation mais rarement obliger à se plier à l'avantage numéro 3;-)
Hastur
14

Vous divisez le code en fonctions pour la même raison que vous le feriez pour C / C ++, Python, Perl, Ruby ou tout autre code de langage de programmation. La raison la plus profonde est l'abstraction - vous encapsulez des tâches de niveau inférieur dans des primitives de niveau supérieur (fonctions), de sorte que vous n'ayez pas à vous soucier de la façon dont les choses sont accomplies. En même temps, le code devient plus lisible (et maintenable), et la logique du programme devient plus claire.

Cependant, en regardant votre code, je trouve assez étrange d’avoir une fonction pour déclarer des variables; cela me fait vraiment lever un sourcil.

contre mode
la source
Réponse sous-estimée IMHO. Suggérez-vous de déclarer les variables dans la mainfonction / méthode, alors?
David Tabernero M.
13

Bien que je sois totalement d’accord avec la réutilisabilité , la lisibilité et le fait d’embrasser délicatement les patrons, il existe un autre avantage des fonctions de : la portée variable . Comme le montre le 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.

Je ne vois pas cela très souvent dans les scripts shell du monde réel, mais cela semble être une bonne idée pour des scripts plus complexes. La réduction de la cohésion aide à éviter les bugs où vous écrasez une variable attendue dans une autre partie du code.

La réutilisation signifie souvent créer une bibliothèque commune de fonctions et l'intégrer sourcedans tous vos scripts. Cela ne les aidera pas à courir plus vite, mais cela vous aidera à les écrire plus rapidement.

poussins
la source
1
Peu de gens utilisent explicitement local, mais je pense que la plupart des gens qui écrivent des scripts divisés en fonctions suivent toujours le principe de conception. Usign localrend simplement plus difficile l'introduction de bugs.
Voo
localrend les variables disponibles pour la fonction et ses enfants, il est donc très agréable d'avoir une variable qui peut être transmise de la fonction A, mais non disponible pour la fonction B, qui peut vouloir avoir une variable du même nom mais avec un but différent. Donc c'est bon pour définir la portée, et comme l'a dit Voo - moins de bugs
Sergiy Kolodyazhnyy
10

Une raison complètement différente de celles déjà mentionnées dans d’autres réponses: une des raisons pour laquelle cette technique est parfois utilisée, où la seule instruction de définition non fonctionnelle au niveau supérieur est un appel à main, est de s’assurer que le script ne fait rien par inadvertance. si le script est tronqué. Le script peut être tronqué s'il passe du processus A au processus B (le shell) et que le processus A se termine pour une raison quelconque avant la fin de l'écriture de l'intégralité du script. Cela est particulièrement susceptible de se produire si le processus A récupère le script à partir d'une ressource distante. Pour des raisons de sécurité, ce n’est pas une bonne idée, c’est quelque chose qui est fait et certains scripts ont été modifiés pour anticiper le problème.

hvd
la source
5
Intéressant! Mais je trouve troublant qu'il faille prendre soin de ces choses dans chacun des programmes. Par contre, ce main()motif est habituel en Python où l’on utilise if __name__ == '__main__': main()à la fin du fichier.
Martin Ueding
1
L'idiome python a l'avantage de laisser les autres scripts importle script actuel sans s'exécuter main. Je suppose qu'un garde similaire pourrait être mis dans un script bash.
Jake Cobb
@ Jake Cobb Oui. Je le fais maintenant dans tous les nouveaux scripts bash. J'ai un script qui contient une infrastructure de base de fonctions utilisées par tous les nouveaux scripts. Ce script peut être recherché ou exécuté. Si source, sa fonction principale n'est pas exécutée. La détection de la source par rapport à l'exécution s'effectue via le fait que BASH_SOURCE contient le nom du script en cours d'exécution. Si c'est la même chose que le script principal, le script est en cours d'exécution. Sinon, il est recherché.
DocSalvager
7

Un processus nécessite une séquence. La plupart des tâches sont séquentielles. Cela n'a aucun sens de jouer avec l'ordre.

Mais la grande chose à propos de la programmation - qui inclut les scripts - est le test. Essais, essais, essais. Quels scripts de test avez-vous actuellement pour valider l'exactitude de vos scripts?

Votre patron essaie de vous guider d’être un script kiddy à un programmeur. C’est une bonne direction à suivre. Les gens qui viendront après vous vous plairont.

MAIS. Rappelez-vous toujours vos racines orientées processus. S'il est judicieux de classer les fonctions dans l'ordre dans lequel elles sont généralement exécutées, faites-le au moins lors du premier passage.

Plus tard, vous verrez que certaines de vos fonctions traitent les entrées, les sorties, les traitements, les données de modélisation et les autres, il peut donc être judicieux de regrouper des méthodes similaires, voire de les déplacer dans des fichiers séparés. .

Plus tard, vous réaliserez peut-être que vous avez maintenant écrit des bibliothèques de petites fonctions d'assistance que vous utilisez dans beaucoup de vos scripts.

Dewi Morgan
la source
7

Les commentaires et l’espacement ne peuvent s’approcher de la lisibilité des fonctions, comme je vais le montrer. Sans fonctions, vous ne pouvez pas voir la forêt pour les arbres - de gros problèmes se cachent parmi de nombreuses lignes de détail. En d'autres termes, les personnes ne peuvent pas se concentrer simultanément sur les détails les plus fins et sur la grande image. Cela peut ne pas être évident dans un court script; tant qu'il reste court, il peut être assez lisible. Les logiciels ne deviennent pas plus gros, mais font certainement partie de tout le système logiciel de votre entreprise, qui est sûrement beaucoup plus grand, probablement des millions de lignes.

Considérez si je vous ai donné des instructions telles que celle-ci:

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)

Au moment où vous avez atteint la moitié, voire 5%, vous auriez oublié les premières étapes. Vous ne pouviez probablement pas identifier la plupart des problèmes, car vous ne pouviez pas voir la forêt pour les arbres. Comparer avec les fonctions:

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

C'est certainement beaucoup plus compréhensible, quel que soit le nombre de commentaires que vous pourriez insérer dans la version séquentielle ligne par ligne. Cela rend également beaucoup plus probable que vous remarquerez que vous avez oublié de préparer le café et probablement oublié sit_down () à la fin. Lorsque votre esprit pense aux détails des expressions rationnelles grep et awk, vous ne pouvez pas avoir une vue d'ensemble - "Et si on ne fait pas de café"?

Les fonctions vous permettent principalement de voir la situation dans son ensemble et de remarquer que vous avez oublié de préparer le café (ou que quelqu'un pourrait préférer le thé). À un autre moment, dans un autre état d'esprit, vous vous inquiétez de la mise en œuvre détaillée.

Il y a bien sûr d'autres avantages discutés dans d'autres réponses. Un autre avantage qui n’est pas clairement indiqué dans les autres réponses est que les fonctions fournissent une garantie importante pour la prévention et la correction des bogues. Si vous découvrez qu'une variable $ foo dans la fonction correcte walk_to () était fausse, vous savez qu'il suffit de regarder les 6 autres lignes de cette fonction pour rechercher tout ce qui aurait pu être affecté par ce problème et tout ce qui pourrait ont fait que ce soit faux. Sans fonctions (appropriées), tout et n'importe quoi dans tout le système pourrait être la cause de l'inexactitude de $ foo, et tout et n'importe quoi pourraient être affectés par $ foo. Par conséquent, vous ne pouvez pas réparer en toute sécurité $ foo sans réexaminer chaque ligne du programme. Si $ foo est local à une fonction,

Ray Morris
la source
1
Ce n'est pas la bashsyntaxe. C'est dommage cependant; Je ne pense pas qu'il y ait un moyen de passer des informations à des fonctions comme celle-là. (ie pour();< coffee). Cela ressemble plus à c++ou php(je pense).
voix
2
@ tjt263 sans les parenthèses, c’est la syntaxe bash: pour café. Avec parens, c'est à peu près toutes les autres langues. :)
Ray Morris
6

Quelques truismes pertinents sur la programmation:

  • Votre programme va changer, même si votre patron insiste pour dire que ce n'est pas le cas.
  • Seuls le code et les entrées affectent le comportement du programme.
  • Nommer est difficile.

Les commentaires commencent comme un moyen de ne pas être en mesure d'exprimer clairement vos idées dans le code * et empirent (ou sont tout simplement faux) avec le changement. Par conséquent, dans la mesure du possible, exprimez les concepts, les structures, le raisonnement, la sémantique, le flux, la gestion des erreurs et tout ce qui concerne la compréhension du code en tant que code.

Cela dit, certaines fonctions de Bash n’ont pas été trouvées dans la plupart des langues:

  • L'espacement des noms est terrible dans Bash. Par exemple, si vous oubliez d'utiliser le localmot - clé, vous polluez l'espace de noms global.
  • L'utilisation local foo="$(bar)"entraîne la perte du code de sortie debar .
  • Il n'y a pas de paramètres nommés, vous devez donc garder à l'esprit ce qui "$@"signifie dans différents contextes.

* Je suis désolé si cela est offensant, mais après avoir utilisé des commentaires pendant quelques années et développé sans eux ** pendant plusieurs années, il est clair que ce qui est supérieur est.

** Il est toujours nécessaire d'utiliser des commentaires pour les licences, la documentation de l'API, etc.

l0b0
la source
Je mis presque toutes les variables locales en les déclarant nulle au début de la fonction ... local foo=""Puis les mettre en utilisant l' exécution de commande pour agir sur le résultat ... foo="$(bar)" || { echo "bar() failed"; return 1; }. Cela nous permet de quitter rapidement la fonction lorsqu'une valeur requise ne peut pas être définie. Les accolades sont nécessaires pour s’assurer qu’elles return 1ne sont exécutées qu’en cas d’échec.
DocSalvager
6

Le temps, c'est de l'argent

Il existe d’ autres bonnes réponses qui permettent de mieux comprendre les raisons techniques pour écrire de manière modulaire un script potentiellement long, développé dans un environnement de travail, développé pour être utilisé par un groupe de personnes et pas uniquement pour votre propre usage.

Je veux me concentrer sur une attente: dans un environnement de travail "le temps, c'est de l'argent" . Ainsi, l’absence de bugs et les performances de votre code sont évaluées ainsi que la lisibilité , la testabilité, la maintenabilité, la refactorabilité, la réutilisabilité ...

Ecrire dans les "modules" un code réduira le temps de lecture nécessaire non seulement au codeur lui-même, mais même au temps utilisé par les testeurs ou par le boss. De plus, notez que le temps d'un patron est généralement mieux payé que le temps d'un codeur et que votre patron évaluera la qualité de votre travail.

De plus, écrire dans des "modules" indépendants un code (même un script bash) vous permettra de travailler "en parallèle" avec un autre composant de votre équipe, réduisant ainsi le temps de production global et utilisant au mieux les compétences du célibataire, pour réviser ou réécrire une pièce avec aucun effet secondaire sur les autres, pour recycler le code que vous venez d'écrire "tel quel"pour un autre programme / script, créer des bibliothèques (ou des bibliothèques d'extraits), réduire la taille globale et la probabilité d'erreurs associée, déboguer et tester minutieusement chaque partie ... et bien sûr, il organisera votre programme en section logique / script et améliorer sa lisibilité. Toutes les choses qui permettront d'économiser du temps et donc de l'argent. L'inconvénient est que vous devez vous en tenir aux normes et commenter vos fonctions (ce que vous devez néanmoins faire dans un environnement de travail).

Adhérer à une norme ralentira votre travail au début, mais accélérera ensuite le travail de tous les autres (et de votre vôtre). En effet, lorsque le nombre de personnes impliquées augmente, la collaboration devient un besoin inévitable. Ainsi, par exemple, même si je crois que les variables globales doivent être définies globalement et non dans une fonction, je peux comprendre un standard qui les inizialise dans une fonction declare_variables()appelée toujours dans la première ligne de celle- main()ci ...

Enfin et surtout, ne sous-estimez pas la possibilité, dans les éditeurs de code source modernes, d’afficher ou de masquer des routines séparées de manière sélective ( pliage du code ). Cela gardera le code compact et concentrera l’utilisateur sur le gain de temps.

entrez la description de l'image ici

Ci-dessus, vous pouvez voir comment se déroule uniquement la walk_into_bar()fonction. Même des autres lignes avaient une longueur de 1000 lignes chacune, vous pouviez toujours garder le contrôle de tout le code sur une seule page. Notez qu'il est plié même dans la section où vous allez déclarer / initialiser les variables.

Hastur
la source
2

Outre les raisons données dans d'autres réponses:

  1. Psychologie: un programmeur dont la productivité est mesurée en lignes de code sera incité à écrire du code inutilement détaillé. Plus la gestion se concentre sur des lignes de code, plus le programmeur est incité à développer son code avec une complexité inutile. Cela n’est pas souhaitable, car une complexité accrue peut entraîner une augmentation des coûts de maintenance et des efforts supplémentaires nécessaires pour la correction des bogues.
agc
la source
1
Ce n'est pas une si mauvaise réponse, comme le disent les votes négatifs. Remarque: agc dit, c’est aussi une possibilité, et oui, c’est vrai. Il ne dit pas que ce serait la seule possibilité et n'accuse personne, il ne fait qu'énoncer les faits. Bien que je pense qu’aujourd’hui on n’ait presque pas entendu parler de contrat direct de type "ligne de code" -> "$$", signifie indirectement qu’il est assez courant que la masse du code produit compte pour la plupart des dirigeants / chefs.
user259412
2

Une autre raison souvent négligée est l'analyse syntaxique de bash:

set -eu

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

Ce script contient évidemment une erreur de syntaxe et bash ne devrait pas l'exécuter du tout, non? Faux.

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

Si nous encapsulions le code dans une fonction, cela ne se produirait pas:

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
la source