web-dev-qa-db-fra.com

L'utilisation d'une fonction dans une boucle for est-elle une mauvaise pratique?

J'ai récemment lu quelque part que l'appel d'une fonction dans une boucle est considéré comme une mauvaise pratique. Est-ce vrai? Ainsi, par exemple, si j'avais ce qui suit:

function foo(value){
    console.log(value);
}

var bar = ["Foo", "Bar"];

for(var i = 0; i < bar.length; i++){
    foo(bar[i]);
}

Est-ce une mauvaise pratique de le faire? Devrais-je avoir une autre façon d'appeler foo?

Note: Cette question n'est pas spécifique à Javascript, c'est juste dans quoi j'ai écrit la question.

6
Robert

Ce n'est pas une mauvaise pratique ... tout dépend de ce que fait la fonction, et si le code dans la fonction doit être dans une boucle, ou s'il peut être refactorisé en dehors d'une boucle.

Une fonction n'est qu'un ensemble d'instructions, vous pouvez donc, théoriquement, prendre les instructions de n'importe quelle fonction et les mettre directement dans la boucle, et vous avez essentiellement la même chose. Si cet ensemble d'instructions consiste à ajouter deux plus deux, vous n'avez pas à vous soucier de beaucoup. Si cet ensemble d'instructions consiste à ouvrir une table de base de données de 10 millions de lignes, à trouver une ligne, à écrire les valeurs sur le disque, à fermer la connexion et à répéter, alors vous avez quelque chose à penser.

Souvent, quel que soit le temps que cela prend, cela peut être tout simplement nécessaire même s'il n'est pas performant. D'autres fois, vous pourriez vraiment mettre des choses stupides en boucle.

Prenons l'exemple "ouvrir une table de base de données de 10 millions de lignes et écrire les valeurs de chaque ligne dans un fichier".

Mauvaise boucle:

int count = GetFullCountFromSomewhere();
for (int i = 0 i < count; i++) {
   GetMyRow(i);
   WriteMyRow(i);
}

function GetMyRow(i) {
   Table table = new Table();
   table.Fill(someConnection);
   Row row = table.Rows[i];
   return row;
}

Dans ce qui précède, une instance de table (et tous les frais généraux associés) est effectuée nécessairement pour chaque itération.

Meilleure boucle:

Table table = GetMyTable()
for (int i = 0 i < table.Rows.count; i++) {
   WriteMyRow(table.Rows[i]);
}

function GetMyTable(i) {
   Table table = new Table();
   table.Fill(someConnection);
   return table;
}

ou, peut-être encore mieux (car il pourrait être optimisé en interne par le compilateur de langage):

Table table = GetMyTable();
ForEach(var row in Table.Rows) {
    WriteMyRow(row);
}

Ainsi, vous pouvez voir quelques façons de gérer le code dans une boucle par rapport à sa configuration en dehors de la boucle.

C'est vraiment la seule chose à considérer, au moins au jour le jour.

12
jleach