プログラミング作法
               分かりやすいソースコード
                   beatle




13年3月16日土曜日
自己紹介

              • mixC++では2011年冬から活動
              • C++/C#が好き
              • プログラミング教育の研究


13年3月16日土曜日
プログラミング作法

              • ブライアン・カーニハン
              • 当たり前だが重要なこと
              • 可読性・保守性


13年3月16日土曜日
メニュー

              • 命名
              • スタイル
              • コメント
              • 移植性

13年3月16日土曜日
命名

              • 「プログラミングは『名前』が9割。」
               あるブログより

              • 良い名前 ≒ 良いプログラム


13年3月16日土曜日
命名規則

              • 全体で統一する
              • ルールの内容自体は重要でない
              • PascalCase
               camelCase
               snake_case



13年3月16日土曜日
変数名

              •   長く、説明的な名前                                  グローバル変数
                    // 現在の入力キューの長さ
                    int npending = 0;

              • 短く、簡潔な名前                                          ローカル変数
                    for (i = 0; i < nelems; i++)
                    for (theElementIndex = 0;
                            theElementIndex < numberOfElements;
                            theElementIndex++)




13年3月16日土曜日
関数名
              • 「動詞+名詞」が基本
               • putchar
               • getTime
              • 真偽値を返す関数
                 if (check_digit(c)) ...

                 if (is_digit(c)) ...

13年3月16日土曜日
スタイル

              • 全体で統一する
              • ルールの内容自体は重要でない
              • K&R
               BSD/Allman
               GNU



13年3月16日土曜日
自然な形の式

              • 音読するつもりで書く
              • 否定は分かりにくい
               if (!(block_id < actblks) || !(block_id >= unblocks))
                   ...

               if ((block_id >= actblks) || (block_id < unblocks))
                   ...




13年3月16日土曜日
かっこを使おう

              • 演算子の優先順位は分かりにくい
              • 本来不要な場所にも付ける
               leap_year = y % 4 == 0 && y % 100 != 0 || y % 400 == 0;

               leap_year = ((y%4 == 0) && (y%100 != 0)) || (y%400 == 0);




13年3月16日土曜日
慣用句と一貫性
              i = 0;
              while (i <= n-1)
                  array[i++] = 1.0;

              for (i = n; --i >= 0; )
                  array[i] = 1.0;

              for (i = 0; i < n; i++)
                  array[i] = 1.0;       ループの慣用句!



13年3月16日土曜日
慣用句と一貫性
              • 他にも様々な慣用句がある
              • リストのトラバース
               for (p = list; p != NULL; p = p->next)



              • 無限ループ
               for (;;)
               while (1)

13年3月16日土曜日
悪いコメント1
              • 当たり前のことはいちいち書くな
               /* SUCCESS を返す */
               return SUCCESS;


               /* ゼロエントリカウンタをインクリメント */
               zerocount++;




13年3月16日土曜日
悪いコメント2
              • 悪いコードにコメントをつけるな
              /* "result"が0ならマッチするものが見つかったので真を返す
                 そうでなければ"result"はゼロ以外なので偽を返す */

              printf("*** isword returns !result = %dn", !result);
              return(!result);


              printf("*** isword returns matchfound = %dn", matchfound);
              return matchfound;


                       コメント > コードなら怪しい
13年3月16日土曜日
悪いコメントその他


              • コードと矛盾したコメント
              • 読者の混乱を増大させるコメント


13年3月16日土曜日
良いコメント1
              • グローバルデータにコメント
               • 必要に応じて参照されるメモ
               struct Status { /* プレフィクス+サフィックスリスト */
                   char *pref[NPREF]; /* プレフィクス用の単語 */
                   Suffix *suf;       /* サフィックスのリスト */
                   State *next;       /* ハッシュテーブル中の次の項目 */
               };




13年3月16日土曜日
良いコメント2
              • 関数にコメント
               • 関数が全体として何をするか
               // random: [0..r-1]の範囲の整数を返す
               int random(int r)
               {
                   return (int)(Math.floor(Math.random()*r));
               }




13年3月16日土曜日
移植性
              • 自分の環境だけで動けばいい?
              • 自分の環境だって変わる!
              • 移植性向上の労力
                →優れたプログラミング




13年3月16日土曜日
標準に固執する

              • 言語の標準に従う
               • ANSI-C, C99, C++11 ...
              • 標準ライブラリを使う
               • stdio.h, iostream, STL ...

