メソッドのパラメーター化とグローバル変数


10

私のコードが成長し始めるとき、私をしばらく悩ませてきた非常に単純な質問があります。

ネストされた関数呼び出しの長いルートを通過するときに、パラメーターをグローバル変数に置き換える必要がありますか?

多くの関数が共有変数を変更できるため、グローバル環境はプログラムの状態を予測不可能にする可能性があることを理解していますが、それでもグローバルスペースは物事をとても簡単にします。

私自身について説明しましょう:

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.
}

と取り換える:

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

2番目の方法は、パラメーターが簡単に蓄積され、コードを再利用する必要があるときに非常に制限される場合があるため、プログラムに非常に多くの自由を与えると感じますが、同時に、変数に関連する場合、関数がモジュール性を失うように感じますグローバル環境では、たとえば、finallyDoSomethingWithX別の変数thaで操作したい場合にも再利用性が失われglobalXます。

私は実際にデザインパターンを使用していないため、これが起こっていると思います。Javascriptでプログラミングしているためです。私にとっては、中規模プロジェクトでは、1つのスクリプトですべてを扱う言語のように感じます。

何かアドバイスは?パターン?必要に応じて、より具体的にすることができます。


5
通常、変数を非常に深く渡している場合、問題は正しく分割されていません。システムの他の場所で状態を駆動するグローバル変数については、ペストのように避けてください。ある時点で管理することは不可能であり、ランダムに予期していなかった関数によって一部の状態が変化するため、ランダムに壊れることがあります。
mgw854

ペストのようにそれを避けてください。わかった。「問題を正しく分解していない」についてもう少し詳しく説明していただけますか。私は一般的な考えを理解していますが、それを理解するための例や何かを思いつくことはできません。
AFP_555 2017

2
多くの層の深さに引数を渡すことに気付いたときの一般的な救済策は、メソッドオブジェクトを作成することです。そのメソッドは、パラメータを渡す関数に対応する新しいクラスのオブジェクトです。パラメータはオブジェクトに対してローカルな変数になり、そのメソッドは値を渡す必要がなくなります。
Kilian Foth 2017

@KilianFothありがとう。答えを確認できるように、コードを詳しく説明してもらえますか?
AFP_555 2017

1
JavaScriptコードの構造を、他の言語(「実際の」クラスを使用する言語など)と同じように扱うことを検討してください。SO上でこの関連の質問にいくつかの有用なリンク: stackoverflow.com/questions/927651/...
ベン・コットレル

回答:


7

グローバル変数を使用しないでください。

また、関数のチェーンにパラメーターを渡さないでください!

実際の例を使わないので難しいです。しかし、通常はより良いアプローチがあります。

さまざまな低レベル関数で使用されるAPIを呼び出すために使用する必要があるパスワード変数があるとします。

グローバルなアプローチ(psudoコード)

var pass;

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

パラメータを渡す方法

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

オブジェクトアプローチ

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

    function Multiply(a,b) {
        api.Multiply(a,b); //uses pass from constructor
    }
}

素晴らしい。この方法のパスはグローバル環境にはなく、オブジェクトの属性から取得できるため、マルチ関数のパラメーターでもありません。ありがとう。
AFP_555 2017

3

ペストのようなグローバルは避けてください。

どのコードでもグローバルを変更できます。したがって、チェーンA(x)-> B(x)-> C(x)-> ...-> Z(x)があり、xをグローバルXに格納すると、チェーンA-ができます。 > B-> C-> ...-> Zの場合、その長いチェーンのすべてのステップで、または完全に独立したコードで、誰かがXを変更する可能性があります。Zが使用する値は、Aの値とはまったく異なる場合がありますで始まった。

コードが想定どおりの動作をすることを確認したり、コードが意図したとおりに動作することを確認したりするのは、悪夢です。


1
完全に同意する。グローバルを使用して問題を解決すると、2つの問題が発生します。
Caleb Mauer 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.