まずは、関数分割から

昨日書いたスコープの話は難しかったようなので、今日はもっと戻って関数分割の話をしてみた。考え方は非常に単純だと思うので、ここでつまずくような人はプログラムに向いてないのではないか?あきらめて違う職種に就くのも手じゃないのかとも思う。

基本

1〜10までの数字を足すプログラムがあったとする。

int main(void)
{
    int i, sum;

    sum = 0;
    for(i=1;i<=10;i++) {
        sum = sum + i;
    }

    printf("%d", sum);

    return 0;
}

ちょっと拡張

これに、変更があって1〜10までと1〜100までの演算結果が必要になった。

int main(void)
{
    int i, sum;

    sum = 0;
    for(i=1;i<=10;i++) {
        sum = sum + i;
    }

    printf("%d", sum);

    sum = 0;
    for(i=1;i<=100;i++) {
        sum = sum + i;
    }

    printf("%d", sum);

    return 0;
}

さらに拡張

これに、変更があって1〜10までと1〜100までと1〜1000までと・・・・の演算結果が必要になった。

int main(void)
{
    int i, sum;

    sum = 0;
    for(i=1;i<=10;i++) {
        sum = sum + i;
    }
    printf("%d", sum);

    sum = 0;
    for(i=1;i<=100;i++) {
        sum = sum + i;
    }
    printf("%d", sum);

    sum = 0;
    for(i=1;i<=100;i++) {
        sum = sum + i;
    }
    printf("%d", sum);

    /* 〜省略〜 */
}

これじゃあ、芸がない。

これだと、100まで1000までとか10000までとかなるたびにfor文を記述をしなければならない。これは非常に単純なプログラムだから問題はないけど、難しい処理をしていたらいちいち書くのがめんどくさい。なので、これをfor()の記述をfnc_sum()関数へと分割する。こうすることで、for()の記述がfnc_sum()一行ですむため、すっきり見やすくさらにコード量が減る。

int main(void)
{
    int sum;

    sum = fnc_sum(10);
    printf("%d", sum);

    sum = fnc_sum(100);
    printf("%d", sum);

    return 0;
}

int fnc_sum(int max)
{
    int i, sum;
    sum = 0;
    for(i=1;i<=max;i++) {
        sum = sum + i;
    }

    return sum;
}

さらに利点

関数分割にはコードを記述する量が減るだけではなくて、修正箇所を一箇所にまとめることが出来るという利点もある。どういうことかというと、今までは0〜最大値までの足し算を算出するというものだったが、0からではなく最小値を自分で決めれるように変更が発生したとしよう。この場合、もし関数分割をしていなかったら出てくる箇所全てを変更しなければならないが、関数分割していると変更箇所は一箇所ですむため非常に簡単。

int main(void)
{
    int sum;

    sum = fnc_sum(0, 10);
    printf("%d", sum);

    sum = fnc_sum(30, 100);
    printf("%d", sum);

    return 0;
}

int fnc_sum(int min, int max)
{
    int i, sum;
    sum = 0;
    for(i=min;i<=max;i++) {
        sum = sum + i;
    }

    return sum;
}

総評

おんなじ様なことをやる処理は関数分割をするべき。コードの記述量とコードの編集量を削減できる。ただし、ひとつの関数でやることは明確にひとつのことのみをやるほうがいいと思う。その考えで行くと、fnc_sum()はあくまで合計値を求める関数として設計したため、printf()を含めずに記述している。