web-dev-qa-db-ja.com

シングルスレッド、非OS、組み込みアプリケーションでグローバル変数が悪いのはなぜですか

グローバル変数の使用に対する反対意見のほとんどは、複数のスレッド、スレッドセーフなどの問題に言及しているため、理にかなっています。

しかし、小さなシングルスレッドの非OSの場合、どのような異議がありますか?私の場合、重要な場合は、組み込みシステムを「C」で記述しています。私はこの製品の唯一の開発者でもあります。

グローバル変数を削除するとコードが改善されるのはなぜですか?

(いくつかの応答を読んだ後、このシステムには動的なメモリ割り当てがないことも指摘しておく必要がありました(例:malloc)。すべてのメモリはコンパイル時に静的に割り当てられます。)

30
loneRanger

そうではありません。

グローバル変数に関する2つの基本的な問題は、名前空間が乱雑になることと、「誰も」がそれらを「制御」できないという事実です(したがって、潜在的な衝突と複数のスレッドとの競合)。

他のほとんどすべてのコンピュータプログラミングイディオムがガイドラインであり、厳格なルールではないように、「グローバルは悪い」。このような「ルール」を作るときは、ルール作成の背景にある状況や動機を理解するために、単に暗記でルールを採用するよりも最善です。盲目的に服用しないでください。

あなたの場合、あなたはあなたのシステムの性質とルールに関する議論を理解しているようで、この場合は適用されないと判断しました。そうです、そうではありません。

だから、それについて心配しないでください。

49
Will Hartung

これは理由を与える良い記事です グローバル変数が悪い理由

不要なときにグローバル変数を避ける必要があるのはなぜですか?

非局所性-ソースコードは、個々の要素の範囲が制限されている場合に最も理解しやすくなります。グローバル変数は、プログラムのどの部分でも読み取ったり変更したりできるため、考えられるすべての使用法を覚えたり、推論したりすることが困難になります。アクセス制御や制約チェックなし-グローバル変数はプログラムの任意の部分で取得または設定でき、その使用に関するルールは簡単に破られたり忘れられたりする可能性があります。

暗黙的な結合-多くのグローバル変数を持つプログラムは、多くの場合、それらの変数のいくつかの間で緊密な結合、および変数と関数の間の結合を持っています。結合されたアイテムをまとまりのあるユニットにグループ化すると、通常、より良いプログラムにつながります。

メモリ割り当ての問題-一部の環境には、グローバルの割り当てを難しくするメモリ割り当てスキームがあります。これは、「コンストラクター」に割り当て以外の副作用がある言語で特に当てはまります(その場合、2つのグローバルが相互に依存しているという危険な状況を表現できるため)。また、モジュールを動的にリンクする場合、異なるライブラリに独自のグローバルインスタンスがあるかどうか、またはグローバルが共有されているかどうかが不明確になる可能性があります。

テストと制限-グローバルを利用するソースは、実行間で「クリーンな」環境を簡単にセットアップできないため、テストがやや困難になります。より一般的には、そのソースに明示的に提供されていないあらゆる種類のグローバルサービスを利用するソースは、同じ理由でテストするのが困難です。

グローバルの追加は本当に簡単です。それらを宣言する習慣を身につけるのは簡単です。良いデザインを考えるよりもはるかに高速です。

グローバル変数はあなたが思うほど悪くはありません。不必要なときはいつでも避けるべきです。グローバル変数は、プログラム全体で使用される変数をうまく利用できます。その変数がどこで変更を行うかを常に追跡する必要があることを忘れないでください。ただし、プログラムの限られた部分でのみ使用される傾向がある変数の場合は、グローバルにすることを避けるのが適切な理由です。

18
TStamper

マクロが必ずしも悪いわけではなく、濃縮ウランが必ずしも悪いわけではないのと同じように、グローバル変数は必ずしも悪いわけではありません。与えられたデザインの選択の長所と短所について意識的な決定を下す限り、あなたは大丈夫であるはずです。

