■構造的欠陥とは■「構造的欠陥」といっているのは、多数のソースファイルの全体におよぶ欠陥のことです。ここ では特に、プログラム全体から使われるため、たった1つのヘッダーファイルの善し悪しがプログ ラム全体に与える甚大な影響について説明します。ヘッダーファイル(.h)を作る時の常識を知らな かったために涙ぐましい苦労をしてバグを入れてしまうという欠陥です。 元のプログラムでは、先頭で標準以外のヘッダーファイルも使っていますが、さらにいくつかの 変数が別にわざわざextern宣言されています。さらにグローバルな変数の宣言も行なわれています。 大きなプログラムでは、プログラム全体で共通に使うような変数、配列、マクロなどが多数必要 になります。これをいかにちゃんとするかが、プログラムの「生死」を決めてしまいます。 抽象的説明で、理解しにくいでしょうね。
■具体例■では、変数 Cursor がどのようになっているか調べてみると、3つのファイルで使用されており、 そのうちの1つで、 unsigned char Cursor;と宣言され、他の2つでは extern unsigned char Cursor;とextern宣言されていました。このプログラムでは、かなりの数のグローバル変数の宣言がこのよ うになっています。
■欠陥■このようなコーディングをしても文法的には間違いではありませんから、バグさえなければ(こ んな書き方をしていると、そうは思えないが)一応ちゃんと動きます。 では、何が欠陥なのでしょうか?この書き方では、どのようなグローバル変数を使っているかは、 ソースファイル上では全然分かりません。要するに、変数一覧表がない訳です。手書きの変数一覧 表を用意したって、こんな書き方では、いつでも、誰でも、新しいグローバル変数を作れてしまい ます。 それに、グローバル変数の名前を変更するときなど、きっと変更忘れなどが次第に増えていくで しょう。 プログラム全体に影響の及ぶ宣言などは、個々のソースファイル(.c)には絶対に書いてはいけま せん。グローバルなものは、すべてインクルードファイル(.h)にまとめましょう。 こうすれば、インクルードファイルに書かれているものがグローバルで、個々のファイルに書か れているものはローカルなものとなり、所在がはっきりします。 こうすると、いままで何ヶ所かで宣言していたものが、たった1個所の宣言で済み、楽になりま す。「楽をしてバグを減らす」は、プログラミングの鉄則です。 ところで、グローバル宣言のし方は、 unsigned char Cursor; extern unsigned char Cursor;の2つあったのに、これがたった1つになるというのは変ですよね。でも、できるのです。どうす ればよいのでしょうか?
■グローバル宣言一覧表■次のように、extern を Extern に変更すると、どうなるでしょうか。 #ifdef GLOBAL_DEFINE #define Extern /*define*/ #else #define Extern extern #endif .......................... .......................... Extern unsigned char Cursor;まず、普通のファイルをコンパイルする時は、GLOBAL_DEFINE はマクロ定義されていないので、 Extern は extern に置換されます。 グローバル変数の実体を作るためだけのファイルを用意し、まず、 #define GLOBAL_DEFINEとして、GLOBAL_DEFINEをマクロ定義してしまいます。そのあとで、グローバルを書き並べたヘッ ダーファイルを#include してしまうと、その中のExternは消えてなくなるので、実体が確保され ます。Cのソースファイルには、関数が全然含まれていなくてもかまわないのです。 分かりましたかね。 マクロも変数もグローバルなものはとにかく全部入れてしまうと、これですっきりした上に、グ ローバルなものの一覧表ができてしまっているのです。
■効果■このように、ヘッダーファイルにまとめることによる開発上のメリットはどのくらいと思います か。1,000行以上で、複数のファイルに分けるようになってくると急激に効果が出てきます。もう、 10,000行を越える場合は、グローバルなものの整理がきちんとできないようでは、永久にバグが取 れないでしょう。この整理は、しない場合と比較すると、総開発費を何割も削減し、バグ発生率を 数分の1にすることは確実です。というより、こんなこともちゃんとできないで、1万行を越すよ うなプログラムは書くなというべきでしょう。
|
ナンプレ問題 |