7

グローバル変数とその誤用に関する議論は、それに一定の独断的な口調を持っているようです。「グローバルは悪い」という概念に異議を唱えるためにここにいるわけではありません。なぜグローバルが悪いのかが私には理にかなっているからです。ただし、スコープの高い変数とオブジェクトをコードから効果的にリファクタリングする方法を正確に示す興味深いコードスニペットがあるかどうか疑問に思いました。この質問では、「簡単なので、ここでグローバル変数を使用する必要がある」という一般的で有用な解決策の例またはパターンを探しています。

これは架空の、おそらく考案された例です。関数に送信されたパラメーターを追跡するためにグローバル変数を使用しています。そして、チェーンのさらに下流で障害が発生した場合は、グローバル変数のパラメーターを使用して、戻って関数を再度呼び出すことができます。

public var myGlobalState:Object = new Object();

public function addPerson (name:String, person:Object, personCount:int, retryCount:int):void
{
     myGlobalState = null; // Clear out old values

     myGlobalState = new Object();
     myGlobalState.name = name;
     myGlobalState.person = person;
     myGlobalState.personCount = personCount;
     myGlobalState.retryCount = retryCount;

     person.userId = personCount + 1;
     person.name = name;

     savePerson(person);
}

public function savePerson (person:Object):void
{
    // Some code that attempts to save the person object properties to a database...
    // The process returns a status code for SUCCESS of FAILURE.

    // CODE TO SAVE TO DATABASE ....

    // Return status code...

    if (status == "fail")
    {
        // Retry at least once by calling the addPerson function again

        if (myGlobalState.retryCount < 3)
        {
            addPerson (myGlobalState.name, person, myGlobalState.personCount, myGlobalState.retryCount);
        }
    }
}
4

3 に答える 3

12

スニペットはありませんが、実際の例があります。アプリケーションの線形キャリブレーション定数(質量分析フィールド)はグローバルであり、さまざまなスペクトルのグローバルキャリブレーション定数を保存および復元するための複雑なコードがありました。2つの値の使用法はプログラム全体に広がり、2つの定数を使用した未校正の質量値と校正済みの質量値の間の変換がすべての場合に正しいことを変更または確認することは困難でした。

キャリブレーションされていない質量値とキャリブレーションされた質量値の間の変換を担当するクラスに2つのキャリブレーション定数をカプセル化することでリファクタリングしました。変換を行う機能も導入されたため、プログラム全体に分散するのではなく、プログラム内の1か所に集中化されました。このカプセル化により、後で新しい種類のキャリブレーション(線形ではない)を簡単に導入できるようになりました。

2つのグローバル変数にアクセスする代わりに、スペクトルを表すクラスは、新しいキャリブレーションクラスのインスタンスを持ち、使用します。各インスタンスには、独自のキャリブレーション定数のセットがあります。

于 2009-09-04T11:38:49.220 に答える
5

簡単な解決策は、すべてのグローバル変数を1つの巨大なオブジェクト内に追加し、場合によっては複数の子オブジェクトを追加してデータのグループを分離することです。これらすべての変数が1つのオブジェクトに含まれている場合、必要なのは、このオブジェクトを格納するための1つのグローバル変数だけです。すべてのコードは、グローバル変数ではなく、このオブジェクトの変数を参照します。

次のステップは、この単一のグローバルオブジェクトを取り除くことです。そして、それは数百のグローバル変数を取り除くよりも簡単なはずです。これは、他のメソッドに渡す追加のパラメーターに変更することで実行できます。

すべてのグローバルデータがなくなったら、コードをリファクタリングして、この共有オブジェクトを複数の小さなオブジェクトに分割するなどして最適化することを検討できます。ただし、すべてを1つのオブジェクト内に移動することで、すべての管理が容易になります。

于 2009-09-04T12:49:41.470 に答える
2

答えは通常、プログラムのアーキテクチャにあります。グローバル変数が絶対に必要な方法で設計することができ、それらを必要としない方法で設計することができます。通常、後のシナリオでは、より優れたクリーンなアーキテクチャになり、グローバル変数などに依存するメソッドの単体テストを作成する際の通常の問題をすべて回避できます。

この質問も役立ちます。

PS特定のシナリオでは、グローバル変数は実際にはまったく必要ありませんaddPerson。メソッドにパラメーターとして簡単に渡すことができます。

于 2009-09-04T11:40:06.860 に答える