13年3月16日土曜日
条件コンパイル
              • 条件コンパイルは避けよう
               • 全組合せでテストできますか?
              #ifdef _MAC
                  printf("This is Macintoshr");
              #else
                  ほかのシステムではこの文で構文エラー
              #endif




13年3月16日土曜日
まとめ

              • 命名:説明的な名前 vs 簡単な名前
              • スタイル:慣用句で見やすく!
              • コメント:整合性を意識
              • 移植性:良いプログラムへの道

13年3月16日土曜日
命名するということ

              • 名前を付ける
               =抽象化
               =プログラミング

              • 例えば、配列のコピー

13年3月16日土曜日
処理を埋め込む
        int main(void)
        {
            char buf[16], data[N];
            int block = 0, i;
            ...

              // 16バイトずつ読み込んで、dataに格納
              while (1) {
                  fread(buf, 1, sizeof(buf), fp);
                  if (feof(fp)) break;
                  for (i = 0; i < sizeof(buf); i++)
                      data[block * sizeof(buf) + i] = buf[i];
                  block++;
              }
        }

13年3月16日土曜日
関数に分ける
        int main(void)
        {
            char buf[16], data[N];
            int block = 0, i;
            ...

              // 16バイトずつ読み込んで、dataに格納
              while (1) {
                  fread(buf, 1, sizeof(buf), fp);
                  if (feof(fp)) break;
                  copy_array(data + block * sizeof(buf),
                             buf,
                             sizeof(buf));
                  block++;
              }
        }
13年3月16日土曜日
// 16バイトずつ読み込んで、dataに格納
              while (1) {
                  fread(buf, 1, sizeof(buf), fp);
                  if (feof(fp)) break;
                  for (i = 0; i < sizeof(buf); i++)
                      data[block * sizeof(buf) + i] = buf[i];
                  block++;

                                      抽象化
              }


                // 16バイトずつ読み込んで、dataに格納
                while (1) {
                    fread(buf, 1, sizeof(buf), fp);
                    if (feof(fp)) break;
                    copy_array(data + block * sizeof(buf),
                               buf,
                               sizeof(buf));
                    block++;
                }


13年3月16日土曜日
ラベル付けは大事!!

              ご清聴ありがとうございました




13年3月16日土曜日