引数のいくつかに対してグローバル変数は次のとおりです。

  1. それらは優れたオブジェクト指向設計に違反します
  2. コードが期待するすべてのグローバル変数を設定せずにコードの個々のブロックをテストすることはできないため、コードの単体テストが困難になります。
  3. これらはコードの結合度を高めます。あるコードブロックでのアクションは、共有グローバル変数を介して予測できない方法で別のコードブロック内のものに影響を与える可能性があります。

いくつかの議論者forグローバル変数:

  1. 多くの機能間で単一のリソースを簡単に共有できます
  2. コードを読みやすくすることができます

設計において、グローバル変数が理にかなっており、ランダムなエラーやテストの頭痛の種を設定することなく、コードを読みやすく、保守しやすくするために使用できる場合は、必ずそれらを使用してください。

私は組み込みマイクロコントローラー用に多くのCコードを記述しており、常にグローバル変数を使用しています。このような厳格なシステムでは、グローバル変数は理にかなっています。私は潜在的な欠点を認識していますが、長所と短所を分析し、主要な落とし穴を防ぐためにコードを記述しています。

結論:厳格なルールはありません。あなたが持っている最良の情報に基づいて、あなたの特定のプロジェクトまたはプラットフォームに最適な決定をするだけです。

18
e.James

カップリングを最小限に抑えるためです。あなたのシステムは今は小さいかもしれませんが、あなたが働き続けるならば、それはそうではないことがわかるかもしれません。

8
Otávio Décio

Cで記述された小さな組み込みアプリケーションでは、グローバル変数が必要です。たとえば、割り込みサービスルーチンと別のモジュールの間で情報を渡すには、グローバル変数を使用する必要があります。これらは、組み込みアプリケーションでグローバル変数を効果的に使用するのに役立ついくつかのヒントです。

  • 静的変数とグローバル変数を区別します。静的変数は、同じCファイル内のすべての関数から使用できます。これらは、C++クラスのプライベートメンバーに相当します。 Cでは、コンパイラの仕事を自分で行う必要があります。 staticキーワードを使用して、モジュール外での変数の誤った使用を回避し、そのスコープを明確にします。変数の前にモジュールの名前を付けることをお勧めします。

  • グローバル変数(多くのCファイルで使用される)の命名規則に従います。それらがグローバルであることを明確に示してください。

  • 多くのグローバル変数が必要な場合は、それらを構造体にバンドルすることを検討してください。

  • 必要に応じて、volatileキーワードを使用します。これは、グローバル変数がISRによって変更される場合に必要です。

7
kgiannakakis

