La réponse primaire, bien sûr, est: diviser en petits morceaux, chaque morceau fait une chose bien.
Il est difficile d'être plus précis sans voir un exemple, mais vous avez dit que vous avez un "... état de condition dans une grande déclaration de changement ..." qui offre certainement une opportunité d'amélioration: Vous pouvez déplacer le contenu de chaque cas dans sa propre fonction. Si vous faites cela, vous avez deux choix: soit faire fonctionner les fonctions uniquement avec les arguments que vous leur transmettez, ce qui tend à rendre les choses plus modulaires, soit à rendre les fonctions de fermeture qui manipulent les données dans la fonction externe. Je dirais que ce dernier est moins idéal — pour ces fins — mais il peut être plus rapide à faire et ainsi être une "victoire rapide".
Disons que nous avions à l'origine:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
/* ...do lots of stuff involving v1 and v2...*/
break;
case bar:
/* ...do lots of stuff involving v1 only...*/
break;
case charlie:
/* ...do lots of stuff involving v2 and v3...*/
break;
}
}
Puis:
La première option: Complètement fonctions indépendantes:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
doFooStuff(v1, v2);
break;
case bar:
doBarStuff(v1);
break;
case charlie:
doCharlieStuff(v2, v3);
break;
}
}
function doFooStuff(v1, v2) {
}
function doBarStuff(v1) {
}
function doCharlieStuff(v2, v3) {
}
... et bien sûr, les chances sont que vous auriez besoin de ces fonctions retourner quelque chose, puis gérer cela, par exemple:
case foo:
v1 = doFooStuff(v1, v2);
break;
... si doFooStuff
doit mettre à jour v1
. Si elle a besoin de mettre à jour v1
et v2
, vous pouvez retourner un tableau, ou faire v1
et v2
propriétés sur un objet que vous passez dans doFooStuff
, etc. Voici un exemple d'utilisation des propriétés: Remplacer les v1
et v2
propriétés avec un objet (vdata
) qui a v1
et v2
propriétés sur elle:
var vdata = {
v1: "someInitialValue",
v2: "someInitialValue"
};
... alors votre appel à doFooStuff
:
case foo:
doFooStuff(vdata);
break;
...qui permet doFooStuff
de mettre à jour à la fois v1
et v2
. Mais attention, vous ne voulez pas créer un évier avec toutes les variables de myBigFunction
, cela sacrifierait la modularité.
La deuxième option: Utilisation de fermetures et de travailler directement avec les données de la fonction parent:
function myBigFunction() {
var v1, v2, v3;
/* ...set v1, v2, and v3 to various things...*/
switch (condition) {
case foo:
doFooStuff();
break;
case bar:
doBarStuff();
break;
case charlie:
doCharlieStuff();
break;
}
function doFooStuff() {
// work with v1 and v2 directly
}
function doBarStuff() {
// work with v1 directly
}
function doCharlieStuff() {
// work with v2 and v3 directly
}
}
Notez que ici, les différents sous-programmes sont des fermetures à l'intérieur myBigFunction
et ils ont un accès direct à tous myBigFunction
' s variables locales. Ceci est plus modulaire, mais pas tout à fait l'approche modulaire complète de la première option. C'est aussi comme une version locale du problème des fonctions fonctionnant avec des variables globales: Les effets secondaires sont faciles à introduire et peuvent causer des problèmes.
La première option est préférée, mais si elle n'est pas pratique, la deuxième option peut au moins vous aider à rendre la logique de votre ligne principale plus claire. Et bien sûr, une combinaison des deux peut fonctionner.
Il existe de nombreux modèles de conception qui peuvent être utilisés pour résoudre le problème de conditions trop imbriquées/trop profondément imbriquées, cependant, certains exemples de code ou de maquette seront utiles en premier. – Anurag
a ajouté un exemple – meleyal