最適なソースコードの記述

プログラムのソースコードを書く時にいつも悩むことがあります。
それは、ある1つの処理をさせるためだけに対しても、いろいろなアプローチ(アルゴリズム)が考えられるということです。
使い捨てレベルでいいのか、汎用性をどの程度もたせるのか、想定範囲外の事象はないか、 効率性をとことん追求するべきか、既存ライブラリモジュールは最大限利用しきれているか、 などなどなどなど・・・様々です。

実際に、同じ結果を表示させるだけなのにこんなにもソースが違うのか、という例を 以下に紹介してみます。(C言語での例です)

C言語を学習し始めたばかりの頃(Hello World を表示させたりする頃)に、 よく例題や演習問題で出てくる「四則演算」です。

[ 問題 ]
2つの変数 a、b を用意して、まず
 a=4,  b=2 
を代入して四則演算させます。次に、
 a=4,  b=0 
を代入して四則演算させます。以下のような結果を表示させてください。
-----------------
 4 + 2 = 6
 4 - 2 = 2
 4 * 2 = 8
 4 / 2 = 2
 4 + 0 = 4
 4 - 0 = 4
 4 * 0 = 0
 4 / 0 = ERROR !
-----------------
例えば、このようなものです。


以下に2種類のソースコードがありますが、
はテキストにあるような模範的な(初心者向きな)書き方になっています。
はひねくれた私のスタイルで書いたものです。
見比べてみて、どう感じるでしょうか。

#include <stdio.h>

int main ( int argc , char *argv[] )
{
    int i ;        /* ループ用変数 */
    int a , b ;    /* 演算用変数 */

    for ( i = 1 ; i <= 2 ; i ++ )   /* 2回ループ */
    {
        if ( i == 1 )   /* 1回目のループの時 */
        {
            a = 4 ;
            b = 2 ;
        }
        else            /* 2回目のループの時 */
        {
            b = 0 ;
        }

        printf ( "%d + %d = %d\n" , a , b , a + b ) ;   /* 加算 */

        printf ( "%d - %d = %d\n" , a , b , a - b ) ;   /* 減算 */

        printf ( "%d * %d = %d\n" , a , b , a * b ) ;   /* 乗算 */

        printf ( "%d / %d = " , a , b ) ;               /* 除算の左辺の式 */

        if ( b != 0 )   /* もし b が 0 ではないなら */
        {
            printf ( "%d\n" , a / b ) ;   /* 除算を実行して表示 */
        }
        else            /* もし b が 0 なら */
        {
            printf ( "ERROR !\n" ) ;   /* エラーと表示 */
        }
    }

    return 0 ;
}

#include <stdio.h>

enum{ GOOD, BAD };      /* waru_zero用 */
int waru_zero = GOOD;   /* 0で割りそうだったらBAD, それ以外はGOOD */

#define  ENZAN_NUM     4            /* 演算の種類の数 */
#define  ERRORSTR      "ERROR ! "   /* エラーの文字 */

#define  TASU(p, q)    p+q                             /* マクロ (たす) */
#define  HIKU(p, q)    p-q                             /* マクロ (ひく) */
#define  KAKERU(p, q)  p*q                             /* マクロ (かける) */
#define  WARU(p, q)    ((q) ? p/q : (waru_zero=BAD))   /* マクロ (わる) */
	/* q が 0 なら割り算を行わず、waru_zero に BAD を代入する */

/* 四則演算の関数 */
int tasu(int x, int y){   return TASU(x, y); }
int hiku(int x, int y){   return HIKU(x, y); }
int kakeru(int x, int y){ return KAKERU(x, y); }
int waru(int x, int y){   return WARU(x, y); }

/* マクロ関数 */
int (*p_enzan[ENZAN_NUM])(int, int) = { tasu, hiku, kakeru, waru };

/* ============================= */
/*           main 関数           */
/* ============================= */
int main(int argc, char *argv[])
{
    int i, i2, a=4, b=2, result;  /* ループ、2つの数と演算結果 */
    char resultstr[32] = ERRORSTR;   /* 演算結果の文字列 */
    const char *enzanshi[ENZAN_NUM]={"+", "-", "*", "/"};   /* 演算子4つ */

    for(i=0; i<2; i++){   /* ループ */
        if(i>0) b=0;   /* 2ループ目は b=0 */

        for(i2=0; i2<ENZAN_NUM; i2++){   /* ENZAN_NUM 個の計算 */

          result = (*(p_enzan+i2))(a, b);   /***** 計算 *****/

            /* 0で割ろうとしたかどうか */
            if(waru_zero==GOOD) sprintf(resultstr, "%d", result);
            else                strcpy(resultstr, ERRORSTR);

            /***** 結果出力 *****/
            printf("%d %s %d = %s\n", a, *(enzanshi+i2), b, resultstr);
        }
    }
    return 0;
}



どちらの方がいいと思いましたか? 
人によっていろいろあると思いますが、私は上のほうがぱっと見て分かりやすいから、 どっちかと聞かれたら絶対上のほうがいいです、と答えます! 間違いなく!
なら、テメエもそうしろよと思うかもしれませんが、いつも上のほうがいいとは限らないので、 そこがやっかいなんですね。
ソフトを作っているときには、いずれのために汎用性を持たせる必要が出てくるのではないか、 などと考えると、下のようになってしまいがちなんですね。

なんだかんだといろいろと語っているみたいだが、結局はただ単に、四則演算のプログラムに #defineとか、enumとか、「(条件) ? 真 : 偽」とか、マクロ関数とか、関数ポインタとか、 文字列処理関数とか を使ってみたかっただけじゃないんかと。 それを公開したかっただけじゃないのかと、問い詰めないでいただきたい。。。
同じお題で、もっとひねくれたソース大募集 (^-^;
戻る