Lorsque je traite des algorithmes compliqués dans des langages prenant en charge les fonctions imbriquées (comme Python et D), j'écris souvent des fonctions énormes (car l'algorithme est compliqué), mais j'atténue cela en utilisant des fonctions imbriquées pour structurer le code compliqué. Les énormes fonctions (plus de 100 lignes) sont-elles toujours considérées comme mauvaises même si elles sont bien structurées en interne via l'utilisation de fonctions imbriquées?
Edit: Pour ceux d'entre vous qui ne sont pas familiers avec Python ou D, les fonctions imbriquées dans ces langages permettent également d'accéder à l'étendue des fonctions externes. En D, cet accès permet la mutation des variables dans la portée externe. En Python, il autorise uniquement la lecture. Dans D, vous pouvez explicitement désactiver l'accès à la portée externe dans une fonction imbriquée en le déclarant static
.
Réponses:
Souvenez-vous toujours de la règle, une fonction fait une chose et la fait bien! Si vous le pouvez, évitez les fonctions imbriquées.
Il entrave la lisibilité et les tests.
la source
Certains ont fait valoir que les fonctions courtes peuvent être plus sujettes aux erreurs que les fonctions longues .
Personnellement, j'ai trouvé que le code en ligne bien commenté est plus facile à suivre (surtout lorsque vous n'êtes pas celui qui l'a écrit à l'origine) que lorsqu'il est divisé en plusieurs fonctions qui ne sont jamais utilisées ailleurs. Mais cela dépend vraiment de la situation.
Je pense que le principal point à retenir est que lorsque vous divisez un bloc de code, vous échangez un type de complexité contre un autre. Il y a probablement un endroit idéal quelque part au milieu.
la source
Idéalement, la fonction entière devrait être visible sans avoir à faire défiler. Parfois, ce n'est pas possible. Mais si vous pouvez le décomposer en morceaux, cela facilitera la lecture du code.
Je sais que dès que j'appuie sur Page Haut / Bas ou que je passe à une autre section du code, je ne me souviens que de 7 +/- 2 choses de la page précédente. Et malheureusement, certains de ces emplacements vont être utilisés lors de la lecture du nouveau code.
J'aime toujours penser à ma mémoire à court terme comme les registres d'un ordinateur (CISC, pas RISC). Si vous avez toute la fonction sur la même page, vous pouvez aller dans le cache pour obtenir les informations requises d'une autre section du programme. Si la fonction entière ne peut pas tenir sur une page, ce serait l'équivalent de toujours pousser n'importe quelle mémoire sur le disque après chaque opération.
la source
Pourquoi utiliser des fonctions imbriquées plutôt que des fonctions externes normales?
Même si les fonctions externes ne sont utilisées que dans votre seule fonction, autrefois grande, cela rend tout le désordre plus facile à lire:
la source
Je n'ai pas le livre devant moi en ce moment (pour citer), mais selon Code Complete, le "sweetspot" pour la durée de la fonction était d'environ 25 à 50 lignes de code selon ses recherches.
Il y a des moments où il est acceptable d'avoir de longues fonctions:
Les moments où ce n'est pas ok d'avoir de longues fonctions:
L'essentiel est que la maintenabilité devrait être l'une des plus hautes priorités de votre liste. Si un autre développeur ne peut pas regarder votre code et obtenir un "résumé" de ce que le code fait en moins de 5 secondes, votre code ne fournit pas suffisamment de "métadonnées" pour dire ce qu'il fait. Les autres développeurs devraient être capables de dire ce que fait votre classe simplement en regardant le navigateur d'objets dans votre IDE choisi au lieu de lire plus de 100 lignes de code.
Les fonctions plus petites présentent les avantages suivants:
La liste continue.....
la source
La réponse est que cela dépend, mais vous devriez probablement en faire un cours.
la source
Je n'aime pas la plupart des fonctions imbriquées. Les lambdas entrent dans cette catégorie, mais ne me signalent généralement que s'ils contiennent plus de 30 à 40 caractères.
La raison fondamentale est qu'elle devient une fonction très localement dense avec une récursion sémantique interne, ce qui signifie qui qu'il est difficile pour moi d'envelopper mon cerveau, et il est juste plus facile de pousser certaines choses vers une fonction d'aide qui n'encombre pas l'espace de code .
Je considère qu'une fonction doit faire sa chose. Faire d'autres choses, c'est ce que font les autres fonctions. Donc, si vous avez une fonction de 200 lignes faisant son affaire, et que tout coule, c'est A-OK.
la source
Est ce acceptable? C'est vraiment une question à laquelle vous seul pouvez répondre. La fonction atteint-elle ce dont elle a besoin? Est-il maintenable? Est-ce «acceptable» pour les autres membres de votre équipe? Si c'est le cas, c'est ce qui compte vraiment.
Edit: je n'ai pas vu la chose sur les fonctions imbriquées. Personnellement, je ne les utiliserais pas. J'utiliserais plutôt des fonctions régulières.
la source
Une longue fonction "en ligne droite" peut être un moyen clair de spécifier une longue séquence d'étapes qui se produisent toujours dans une séquence particulière.
Cependant, comme d'autres l'ont mentionné, cette forme a tendance à avoir des étendues locales de complexité dans lesquelles le flux global est moins évident. Placer cette complexité locale dans une fonction imbriquée (c'est-à-dire: définie ailleurs dans la fonction longue, peut-être en haut ou en bas) peut restaurer la clarté du flux principal.
Une deuxième considération importante est de contrôler la portée des variables qui sont destinées à être utilisées uniquement dans un tronçon local d'une fonction longue. La vigilance est requise pour éviter d'avoir une variable introduite dans une section de code référencée involontairement ailleurs (par exemple, après des cycles d'édition), car ce type d'erreur n'apparaîtra pas comme une erreur de compilation ou d'exécution.
Dans certains langages, ce problème est facilement évité: un tronçon de code local peut être encapsulé dans son propre bloc, comme avec "{...}", dans lequel toutes les variables nouvellement introduites ne sont visibles que pour ce bloc. Certains langages, tels que Python, ne disposent pas de cette fonctionnalité, auquel cas les fonctions locales peuvent être utiles pour appliquer des régions de portée plus petite.
la source
Non, les fonctions multi-pages ne sont pas souhaitables et ne devraient pas passer en revue le code. J'écrivais aussi de longues fonctions, mais après avoir lu le refactoring de Martin Fowler , je me suis arrêté. Les fonctions longues sont difficiles à écrire correctement, difficiles à comprendre et difficiles à tester. Je n'ai jamais vu une fonction de même 50 lignes qui ne serait pas plus facile à comprendre et à tester si elle était divisée en un ensemble de fonctions plus petites. Dans une fonction multi-page, il y a presque certainement des classes entières qui devraient être éliminées. Il est difficile d'être plus précis. Vous devriez peut-être publier une de vos longues fonctions dans Code Review et quelqu'un (peut-être moi) peut vous montrer comment l'améliorer.
la source
Quand je programme en python, j'aime prendre du recul après avoir écrit une fonction et me demander si elle adhère au "Zen of Python" (tapez 'import this' dans votre interpréteur python):
Beau, c'est mieux que laid.
Explicite vaut mieux qu'implicite.
Simple, c'est mieux que complexe.
Complexe vaut mieux que compliqué.
L'appartement est meilleur que l'emboîtement.
Clairsemé vaut mieux que dense.
La lisibilité compte.
Les cas spéciaux ne sont pas assez spéciaux pour enfreindre les règles.
Bien que la praticité l'emporte sur la pureté.
Les erreurs ne doivent jamais passer silencieusement.
Sauf si explicitement réduit au silence.
Face à l'ambiguïté, refusez la tentation de deviner.
Il devrait y avoir une - et de préférence une seule - manière évidente de le faire.
Bien que cette façon ne soit pas évidente au début, sauf si vous êtes néerlandais.
C'est mieux que jamais. à présent.
Bien que jamais ne soit souvent mieux que juste
Si l'implémentation est difficile à expliquer, c'est une mauvaise idée.
Si la mise en œuvre est facile à expliquer, ce peut être une bonne idée.
Les espaces de noms sont une excellente idée de klaxon - faisons-en plus!
la source
Mettez-les dans un module séparé.
En supposant que votre solution n'est pas plus gonflée que d'avoir besoin, vous n'avez pas trop d'options. Vous avez déjà divisé les fonctions en différentes sous-fonctions, la question est donc de savoir où les mettre:
Maintenant, la deuxième et la troisième alternatives sont imbriquées dans un certain sens, mais la deuxième alternative ne semblerait pas mauvaise pour certains programmeurs. Si vous n'excluez pas la deuxième alternative, je ne vois pas trop de raisons d'exclure la troisième.
la source