プログラミング作法

  • 1.
    プログラミング作法 分かりやすいソースコード beatle 13年3月16日土曜日
  • 2.
    自己紹介 • mixC++では2011年冬から活動 • C++/C#が好き • プログラミング教育の研究 13年3月16日土曜日
  • 3.
    プログラミング作法 • ブライアン・カーニハン • 当たり前だが重要なこと • 可読性・保守性 13年3月16日土曜日
  • 4.
    メニュー • 命名 • スタイル • コメント • 移植性 13年3月16日土曜日
  • 5.
    命名 • 「プログラミングは『名前』が9割。」 あるブログより • 良い名前 ≒ 良いプログラム 13年3月16日土曜日
  • 6.
    命名規則 • 全体で統一する • ルールの内容自体は重要でない • PascalCase camelCase snake_case 13年3月16日土曜日
  • 7.
    変数名 • 長く、説明的な名前 グローバル変数 // 現在の入力キューの長さ int npending = 0; • 短く、簡潔な名前 ローカル変数 for (i = 0; i < nelems; i++) for (theElementIndex = 0; theElementIndex < numberOfElements; theElementIndex++) 13年3月16日土曜日
  • 8.
    関数名 • 「動詞+名詞」が基本 • putchar • getTime • 真偽値を返す関数 if (check_digit(c)) ... if (is_digit(c)) ... 13年3月16日土曜日
  • 9.
    スタイル • 全体で統一する • ルールの内容自体は重要でない • K&R BSD/Allman GNU 13年3月16日土曜日
  • 10.
    自然な形の式 • 音読するつもりで書く • 否定は分かりにくい if (!(block_id < actblks) || !(block_id >= unblocks)) ... if ((block_id >= actblks) || (block_id < unblocks)) ... 13年3月16日土曜日
  • 11.
    かっこを使おう • 演算子の優先順位は分かりにくい • 本来不要な場所にも付ける leap_year = y % 4 == 0 && y % 100 != 0 || y % 400 == 0; leap_year = ((y%4 == 0) && (y%100 != 0)) || (y%400 == 0); 13年3月16日土曜日
  • 12.
    慣用句と一貫性 i = 0; while (i <= n-1) array[i++] = 1.0; for (i = n; --i >= 0; ) array[i] = 1.0; for (i = 0; i < n; i++) array[i] = 1.0; ループの慣用句! 13年3月16日土曜日
  • 13.
    慣用句と一貫性 • 他にも様々な慣用句がある • リストのトラバース for (p = list; p != NULL; p = p->next) • 無限ループ for (;;) while (1) 13年3月16日土曜日
  • 14.
    悪いコメント1 • 当たり前のことはいちいち書くな /* SUCCESS を返す */ return SUCCESS; /* ゼロエントリカウンタをインクリメント */ zerocount++; 13年3月16日土曜日
  • 15.
    悪いコメント2 • 悪いコードにコメントをつけるな /* "result"が0ならマッチするものが見つかったので真を返す そうでなければ"result"はゼロ以外なので偽を返す */ printf("*** isword returns !result = %dn", !result); return(!result); printf("*** isword returns matchfound = %dn", matchfound); return matchfound; コメント > コードなら怪しい 13年3月16日土曜日
  • 16.
    悪いコメントその他 • コードと矛盾したコメント • 読者の混乱を増大させるコメント 13年3月16日土曜日
  • 17.
    良いコメント1 • グローバルデータにコメント • 必要に応じて参照されるメモ struct Status { /* プレフィクス+サフィックスリスト */ char *pref[NPREF]; /* プレフィクス用の単語 */ Suffix *suf; /* サフィックスのリスト */ State *next; /* ハッシュテーブル中の次の項目 */ }; 13年3月16日土曜日
  • 18.
    良いコメント2 • 関数にコメント • 関数が全体として何をするか // random: [0..r-1]の範囲の整数を返す int random(int r) { return (int)(Math.floor(Math.random()*r)); } 13年3月16日土曜日
  • 19.
    移植性 • 自分の環境だけで動けばいい? • 自分の環境だって変わる! • 移植性向上の労力  →優れたプログラミング 13年3月16日土曜日
  • 20.
    標準に固執する • 言語の標準に従う • ANSI-C, C99, C++11 ... • 標準ライブラリを使う • stdio.h, iostream, STL ... 13年3月16日土曜日
  • 21.
    条件コンパイル • 条件コンパイルは避けよう • 全組合せでテストできますか? #ifdef _MAC printf("This is Macintoshr"); #else ほかのシステムではこの文で構文エラー #endif 13年3月16日土曜日
  • 22.
    まとめ • 命名:説明的な名前 vs 簡単な名前 • スタイル:慣用句で見やすく! • コメント:整合性を意識 • 移植性:良いプログラムへの道 13年3月16日土曜日
  • 23.
    命名するということ • 名前を付ける =抽象化 =プログラミング • 例えば、配列のコピー 13年3月16日土曜日
  • 24.
    処理を埋め込む int main(void) { char buf[16], data[N]; int block = 0, i; ... // 16バイトずつ読み込んで、dataに格納 while (1) { fread(buf, 1, sizeof(buf), fp); if (feof(fp)) break; for (i = 0; i < sizeof(buf); i++) data[block * sizeof(buf) + i] = buf[i]; block++; } } 13年3月16日土曜日
  • 25.
    関数に分ける int main(void) { char buf[16], data[N]; int block = 0, i; ... // 16バイトずつ読み込んで、dataに格納 while (1) { fread(buf, 1, sizeof(buf), fp); if (feof(fp)) break; copy_array(data + block * sizeof(buf), buf, sizeof(buf)); block++; } } 13年3月16日土曜日
  • 26.
    // 16バイトずつ読み込んで、dataに格納 while (1) { fread(buf, 1, sizeof(buf), fp); if (feof(fp)) break; for (i = 0; i < sizeof(buf); i++) data[block * sizeof(buf) + i] = buf[i]; block++; 抽象化 } // 16バイトずつ読み込んで、dataに格納 while (1) { fread(buf, 1, sizeof(buf), fp); if (feof(fp)) break; copy_array(data + block * sizeof(buf), buf, sizeof(buf)); block++; } 13年3月16日土曜日
  • 27.
    ラベル付けは大事!! ご清聴ありがとうございました 13年3月16日土曜日