2010年12月3日金曜日

柔軟なコード設計=シンプルなコードとは必ずしもならない件

「シンプルisペスト」はプログラマの合言葉だとは思うのだけれど、設計変更に対して柔軟であろうとするコードってのは必ずしもシンプルにはなってくれないな・・・と感じています。

汎用的なコード設計とか大げさな話じゃなくて、もっとささやかな話ですよ。

例えば、

void Receive(int Param1, int Param2)

のように2つの引数を受け取るReceive関数が存在し、後になってこのReceive関数の引数が3つ必要になってしまう・・・という事態になったとしましょう。

その場合、もし全ソースコード中でReceive関数が記述されている箇所が数ヶ所であれば変更コストも少なくて済みますが、これが数百ヶ所ともなるとただ事ではなくなります。

それでも、リファクタリングや自動テスト環境が十分に整った開発環境であれば対応できなくもありませんが、そんな環境では無い場合には、プログラマは突然腹痛に見舞われることになるでしょう。

 

もし、事前に変更の可能性を予見できた場合には、例えばReceive関数に受け渡すパラメータを構造体にまとめてしまって、そのポインタを渡すという形式にすることが考えられます。

struct Param{
    int Param1;
    int Param2;
};

void Receive(Param *pParam)

これならば、パラメータの型や数に変更の要求が出てきたとしても、Receive関数は一切いじらずに済みそうです。変りにソースコードが以前よりも少しゴチャっとしだします。

 

例えば数値代入にしても、

Param1 = 25;

で済んでいたのが、

pParam->Param1 = 25;

と書かねばならなくなってしまいました。

 

また、void Receive(Param *pParam)をみて、Param構造体がどのようなメンバを持つのかパッと見分かりません。マウスカーソルを当てればメンバがポップアップ表示されるようなIDEが使える環境であれば不自由ないかもしれませんが、そうで無い場合はこれは少しストレスになります。

「いや、構造体使っても全然シンプルじゃん」と思われるかもしれませんが、それはシンプルな例を示しているからそう感じられるだけです。実際には、構造体内に構造体が入り組んだり、クラスを渡したり、キャストが乱入したりしてソースコード数十万行のいたるところでそのような記述が目に付くようになると、とてもシンプルなコードには見えなくなってきます。

 

以上、柔軟性を確保しようとコードを書き直したら、該当部分のコード量が2倍になってしまったので衝動的に書いたエントリーでした。