プログラミングを行う際に、効率的かつスムーズにコードを管理するためには、適切なテクニックが必要です。
その中でも、関数の分割とmain関数からの呼び出しは特に重要です。
本記事では、この便利なテクニックについて詳しく解説します。
1. コードの可読性向上
プログラムコードが成長するにつれて、main関数が長大化していくことは避けられません。
しかし、main関数が巨大化するとコードが読みづらくなり、理解が難しくなります。
文章にしても、あまりにも長い文章になると理解が難しくなりますよね。それと同じです。
こういった時、プログラムでは関数に分割することで、コードの意図が明確になり、可読性が向上します。
【main()関数内に全て書いた例】
// main関数の例 int main(void) { // 関数に分割されていない場合 // 以下のような長いコードになる // 得点において以下の処理を行う // 1. 合計点・平均点を出して出力する // 2. 1番高い得点を探して出力する // 3. 1番低い得点を探して出力する int score[5] = {60, 57, 38, 79, 91}; int idx; int goukei; double average; int highScore; int lowScore; // 1. 合計点・平均点を出して出力する goukei = 0; for(idx=0; idx<5; idx++) { goukei += score[idx]; } average = ((double)goukei / 5.0); printf(“goukei : %d¥n”, goukei); printf(“average : %d¥n”, average); // 2. 1番高い得点を探して出力する highScore = score[0]; for(idx=1; idx<5; idx++) { if(highScore < score[idx]) { highScore = score[idx]; } } printf(“high score : %d¥n”, highScore); // 3. 1番低い得点を探して出力する lowScore = score[0]; for(idx=1; idx<5; idx++) { if(lowScore > score[idx]) { lowScore = score[idx]; } } printf(“low score : %d¥n”, lowScore); return 0; }
【main()関数での関数呼び出しの例】
細かい処理コードは関数群に任せるようにします。
main()からは必要な関数を必要な場所で呼び出します。
// main関数での関数呼び出しの例 int main(void) { int score[5] = {60, 57, 38, 79, 91}; function1(score); // 1. 合計点・平均点を出して出力する function2(score); // 2. 1番高い得点を探して出力する function3(score); // 3. 1番低い得点を探して出力する return 0; }
ここで呼び出されている関数群の詳細は次の章で説明します。
2. 再利用性の向上
同じ機能を複数の場所で使用する場合、関数にまとめることでコードの再利用性を高めることができます。
これにより、同じ機能をあちこちに実装する必要がなくなり、コードの冗長性が減少します。
1.のmain()で呼び出している関数群の処理コードを準備します。
// 関数の例 void function1(int *num1) { // 1. 合計点・平均点を出して出力する int goukei; double average; int idx; goukei = 0; for(idx=0; idx<5; idx++) { goukei += num1[idx]; } average = ((double)goukei / 5.0); printf(“goukei : %d¥n”, goukei); printf(“average : %d¥n”, average); } void function2(int *num2) { // 2.1番高い得点を探して出力する int tempScore; tempScore = num2[0]; for(idx=1; idx<5; idx++) { if(tempScore < num2[idx]) { tempScore = num2[idx]; } } printf(“high score : %d¥n”, tempScore); } void function3(int *num3) { // 3.1番低い得点を探して出力する int tempScore; tempScore = num3[0]; for(idx=1; idx<5; idx++) { if(tempScore > num3[idx]) { tempScore = num3[idx]; } } printf(“low score : %d¥n”, tempScore); }
このように、処理別の関数を部品のように準備することにより、呼び出し元であちこちに同じコードを書かなくてはならなくなるものも、関数を呼び出すだけで処理されるようになります。
あちこち書き込むよりも数段わかりやすくなります。
3. デバッグの容易化
関数に分割されたコードでは、特定の機能が誤動作している場合、その関数だけを調査すれば良くなります。
これにより、バグの特定や修正が容易になります。
// バグが発生した場合のデバッグの例 void function1(void) { // バグのあるコードが書かれている // この関数にバグがあるとわかれば、この関数を単体でテストしてバグ修正が可能 } void function2(void) { // 正常なコードが書かれている }
4. テストのしやすさ
関数に分割されたコードは、個々の関数を単体でテストすることができます。
これは開発において非常に重要なポイントで、個々の関数ごとに機能動作確認を行うことができ、関数ごとにバグ発見と修正を行うことができます。
これにより、テスト駆動開発(TDD)の手法を実践しやすくなり、コードの品質向上に役立ちます。
int main(void) { // 本番関数ではなくテスト用関数を動かしたい //function1(); //本番用なのでコメントアウトする //function2(); //本番用なのでコメントアウトする // テスト用の関数をコールする testMain(); } // テストの例 void testMain(void) { testFunction1(); testFunction2(); } void testFunction1(void) { // function1のテストコード } void testFunction2(void) { // function2のテストコード }
5. チームでの作業の効率化
関数に分割されたコードは、複数の開発者が同じコードベースで作業する場合に特に役立ちます。
それぞれの開発者が担当する範囲が明確になるため、コンフリクトの可能性が低下し、作業の衝突を防ぐことができます。
int main(void) { function1(); // Aさんが担当して書いた関数 function2(); // Bさんが担当して書いた関数 function3(); // Cさんが担当して書いた関数 function4(); // Dさんが担当して書いた関数 return 0; } // Aさんが担当して書いた関数 void function1(void) { printf(“This is a function created by A.¥n”); } // Bさんが担当して書いた関数 void function2(void) { printf(“This is a function created by B.¥n”); } // Cさんが担当して書いた関数 void function3(void) { printf(“This is a function created by C.¥n”); } // Dさんが担当して書いた関数 void function4(void) { printf(“This is a function created by D.¥n”); }
6. まとめ
関数の分割とmain(または呼び出し元)からの呼び出しは、プログラミングにおける重要なテクニックであり、コードの管理や保守性を向上させる上で不可欠であり、より複雑なシステムにおいても効率の良いコーディングが実現できます。
ぜひこのテクニックを活用して、より効率的なプログラムを開発してみてください。
キャリア相談サービス coachee
プログラミングに興味のある方、転職に悩んでいる方!
あなたの最大限の特技とメリットを引き出し、より良いキャリアをつむためのコーチングを行ってくれます。転職サイトではなくキャリアップのための相談・コーチングサービスです。
私はどんな仕事に向いている?等相談者の方がメインとなって様々な面からサポートしてくれます。
転職等にお悩みの方は是非一度いかがですか?
コメント