Méthodes de paramétrage vs variables globales

10

J'ai une question très simple qui me hante depuis un moment lorsque mon code commence à grandir.

Les paramètres doivent-ils être remplacés par des variables globales lorsqu'ils passent par de longues routes d'appels de fonctions imbriquées?

Je comprends que l'environnement global peut rendre l'état d'un programme imprévisible car de nombreuses fonctions peuvent modifier des variables partagées, mais malgré tout, l'espace global rend les choses si faciles.

Je m'explique:

functionA(){
   x = something
   functionB(x)
}
functionB(x){
   functionC(x)
}
functionC(x){
   finallyDoSomethingWithX(x)
}
finallyDoSomethingWithX(x){
  x += 1 //Very dummy example ignoring pass by value, not reference.
}

Remplacé par:

globalX;
functionA(){
   globalX = something
   functionB()
}
...
...
...
finallyDoSomethingWithX(){
   globalX += 1
}

Je pense que la deuxième façon donne tellement de liberté pour programmer parce que les paramètres peuvent s'accumuler facilement et peuvent également être très restrictifs parfois lorsque le code doit être réutilisé, mais en même temps, j'ai l'impression que la fonction perdra sa modularité lorsqu'elle est liée à une variable dans l'environnement global, perdant également la réutilisabilité lorsque, par exemple, je veux fonctionner finallyDoSomethingWithXavec une autre variable différente tha globalX.

Je pense que cela m'arrive parce que je n'utilise pas réellement de modèles de conception parce que je programme en Javascript, ce qui pour moi ressemble à un langage à script unique pour tous les projets moyens.

Des conseils? motifs? Je peux être plus précis si besoin.

AFP_555
la source
5
En règle générale, si vous transmettez des variables très profondément, vous n'avez pas correctement résolu le problème. Quant aux variables globales conduisant l'état ailleurs dans le système, évitez-le comme la peste. Il est impossible de gérer à un certain point, et vous constaterez que les choses se brisent au hasard parce qu'un état est muté par une fonction à laquelle vous ne vous attendiez pas au hasard.
mgw854
A éviter comme la peste. Compris. Pourriez-vous nous en dire un peu plus sur "vous n'avez pas résolu le problème correctement". Je comprends l'idée générale mais je ne peux pas trouver un exemple ou quelque chose pour la comprendre vraiment.
AFP_555
2
Un remède courant lorsque vous vous retrouvez à passer des arguments à plusieurs niveaux est de créer un objet méthode : un objet d'une nouvelle classe dont les méthodes correspondent aux fonctions qui transmettent les paramètres. Les paramètres peuvent alors devenir des variables locales à l'objet, et ses méthodes n'ont plus besoin de transmettre les valeurs.
Kilian Foth
@KilianFoth Merci. Pourriez-vous s'il vous plaît élaborer avec du code afin que je puisse vérifier la réponse?
AFP_555
1
Pensez à traiter la structure de votre code JavaScript comme vous le feriez dans d'autres langues (comme celles qui utilisent des classes "réelles"). Quelques liens utiles sur cette question connexe sur SO: stackoverflow.com/questions/927651/…
Ben Cottrell

Réponses:

7

N'utilisez pas de variables globales.

De plus, ne transmettez pas de paramètres à des chaînes de fonctions!

C'est difficile parce que vous n'utilisez pas d'exemple réel. Mais normalement, il y aura une meilleure approche.

Disons que nous avons une variable de mot de passe que nous devons utiliser pour appeler des API qui à leur tour sont utilisées par diverses fonctions de bas niveau.

Approche globale (code psudo)

var pass;

function multiply(a,b) {
   return apiMultiply(pass,a,b);
}

Approche de passage de paramètres

function multiply(a,b,pass) {
    return apiMultiply(pass,a,b);
}

Approche objet

class math {
    var api;
    constructor(pass) {
        api = new api(pass);
    }

    function Multiply(a,b) {
        api.Multiply(a,b); //uses pass from constructor
    }
}
Ewan
la source
Excellent. De cette façon, pass n'est pas dans l'environnement global et n'est pas non plus un paramètre pour plusieurs fonctions car il peut être extrait des attributs de l'objet. Merci.
AFP_555
3

Évitez les globaux comme la peste.

Tout code peut modifier un global. Donc, si vous aviez une chaîne A (x) -> B (x) -> C (x) -> ... -> Z (x), et vous stockez x dans un X global et maintenant vous avez une chaîne A- > B-> C -> ...-> Z, puis à chaque étape de cette longue chaîne, ou dans un code complètement indépendant, quelqu'un pourrait changer X. Et la valeur que Z utilise pourrait être complètement différente de celle que A a commencé avec.

C'est un cauchemar si jamais vous voulez être sûr que votre code fait ce qu'il est censé faire, ou qu'il fait ce que vous pensez qu'il fait.

gnasher729
la source
1
Entièrement d'accord. Si vous utilisez des globaux pour résoudre votre problème, vous avez maintenant deux problèmes.
Caleb Mauer