2018年12月03日

空行はブロックの前ではなく読ませたい文の前に入れる - リーダブル コード(56)

今回紹介する方針は非常に重要です。 プログラムのコードを書くときの方針として、今までの常識としていた方針が間違っていた、目から鱗が落ちるような方針を紹介します。

次に示すように処理内容が10行近く以上の長い関数があるとします。

void FunctionA() {
  OptionClass* option = new OptionClass;
  option.Source = "C:\\FolderA";
  option.Destination = "C:\\FolderB";
  SpecialCopy( option );
  option.Source = "C:\\FolderAA";
  option.Destination = "C:\\FolderBB";
  SpecialCopy( option );
}


上記の関数には7つの文があります。 このように処理内容が長いときは、いくつかの処理ブロックに分けることができます。

処理ブロックを分ける行に空行を入れてみましょう。 すると、2つのコピーであることがよく分かります。

void FunctionA( int in_a ) {
  OptionClass* option = new OptionClass;
  option.Source   = "C:\\FolderA";
  option.Destination = "C:\\FolderB";
  SpecialCopy( option );

  option.Source   = "C:\\FolderAA";
  option.Destination = "C:\\FolderBB";
  SpecialCopy( option );
}


しかし、これだけでは、2つブロックがあることが分かるだけで、2つのコピーをしていることまでは、すぐに理解することができません。 なぜなら、ブロックの最後まで読まなければ、コピーであることを知ることができないからです。

そこで、コピーがある文の前に空行を入れてみましょう。 つまり、読ませたい文の前に空行を入れるのです。

void FunctionA( int in_a ) {
  OptionClass* option = new OptionClass;
  option.Source   = "C:\\FolderA";
  option.Destination = "C:\\FolderB";

  SpecialCopy( option );
  option.Source   = "C:\\FolderAA";
  option.Destination = "C:\\FolderBB";

  SpecialCopy( option );
}


始めのうちは、2つ目のブロックに3つ目のブロックの内容が混ざっていることが気になるかもしれません。 ただ、そう思うのは、空行がブロックの区切りとして読むことに慣れている状態のとき、かつ、処理内容をすべて理解していて、ブロックが正しく分けられていることを監査している状態のときだけです。 文章を読んで理解しようとしているときではありません。

普段、文章を読んでいて、このあたりに期待する情報が書かれていないだろうなと思ったときは、今読んでいる文を読み飛ばします。 これは、文書でもコードでも同じで、誰でもすることです。 数行読み飛ばすこともありますが、ほとんどの場合、次の段落まで読み飛ばすことでしょう。

つまり、空行の次の行から読み始めるのです。 この行動は、どんな人でも自然に行うことなので、空行の次が重要であるという知識やルールは必要ありません。 読む人のルールが少なくなるので、(書くときの)ルールとして優れています。

読ませたい文の前に空行を入れることの有用性に気づいたら、ブロックに分けることの有用性が相対的に低くなるため、ブロックを分ける位置に空行が無いことに目くじらを立てなくなります。 ルールのためのルールであってはなりません。

それでも納得できない人のために、ためしに、ブロックを分ける行にも空行を入れて、ブロックの区切りを明示してみることにしましょう。

void FunctionA( int in_a ) {
  OptionClass* option = new OptionClass;
  option.Source   = "C:\\FolderA";
  option.Destination = "C:\\FolderB";

  SpecialCopy( option );

  option.Source   = "C:\\FolderAA";
  option.Destination = "C:\\FolderBB";

  SpecialCopy( option );
}


上記のコードを素早く読んでみてください。 目に入るのは、SpecialCopy 関数の呼び出し2つと、option.Source 変数への代入になると思います。 コードを読んで理解しようとしているときは、目に入ったコードから情報を入手することになります。 果たして、option.Source 変数への代入するという情報は概要を知るうえで重要でしょうか。 いいえ、むしろ邪魔な情報になります。

とはいえ、少し余分な情報が増えるだけなので、あまり実害はありません。 ですので、ブロックの区切りに空行を入れるべきではないというルールは必要ありません。 その代わり、ブロックの区切りに空行を入れるというルールがあるのなら、そのルールを無くすのがよいでしょう。

なお、ルールを少なくすべきというのは、人間が従うべきルールが少ないほうがいいというのであって、機械にとっては、多くの有用なルールや方針に従わせたほうがいいです。 機械が対応できない分を人間がしようと思っても限界があります。 多くのルールは、必要性な理由がありそうだというだけで、実際には有用ではなく作業の完了を遅らせることが多いので、ルールの棚卸しが重要です。

sage_p at 01:50│Comments(0) プログラミング 

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