プログラミング

プログラミング作法とコーディング基準

インデンテーションとネスティング

次に示すのは,1から100まで数えていって,3の倍数のときに「アホになる」,5の倍数のときに「犬になる」と表示するアルゴリズムです.

変数 i を宣言 i ← 1 (iに1を代入) i が 100 になるまで繰り返す | もし i が 3 で割り切れたら | | 「アホになる」と表示する | もし i が 5 で割り切れたら | | 「犬になる」と表示する | i ← i + 1

iが100になるまで繰り返すのはどの範囲か,iが割り切れたときに処理を行うのはどの範囲かを,縦棒とインデントを使って表現しました.もし,インデントを使わないとこうなります.

変数 i を宣言 i ← 1 (iに1を代入) i が 100 になるまで繰り返す |もし i が 3 で割り切れたら ||「アホになる」と表示する |もし i が 5 で割り切れたら ||「犬になる」と表示する |i ← i + 1

インデントを使わなくても,プログラムの構文として正しければ動作します.しかし,後からプログラムを見直すときや,他の人にプログラムを読んでもらう場合,インデントをした方が読みやすくなります(可読性の向上).インデントは空白文字でも行えますが,タブを使うと便利です.

Caution

多くのプログラミング言語では,インデントに全角スペースを使うとエラーになります.スペースを使うときは半角にして下さい.

続いて,入力された数字(西暦)がうるう年かどうかを判定するアルゴリズムを示します(うるう年は西暦が4の倍数のときですが,100の倍数のときは違います;ただし,400の倍数のときはうるう年になります).

y ← キーボードの数値(入力された値をyに代入) もし y が 4 で割り切れたら | もし y が 100 で割り切れたら | | もし y が 400で割り切れたら | | | 「うるう年です」 | | そうでなければ | | | 「うるう年ではありません」 | そうでなければ | 「うるう年です」

繰り返しや条件分岐の範囲の中に,さらに繰り返しや条件分岐を入れることをネスト(入れ子)と言います.ただし,あまりにもネストが深すぎると読みにくくなります.

変数 y を宣言 y ← キーボードの数値(入力された値をyに代入) もし ( y が 400 で割り切れたら ) または ( y が 4 で割り切れて 100 で割り切れないならば ) | 「うるう年です」 そうでなければ | 「うるう年ではありません」

このようにして,うまく条件文の書き方を工夫すれば,ネストを必要以上にしなくて済みます.

命名標準・使用禁止命令

変数やサブルーチンの名前は,基本的には自由につけられます.ただし,一定の規則をもって名前をつけた方が,後から見直すときに読みやすくなります.また,複数の人と共同でプログラムを書くときは,名前の付け方(ローマ字を使うのか英単語を使うのか・アルファベットの大文字と小文字の使い分け)を統一しておくべきです.

なお,どのプログラミング言語にも予約語があります.例えば,C言語では条件分岐を表すifや,繰り返しを表すfor・while等は予約語なので,変数やサブルーチンの名前として使えません.

次に,使用禁止命令について触れます.と言っても,プログラマのスタンスやプログラミング言語による面が大きく,一概に「これが悪い」と言い切れるものはありません.ここでは,C言語を例にして説明します.

まず,無限ループgoto文について触れます.

