Je peux penser à au moins deux arguments en faveur de fonctions longues:
Cela signifie que vous avez beaucoup de contexte autour de chaque ligne. Une façon de formaliser ceci: dessinez le graphe de flux de contrôle de votre code. À un sommet (~ = ligne) entre l'entrée de fonction et la sortie de fonction, vous connaissez tous les fronts entrants. Plus la fonction est longue, plus il y a de tels sommets.
Beaucoup de petites fonctions signifient qu'il existe un graphe d'appels plus grand et plus complexe. Choisissez une ligne aléatoire dans une fonction aléatoire et répondez à la question "dans quel contexte cette ligne est-elle exécutée?" Cela devient d'autant plus difficile que le graphe d'appel est volumineux et complexe, car il doit examiner plus de sommets dans ce graphe.
Il existe également des arguments contre les fonctions longues, comme la possibilité de tester l’unité. Servez-vous de votre expérience pour choisir entre l’une et l’autre.
Note: Je ne dis pas que votre patron a raison, seulement que son point de vue peut ne pas être complètement dépourvu de valeur.
Je pense que mon point de vue est que le bon paramètre d'optimisation n'est pas la longueur de la fonction. Je pense qu'il est plus utile de penser en termes de desiderata comme suit: toutes choses étant égales par ailleurs, il est préférable de pouvoir extraire du code une description détaillée de la logique métier et de la mise en œuvre. (Les détails de l'implémentation de bas niveau peuvent toujours être lus si vous pouvez trouver le bit de code approprié.)
Commentant la réponse de David Arno :
Écrire de petites fonctions est une tâche pénible, car il vous oblige à vous déplacer dans chaque petite fonction pour voir ce que le code fait.
Si la fonction est bien nommée, ce n'est pas le cas. isApplicationInProduction va de soi et il ne devrait pas être nécessaire d'examiner le code pour voir ce qu'il fait. En fait, le contraire est vrai: l’examen du code révèle moins quant à l’intention que le nom de la fonction (c’est pourquoi votre patron doit recourir à des commentaires).
Le nom met en évidence ce que la valeur de retour signifie , mais il ne dit rien sur les effets de l' exécution du code (= ce que le code fait ). Les noms (uniquement) transmettent des informations sur l' intention , le code transmet des informations sur le comportement (à partir desquelles des parties de l'intention peuvent parfois être déduites).
Parfois, vous voulez l'un, parfois l'autre, pour que cette observation ne crée pas une règle de décision unilatérale universellement valable.
Mettez tout dans une grande boucle principale même si la boucle principale compte plus de 300 lignes, la lecture est plus rapide
La numérisation est peut-être plus rapide, mais pour vraiment "lire" le code, vous devez être capable de l'exécuter efficacement dans votre tête. C'est facile avec de petites fonctions et c'est vraiment très dur avec des méthodes de plusieurs centaines de lignes.
Je suis d'accord que vous devez l'exécuter dans votre tête. Si vous avez 500 lignes de fonctionnalités dans une seule grande fonction par rapport à de nombreuses petites fonctions, je ne comprends pas pourquoi cela devient plus facile.
Supposons le cas extrême de 500 lignes de code en ligne droite ayant un effet très secondaire et si vous voulez savoir si l’effet A se produit avant ou après l’effet B. Dans le cas d’une grande fonction, utilisez Page Haut / Bas pour localiser deux lignes, puis comparez numéros de ligne. Dans le cas des nombreuses petites fonctions, vous devez vous rappeler où se produisent les effets dans l'arborescence des appels et, si vous oubliez, vous devez passer une quantité non négligeable de temps à redécouvrir la structure de cet arborescence.
Lorsque vous parcourez l'arborescence des appels des fonctions de support, vous devez également déterminer quand passer de la logique métier aux détails de la mise en œuvre. Je prétends sans preuve * que plus le graphe d’appel est simple, plus il est facile de faire cette distinction.
(*) Au moins, je suis honnête à ce sujet ;-)
Encore une fois, je pense que les deux approches ont des forces et des faiblesses.
N'écrivez que de petites fonctions si vous devez dupliquer le code
Je ne suis pas d'accord. Comme votre exemple de code le montre, de petites fonctions bien nommées améliorent la lisibilité du code et doivent être utilisées chaque fois que [par exemple] vous n'êtes pas intéressé par le "comment", mais uniquement par le "quoi" d'une fonctionnalité.
Que vous soyez intéressé par le "comment" ou le "quoi" dépend du but pour lequel vous lisez le code (par exemple, avoir une idée générale plutôt que de traquer un bogue). Le but pour lequel vous lisez le code n'est pas disponible lors de l'écriture du programme et vous lirez probablement le code à des fins différentes; différentes décisions seront optimisées à des fins différentes.
Cela dit, c’est le point de vue du patron avec lequel je suis probablement le plus en désaccord.
N'écrivez pas une fonction avec le nom du commentaire, mettez votre ligne de code complexe (3-4 lignes) avec un commentaire ci-dessus. Comme cela, vous pouvez modifier le code défaillant directement
Je ne peux vraiment pas comprendre le raisonnement derrière celui-ci, en supposant que ce soit vraiment sérieux. [...] Les commentaires ont un défaut fondamental: ils ne sont pas compilés / interprétés et ne peuvent donc pas être testés à l'unité. Le code est modifié et le commentaire est laissé seul et vous finissez par ne pas savoir qui est correct.
Les compilateurs ne comparent que les noms pour l’égalité, ils ne vous donnent jamais une MisleadingNameError. De plus, étant donné que plusieurs sites d’appel peuvent appeler une fonction donnée par son nom, il est parfois plus ardu et plus sujet aux erreurs de changer de nom. Les commentaires n'ont pas ce problème. Cependant, ceci est quelque peu spéculatif; pour vraiment régler ce problème, il faudrait probablement des données sur le point de savoir si les programmeurs sont plus susceptibles de mettre à jour des commentaires trompeurs par rapport à des noms trompeurs, et je n'ai pas cela.