プログラミング作法

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

プログラミング作法(プログラミングさほう、: Programming style)は、プログラムソースコードを書くときの規則やガイドライン群を指す。

この分野の古典は、1970年代の書籍『プログラム書法』(The Elements of Programming Style)である。時代が古いため、例はもっぱらFORTRANである。

特定のプログラムで使われているプログラミング作法は、単にその作者の好みの問題という場合もあるし、企業や組織が開発したものなら、その組織の決めたコーディング標準コーディング規約によるものという場合もある。プログラミング作法はプログラミング言語(あるいは言語ファミリ)に依存することが多いが、一部の規則は多くの言語に通用する。(例えば、C言語のソースコードで適切と思われる作法は、BASICのソースコードには通用しない、などといった事柄である)

よい作法の要素[編集]

よい作法を明確に定めるのは困難である。しかし、多くのプログラミング作法に共通する要素はいくつか存在する。プログラミング作法の一部とされるのは、

  • 字下げを含めたソースコードのレイアウト
  • 演算子やキーワードの前後での空白の使用
  • キーワードと変数名の区別の明確化
  • ユーザー定義識別子(関数名・変数名など)のスペリングの作法
  • コメントの使用と作法
  • プログラミング構文の使用法や使用禁止(例えばgoto文

などである。

いずれにせよ、良い作法が志向するのはプログラムの明瞭な表現である。従ってどんな言語のどんな流儀においても、

  • 間違ったプログラムが明らかに間違って見える
  • 正しいプログラムはその正しさを検証する事が容易となる

といったような、基本的な理念が共有される。

コードの見た目[編集]

プログラミング作法は一般にソースコードの見た目を扱い、プログラムの可読性の向上を目指している。しかし、ソースコードのフォーマットを自動的に行うソフトウェアを使う場合、見た目に関してプログラマが気を使うべきは命名法・論理・高度な技法などということになる。実際、コンピュータにソースコードのフォーマットを任せると時間の節約になり、一種の宗教論争をしなくとも企業全体で1つの標準に従える。

字下げ[編集]

字下げスタイルは、制御フローやコードのブロックを識別し易くする。字下げによってコードの論理ブロックを識別するプログラミング言語では、字下げスタイルはプログラムの動作そのものに影響する。他の言語、特に括弧でブロックを示す言語では、字下げスタイルは動作には影響しない。しかし一貫した論理的な字下げスタイルを採用すると、コードが読みやすくなる。次のコードを比較してみよう。

if (hours < 24 && minutes < 60 && seconds < 60)
{
   return true;
}
else
{
   return false;
}
if (hours < 24 && minutes < 60 && seconds < 60) {
   return true;
} else {
   return false;
}
   if (hours < 24 && minutes < 60 && seconds < 60) {
return true;
   }
   else {
return false;
   }

上の2つの例の方が最後の例よりも読みやすいと感じる人が多い。字下げスタイルは複数の構文が入れ子になっている場合に特に重要となる。

もちろん、これらの例は読みやすさを比較するためにわざとこのように書かれており、次のような書き方がもっと簡単である(ただし、次のような書き方が出来ない言語も存在することに、注意が必要である)。

return hours < 24 && minutes < 60 && seconds < 60;

Python は字下げを制御構造を示すのに使っており、正しい字下げは「必須」である。そうすることで括弧を不要とし、字下げスタイルも一定になるので、可読性が向上する。問題は Python のコードの一部を別の箇所にコピーする場合である。その場合、字下げレベルが不適切になる可能性が高い。これを手で直すのは手間がかかるが、一部のテキストエディタIDEには自動的に字下げレベルを合わせる機能がある。また、Python のコードをウェブページなどに掲載する場合、空白を無視されると困ったことになる。ウェブページの場合、Python のコードは "<code> ... </code>" というHTMLタグで囲み、適切に表示されるようにする。

Haskellも同様のオフサイドルールにより、ブロックを識別する。ただし Python とは異なり、Haskell では括弧とセミコロンを代わりに使うこともできる。

桁位置合わせ[編集]

隣接する行の桁位置を合わせると、誤字を見つけやすくなることがある。例えば次のコードを比較してみよう。

$search = array('a', 'b', 'c', 'd', 'e');
$replacement = array('foo', 'bar', 'baz', 'quux');
$search      = array('a',   'b',   'c',   'd',   'e');
$replacement = array('foo', 'bar', 'baz', 'quux');

後者の例では、前者の例で必ずしも明らかでなかった次の2点が明らかとなっている。

  • search と replacement は何らかの関連があり、対応している。これらは別個の無関係な変数ではない。
  • search の方が項目が1つ多い。これがバグなら、より目立つようになっている。

言語によっては桁位置合わせで関連性を示すよりも、構造体などで明確に関連性を示したほうが良い。また、コードを修正する場合は通常よりも余計な作業が発生するため、メンテナンスが必要なコードでの桁位置合わせは嫌われることが多い。あるいは、単に面倒ということもあり、実施されないこともある。

空白[編集]

自由形式言語では空白を完全に無視するものが多い。コードのレイアウトで空白をうまく使うのも、よいプログラミング作法の一部と見なされる。

次のC言語のコードを比較してみよう。

int count;
for(count=0;count<10;count++)
{
  printf("%d",count*count+count);
}
int count;
for (count = 0; count < 10; count++)
{
  printf("%d", count * count + count);
}

この2つのコードは、どちらがより良い表現と言えるのかはかなり個人差が大きい。空白を多めに取るスタイルでは、演算子の関係などは明瞭になるものの、一つの行としてのまとまりを欠く。「地の行では空白を入れるが、括弧内は詰める」といった折衷的なスタイルなどもあり得る。

C言語ファミリでは、行の途中でのタブ文字使用の禁止が推奨される。なぜならテキストエディタの種類や設定によって、タブ文字をどういう幅で表示するかが異なるためである。もっとも、等幅フォントを使用しない作法では、タブ幅はもはやインデントレベル以外の意味を持たなくなるため、この限りではない。

命名、論理、高度な技法[編集]

適切な変数名[編集]

変数名を適切に選択するのがよい作法の要である。不適切な変数名はコードを読みにくくし、理解しにくくする。

例えば次の擬似コードを見てみよう。

get a b c 
if a < 24 and b < 60 and c < 60
  return true
else
  return false

変数名の選択方法がよくないため、この関数のコードは何をしているのか理解しにくい。しかし次のように変数名を設定すると、より分かりやすくなる。

get hours minutes seconds 
if hours < 24 and minutes < 60 and seconds < 60
  return true
else
  return false

コードの意味が分かりやすくなった。すなわち「与えられた時刻情報が24時間制に合っているなら true、合っていないなら false を返す」である。

適切な変数名の選択は、プログラム全体で一貫性を持った命名を行うことで、さらにその効果を高める。こうした統一的な命名規則としてはハンガリアン記法が有名である。

判断構造におけるブーリアン値[編集]

プログラマによっては、上のようなブーリアン型の計算結果と判断が単純に対応した判断構造は、冗長すぎるし間違いやすいと考える。従って、計算結果そのものを次のように返すのがよいと考える人もいる。

return hours < 24 && minutes < 60 && seconds < 60;

これらの違いは純粋にスタイルと構文上のことであって、最近のコンパイラはどちらの形式であっても同じオブジェクトコードを生成する。

逆に前者の作法を好む場合もある。その理由としてデバッグの容易さが挙げられる。ブーリアン型の条件式の中で変数への代入も行われる場合、その計算後に変数の値をデバッガで確認したいとすると、前者の方が確認が容易である。後者では、その行の実行完了後に停止させると関数から抜けてしまっており、値を確認できない(命令単位のステップ実行なら確認可能)。

ループと制御構造[編集]

ループの制御構造の論理的使用もよいプログラミング作法の一部である。適切なループ方法により可読性が向上する(命令型プログラミング言語の場合)。例えば、次の擬似コードを見てみよう。

 count = 0
 while count < 5
   print count * 2
   count = count + 1
 endwhile

このコードは変数名や字下げは問題ないが、次のようにfor文を使った方がずっと読みやすい。

 for count = 0, count < 5, count = count + 1
   print count * 2

多くの言語では、このようなパターンは次のように短縮できる。

 for count = 0 to 5
   print count * 2
 print "Ended loop";

中括弧を多用する言語では、制御構造構文には中括弧を付与することを規約とするのが一般的である。

 for (count = 0 to 5) {
   print count * 2;
 }
 print "Ended loop";

これにより、次のように誤ってセミコロンをつけたときのような発見に時間のかかるバグを回避する。

 for (count = 0 to 5);
   print count * 2;
 print "Ended loop";

あるいは、次のようにループ内で実行する行を増やしたときも中括弧を予めつけておけば、バグを回避できる。

 for (count = 0 to 5)
   log "loop reached " + count;
   print count * 2;
 print "Ended loop";

さらにプリプロセッサが続く行を削除してしまった場合にも対応できる。

 for (count = 0 to 5)
 print "Ended loop";

リスト[編集]

行ごとに何らかのリストのアイテムを列挙する場合、アイテムとアイテムを分離する記号(セパレータ)を最後のアイテムにも付与するのがよいとされる(C言語のようにそのような書き方が文法的に間違っていない場合)。

  $stuff = array(
    'item1',
    'item2',
    'item3',  /* 最後にもカンマを付与 */
  );
  while (1) {
    'command1';
    'command2';
    'command3';  /*  最後にもセミコロンを付与 */
  }

これにより、行の並べ替えをした場合やアイテムを追加した場合に、セパレータを入れ忘れることによるバグを回避する。

関連項目[編集]

外部リンク[編集]

各種言語のコーディング規約[編集]

プロジェクトにおけるコーディング規約[編集]