int main(void) { while(1) { // 条件が常に成立するので無限ループになる (色々な処理が書かれている) if( owari == 1 ) { // 終わり goto owari; // ここから } } owari: // ここにジャンプ return 0; }

私の経験上,このような書き方はゲームプログラムに多かったです.ゲームの処理(キャラクターを動かしたり当たり判定を行う)は,プレーしている間はずっと続くので,繰り返し文を使うのが楽だったからです.しかし,この書き方に慣れすぎて,何でもかんでも無限ループとgoto文を使うのはおすすめできません.

上記のプログラムから無限ループとgoto文を取り去った書き方を示します.

int main(void) { int owari = 0; // 変数 owari に 0 を代入 while( owari != 1 ) { // 変数 owari が 1 でなかったら (色々な処理が書かれている) if( (何らかの判定) ) { // 終わり owari = 1; // 変数 owari に 1 を代入 } } return 0; }

ところで,変数owariは整数型ですが,何ビットかはシステムによって異なります.つまり,動かすシステムによって格納できる値の範囲が変わるため,開発環境ではうまく動作するものが,別の環境では誤動作することもあり得ます.

C言語の例でいえば,short intやlong intのように,何ビットの整数型を使うのか明示すれば,このような心配はなくなります.

プログラムの効率性の向上

次に示すのは,入力された数が素数か判定するアルゴリズムです.

変数 x を宣言 x ← キーボードの数値(入力された値をxに代入) 変数 i を宣言 i ← 1 (iに1を代入) i が x になるまで繰り返す | もし x が 1回でも i で割り切れたら | | 「素数ではありません」と表示する | そうでなければ | | 「素数です」と表示する | i ← i + 1

これでも正しく動作しますが,繰り返しの回数に無駄があります.素数は1とその数のみで割り切れる数です.9は3で割り切れるので素数ではありませんが,9の半分を切り上げたもの(9÷2=4.5より5になります)より大きい数字で割り切れることはありません.同様に,800は半分の400で割り切れますが,401以上の数で割り切れることはありません.

つまり,iをx(入力された数)まで繰り返す必要はありません.実際には,xの半分の値まで繰り返せば結構です.繰り返し回数が減ることにより,無駄な処理がなくなり,効率が良くなります.

次の例を示します.

変数 x と y を宣言 x ← 1 y ← 1 x が 10 になるまで繰り返す | y が 10 になるまで繰り返す | | もし x が 2 で割り切れて y が 2 で割り切れるなら | | | 「x と y の両方が 2 で割り切れます」 | y ← y + 1 x ← x + 1

xとyの両方が偶数で割り切れるときにメッセージを表示しています.このとき,全体の繰り返し回数は10×10=100回です.xの値が1つずつ増えるとyが1から10まで10回繰り返しますが,両方とも偶数の必要があるなら,xが奇数のときにyの繰り返しは不要です.

変数 x と y を宣言 x ← 1 y ← 1 x が 10 になるまで繰り返す | もし x が 2 で割り切れるなら | | | y が 10 になるまで繰り返す | | | | もし y が 2 で割り切れるなら | | | | | 「x と y の両方が 2 で割り切れます」 | | | y ← y + 1 x ← x + 1

同じ結果がより少ない繰り返し回数で得られます.xが奇数のときはyの繰り返しを行わないため,全体の繰り返し回数は50回に減ります.

プログラムの保守性の向上

次に示すのは,30人の生徒を受け持つ先生の,成績処理プログラムの一部です.

// student[1]からstudent[30]に成績が入っている 変数 sum と avg と i を宣言 sum ← 0 i ← 1 i が 30 になるまで繰り返す | sum ← sum + student[i] avg ← sum / 30 平均点として avg を表示

実際には科目別の処理等も考えられます.ここで,生徒の人数が30人から38人に変わった場合,上のプログラムにある30を全て38に変える必要があります.しかし,長いプログラムになると,全ての場所を変えるのは面倒ですし,確認漏れも発生しやすくなります.

そこで,次のように改良します.

// student[1]からstudent[30]に成績が入っている 変数 sum と avg と i と numを宣言 num ← 30 sum ← 0 i ← 1 i が num になるまで繰り返す | sum ← sum + student[i] avg ← sum / num 平均点として avg を表示

こうすれば,生徒数が変わっても,始めのnum ← 30の1ヶ所を変えるだけで済みます.

プログラム構造

次に示すのは,1から20,1から30,1から50までの自然数の和を表示するアルゴリズムです.

// student[1]からstudent[30]に成績が入っている 変数 sum と i と numを宣言 i ← 0 sum ← 0 i が 20 になるまで繰り返す | i ← i + 1 | sum ← sum + i iを表示する i ← 0 sum ← 0 i が 30 になるまで繰り返す | i ← i + 1 | sum ← sum + i iを表示する i ← 0 sum ← 0 i が 50 になるまで繰り返す | i ← i + 1 | sum ← sum + i iを表示する

このアルゴリズムを見ると,同じような処理が何度も続いています.同じような処理はサブルーチンとして定義した方が良いです.

// サブルーチンwa(引数:n 戻り値:sum) 変数 i と sum を宣言 i ← 0 sum ← 0 i が n になるまで繰り返す | i ← i + 1 | sum ← sum + i // メインルーチン 変数 k を 宣言 k ← wa(20) kを表示 k ← wa(30) kを表示 k ← wa(50) kを表示

引数と戻り値の詳細な説明は「プログラム言語」の「プログラム言語の制御構造」を参照して下さい.

サブルーチンを適切に使うことで,プログラムの独立性が上がります.仮に,合計を求める部分に誤りがあっても,サブルーチンだけを修正すれば良いので,保守性も上がります.

ウェブプログラミング

ウェブプログラミングでは,サーバ側とクライアント側それぞれで動作するプログラムを作ります.オフラインの状態でクライアント側でプログラミングすることをクライアントサイドプログラミングと言います.一方,オンラインの状態で,サーバ側に設置されているプログラムを直接編集するサーバサイドプログラミングもあります.

ウェブプログラムの多くはブラウザ上で動きますが,サーバとクライアント間の通信が必要となる部分や,サーバ独自の機能を使う場合,サーバサイドプログラミングでないと動作検証ができないことがあります.例えば,サーチエンジンでよく見かける検索機能の確認は,クライアントサイドプログラミングでは困難です.

クライアントサイドプログラミングでウェブアプリケーションの動作を検証する場合,Apacheというウェブサーバソフトウェアを使う方法があります.また,ブラウザはオフライン上でも動作するため,クライアントにブラウザを使う方法(ウェブクライアントまたはHTMLクライアント)もあります.ただし,ブラウザの仕様や機能の制限により,所望の動作検証ができないこともあります.

リッチクライアントは,アプリケーションの実行環境のみを搭載したもので,クライアントサーバシステムのクライアントにあたるファットクライアントと,ウェブクライアントの中間の性質をもちます.

Ajaxは,ブラウザ内で非同期通信とインタフェースの構築等を行う技術の総称で,通信結果に応じて動的にページの一部を書き換えます.