🚫グローバル変数の危険性と非局所性
関連する情報をより狭く、よりローカルなコンテキストで保存するのではなく、コードの様々なポイントでグローバル変数の使用や設定に依存しすぎる形でコードが構成されています。
この問題は、ソフトウェアの保守を困難にし、脆弱性の発見や修正が困難になったり、時間がかかったりすることで、間接的にセキュリティに影響を及ぼします。また、脆弱性の導入が容易になる可能性もあります。
読みづらさに漬け込まれる。というのがCWE1108「グローバル変数への過度の依存の意見」だ。同じ趣旨で1126「不必要に広い範囲の変数の宣言」というのもある
非局在的な性質=依存度
非局所的な応答が起きるということは、喩えて言うならば、ゴムひもの1点に力を加えると他の全ての点に変形が起きる、というようなものである
静的フィールドも「好ましくない」と?
JavaやC#のような後発のオブジェクト指向言語はグローバル変数を持たないが、クラスの静的フィールド(クラス変数)がグローバル変数に相当する。静的フィールドは一度だけ呼び出される静的イニシャライザまたは静的コンストラクタにより初期化処理を制御することができるが、グローバル変数と同じく非局在的な性質を内包しているため、多用するとコード品質の低下を招く。特に、再代入可能な静的フィールドを外部に公開することは避けるべきとされている
Finalとかしなかった例
non-transitivity(非遷移性)
public class FunctionTable {
public static FuncLoader m_functions;
}
本当にあった怖い話。「public staticをfinal宣言しないでクラス公開すると、公開した型によっては外部から乗っ取られるコード書かれるかもよ?大丈夫?」ということらしい。CWEにもあった
Javaアプレットのようなモバイルコードは、ネットワークを介して送信され、リモートマシン上で実行されるコードです。モバイルコードの開発者は、そのコードが実行される環境をほとんど制御できないため、特別なセキュリティ上の懸念が生じます。環境に対する最大の脅威の1つは、モバイルコードが他の潜在的に悪意のあるモバイルコードと同時に実行されるリスクです。一般的なウェブブラウザはすべて、複数のソースからのコードを同じJVMで一緒に実行するため、モバイルコードのセキュリティガイドラインの多くは、あなたのプログラムが実行されているのと同じ仮想マシンにアクセスできる敵対者によって、オブジェクトの状態と動作が操作されるのを防ぐことに重点を置いています。
class DataSerializer implements Serializable {
public static long serialVersionUID = 1973473122623778747L;
// ...
}
Singletonは前向きにオブジェクト社会にコミットしている。
Singleton パターンとは、そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのことである。ロケールやルック・アンド・フィールなど、絶対にアプリケーション全体で統一しなければならない仕組みの実装に使用される
AlgorithmParameterGeneratorクラスは、特定のアルゴリズムで使われるパラメータのセットを生成するために使用されます。パラメータ・ジェネレータは、getInstanceファクトリ・メソッド(指定したクラスのインスタンスを返すstaticメソッド)を使って構築されます。
en:Initialization-on-demand holder idiom オンデマンドの初期化ホルダーイディオム
ただしこの場合、Singletonクラスがロードされたときに初期化されるのであって、getInstance()が初めて呼ばれたときではない。このことはプログラマーの意図しないタイミングで初期化が始まってしまい混乱の元となる場合がある。 そこで en:Initialization-on-demand holder idiom と呼ばれる手法、すなわちinstanceフィールドのみを別のホルダークラスに隔離して、そのホルダークラスがロードされたときにSingletonの初期化が行なわれるよう改善したものが下記である。
IoDhI =イニシャライズドオンデマンドホルダーイディオム
final class Singleton {
private Singleton() {}
private static class SingletonHolder {
private static final Singleton instance = new Singleton();
}
public static Singleton getInstance() {
return SingletonHolder.instance;
}
}
(Singleton パターンは)扱い次第では、グローバル変数のように機能させることもできる。
例えば Java にグローバル変数はないと言われているが、この Singleton パターンで Singleton クラスを作成することで、コード中のどこからでも同一のインスタンスにアクセスすることができる。これはグローバル変数そのものであり、ゆえに Singleton パターンはグローバル変数と同様の問題を引き起こす危険性をはらんでいる。ただし、パッケージ(名前空間)を指定することにより、インスタンスにアクセス可能なコード範囲を制限し、この問題を回避ないしは軽減することはできる。
推奨している感じがかっこいい。グローバルだからといって禁止ばかりされると萎える。これでは委譲でなく萎譲(萎縮して譲り渡すの意味)である。
萎えてのち方針を譲り渡す、嗚呼、萎譲。。
また、コードを工夫すればインスタンスの個数制限を設けることもできる。たとえば、上記のサンプルコード中の getInstance() を複数回呼び出したとき、10回目までは毎回新しいインスタンスを生成するが、11回目以降は以前のインスタンスを再利用する、といったような機構である。これは単なるグローバル変数で実現することはできない利点である。
これはシングル的なシングルにならないかもしれないが、ファクトリーメソッドがおそらくこういう使い方で何かできてる気がする、flyweightと組み合わせることもできるかもしれない。デザインパターン全般にいえるが、その機構から、生成時にメソッドを挟むことが多いから、生成数の制限がしやすい。どっちかっていうと、そっちが本質なんじゃないかとも思える。が、趣味でやってる限りスコープ気にすることはまずない。
![](https://assets.st-note.com/img/1660297449907-JRGy2dvKCT.png?width=1200)
お願い致します