グローバル変数を使用するコードは、保守が困難です。メンテナは、変数が何をするのかを正確に知る前に、システム内の変数のすべての使用法を見つける必要があるためです。これはメンテナンスを遅くするので、可能な限り避けるべきです。それだけです `

6

それは範囲の問題です。ローカルの概念を実行するためにグローバル変数を作成するのが大好きな開発者がいます。これらの変数の使用法を追跡するのがはるかに困難になるため、それらの使用法を間違えやすくなります。

フロントポーチに財布を置いておくこともできますが、誰がそれにアクセスするかを制御することははるかに少なくなります。

とはいえ、グローバル変数にはいくつかの有効な用途がありますが、他のルールと同様に、従う価値があります。これは例外であり、通常の場合ではありません。彼らの非常に既存の指摘は、彼らには用途があると指摘しています。

グローバル変数を使用することにした場合は、コメントを付けて、適切な名前を付けてください。人々が「boolbIsFound;」のようなグローバル変数を作成するとき、それは本当に私を悩ませます。

コードレビューで新しいグローバル変数をそれぞれ評価し、より良いアプローチがあるかどうかを確認することが重要です。

2
John Christman

簡単に言えば、グローバル変数は歴史的に微妙なバグの原因でした。しかし、(私の関数型プログラマーの帽子をかぶって)all変数は微妙なバグの原因となっています。

基本的に、グローバル変数とは、変数の値を使用してコードを確認し、その変数の値を設定する他のすべてのコードが過去に何をしたかを知らなければ、コードが何をするかを知ることができないことを意味します。

1
Charlie Martin

おそらくグローバル変数そうではありませんあなたの場合は悪いです。一方、あなたはそれらが必要ですか?それらを使用することで何が得られますか?

あなたの場合でも、グローバル変数はアプリケーションの状態を理解するのを難しくします。これはデバッグを妨げる可能性があり、微妙なバグにつながる可能性があります。

グローバル変数もテストを難しくします。これらは、テスト中に避けたい外部コードへの依存関係を追加します。

しかし最後に、Cでプログラミングする場合、グローバルを回避するのは困難です。より高度な言語では、グローバルはほとんどの場合無意味です。それらを使用しても、コードが明確になるわけではありません。

Cでは、グローバルが最良で、最も単純で、最もクリーンなソリューションである場合がたくさんあります。

したがって、あなたの場合は、ケースバイケースでそれを取ります。おそらくいくつかのグローバルを持つことになりますが、それが実際に最良の解決策であることが確実でない限り、変数をグローバルにしないでください。今だけでなく、コードをデバッグしたりアプリケーションを作成したりする必要がある1年後もマルチスレッド。

1
jalf

ほとんどの変数をローカルに保ち、その範囲を縮小することは、より良いプログラミング手法を促進するのに役立ちます。また、変数を誤って変更し、意図しないまたは非自明な結果を探すために関数をトレースする必要があるリスクを軽減します。また、コードの特定のセクションに関連する変数のほとんどが近くで定義および初期化されるため、コードの読み取りと保守が容易になると思います。そうでなければ、私は常にすべてのゴルバルを定義するコードのセクションを参照しているようです。私はいくつかのグローバルを使用しますが、主に構成情報をサブモジュールに渡すために使用します。

0
jholl

グローバル変数を使用すると、それらがいつどこで更新され、どのコードがその変数を更新するかを知るのが難しいことがよくあります。誰がそれを更新できるか、または変数がどのように更新されるかについての制御はありません。

アプリケーションが小さいかどうかを追跡するのはそれほど難しいことではありませんが、アプリケーションが大きくなり、グローバル変数が増えるほど、アプリケーションコードはスパゲッティのように見えます。

つまり、メンテナンスとデバッグの悪夢になります。

0
rein

問題は、最後のコードのどのビットがグローバルの状態を変更したかを追跡することです。一般に、変数についてより簡単に推論できるように、変数を可能な限り最小のスコープ内に保持する必要があります。

0
Richard

頭に浮かぶ理由の1つは、将来の保証です。あなたは現在あなたの製品の唯一の開発者かもしれませんが、他の人が後でそれを維持することは考えられます。もちろん、これはあなたの特定のケースでは当てはまらないかもしれません。

あなたの製品は今は小さくて整頓されているかもしれませんが(グローバル変数を使用しても全体的なデザインが複雑になったり、読みやすさが損なわれたりすることはありません)、製品がそれほど大きくなったり、別の製品に組み込まれたりすることはありませんか?そして、神は別のメンテナ/開発者があなたのグローバル変数の使用を整理しなければならないことを禁じています。

もちろん、グローバル変数を使用することを決定することもできます。プロジェクトがより複雑になっているように見える場合は、戻ってその一部を書き直してください。しかし、なぜその余分な作業を自分で強制するのでしょうか。 (グローバル変数を覚えている場合)その作業を行うのは大変な労力であると判断し、設計を手放す可能性が高くなります。この時点で問題が発生します。

だから、頭痛の種を避け、将来を見据えてデザインしてください。今必要な仕事は、おそらく将来の生活を楽にするでしょう。

それでも納得がいかない場合は、このプロジェクトに取り組んだ開発者であり、最高裁判所の前でコードに欠陥があり、悪いプログラミング慣行で有罪とされたと想像してみてください。 バギー飲酒検知器コードはソースレビューの重要性を反映しています

0
Casey